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 BOOL demo_mode = False;
34 static BOOL 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"
55 /****************************************************************************
56 ****************************************************************************/
57 static int enum_index(int value, const struct enum_list *enumlist)
60 for (i=0;enumlist[i].name;i++)
61 if (value == enumlist[i].value) break;
65 static char *fix_backslash(const char *str)
67 static char newstring[1024];
71 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
79 static char *fix_quotes(const char *str)
81 static pstring newstring;
83 size_t newstring_len = sizeof(newstring);
84 int quote_len = strlen(""");
87 if ( *str == '\"' && (newstring_len - PTR_DIFF(p, newstring) - 1) > quote_len ) {
88 strncpy( p, """, quote_len);
99 static char *stripspaceupper(const char *str)
101 static char newstring[1024];
105 if (*str != ' ') *p++ = toupper_ascii(*str);
112 static char *make_parm_name(const char *label)
114 static char parmname[1024];
118 if (*label == ' ') *p++ = '_';
126 /****************************************************************************
127 include a lump of html in a page
128 ****************************************************************************/
129 static int include_html(const char *fname)
135 fd = web_open(fname, O_RDONLY, 0);
138 printf(_("ERROR: Can't open %s"), fname);
143 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
151 /****************************************************************************
152 start the page with standard stuff
153 ****************************************************************************/
154 static void print_header(void)
156 if (!cgi_waspost()) {
157 printf("Expires: 0\r\n");
159 printf("Content-type: text/html\r\n\r\n");
161 if (!include_html("include/header.html")) {
162 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
163 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
167 /* *******************************************************************
168 show parameter label with translated name in the following form
169 because showing original and translated label in one line looks
170 too long, and showing translated label only is unusable for
172 -------------------------------
173 HELP security [combo box][button]
175 -------------------------------
176 (capital words are translated by gettext.)
177 if no translation is available, then same form as original is
179 "i18n_translated_parm" class is used to change the color of the
180 translated parameter with CSS.
181 **************************************************************** */
182 static const char* get_parm_translated(
183 const char* pAnchor, const char* pHelp, const char* pLabel)
185 const char* pTranslated = _(pLabel);
186 static pstring output;
187 if(strcmp(pLabel, pTranslated) != 0)
190 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>",
191 pAnchor, pHelp, pLabel, pTranslated);
195 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
196 pAnchor, pHelp, pLabel);
199 /****************************************************************************
201 ****************************************************************************/
202 static void print_footer(void)
204 if (!include_html("include/footer.html")) {
205 printf("\n</BODY>\n</HTML>\n");
209 /****************************************************************************
210 display one editable parameter in a form
211 ****************************************************************************/
212 static void show_parameter(int snum, struct parm_struct *parm)
215 void *ptr = parm->ptr;
216 char *utf8_s1, *utf8_s2;
218 if (parm->p_class == P_LOCAL && snum >= 0) {
219 ptr = lp_local_ptr(snum, ptr);
222 printf("<tr><td>%s</td><td>", get_parm_translated(stripspaceupper(parm->label), _("Help"), parm->label));
223 switch (parm->type) {
225 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
226 make_parm_name(parm->label), *(char *)ptr);
227 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
228 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
232 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
233 make_parm_name(parm->label));
234 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
235 char **list = *(char ***)ptr;
236 for (;*list;list++) {
237 /* enclose in HTML encoded quotes if the string contains a space */
238 if ( strchr_m(*list, ' ') ) {
239 push_utf8_allocate(&utf8_s1, *list);
240 push_utf8_allocate(&utf8_s2, ((*(list+1))?", ":""));
241 printf(""%s"%s", utf8_s1, utf8_s2);
243 push_utf8_allocate(&utf8_s1, *list);
244 push_utf8_allocate(&utf8_s2, ((*(list+1))?", ":""));
245 printf("%s%s", utf8_s1, utf8_s2);
252 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
253 _("Set Default"), make_parm_name(parm->label));
254 if (parm->def.lvalue) {
255 char **list = (char **)(parm->def.lvalue);
256 for (; *list; list++) {
257 /* enclose in HTML encoded quotes if the string contains a space */
258 if ( strchr_m(*list, ' ') )
259 printf(""%s"%s", *list, ((*(list+1))?", ":""));
261 printf("%s%s", *list, ((*(list+1))?", ":""));
269 push_utf8_allocate(&utf8_s1, *(char **)ptr);
270 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
271 make_parm_name(parm->label), fix_quotes(utf8_s1));
273 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
274 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
279 push_utf8_allocate(&utf8_s1, (char *)ptr);
280 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
281 make_parm_name(parm->label), fix_quotes(utf8_s1));
283 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
284 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
288 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
289 printf("<option %s>Yes", (*(BOOL *)ptr)?"selected":"");
290 printf("<option %s>No", (*(BOOL *)ptr)?"":"selected");
292 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
293 _("Set Default"), make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?0:1);
297 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
298 printf("<option %s>Yes", (*(BOOL *)ptr)?"":"selected");
299 printf("<option %s>No", (*(BOOL *)ptr)?"selected":"");
301 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
302 _("Set Default"), make_parm_name(parm->label),(BOOL)(parm->def.bvalue)?1:0);
306 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
307 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
308 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
312 printf("<input type=text size=8 name=\"parm_%s\" value=%s>", make_parm_name(parm->label), octal_string(*(int *)ptr));
313 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
314 _("Set Default"), make_parm_name(parm->label),
315 octal_string((int)(parm->def.ivalue)));
319 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
320 for (i=0;parm->enum_list[i].name;i++) {
321 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
322 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
326 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
327 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
332 printf("</td></tr>\n");
335 /****************************************************************************
336 display a set of parameters for a service
337 ****************************************************************************/
338 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
341 struct parm_struct *parm;
342 const char *heading = NULL;
343 const char *last_heading = NULL;
345 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
346 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
348 if (parm->p_class == P_SEPARATOR) {
349 heading = parm->label;
352 if (parm->flags & FLAG_HIDE) continue;
354 if (printers & !(parm->flags & FLAG_PRINT)) continue;
355 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
358 if (!( parm_filter & FLAG_ADVANCED )) {
359 if (!(parm->flags & FLAG_BASIC)) {
360 void *ptr = parm->ptr;
362 if (parm->p_class == P_LOCAL && snum >= 0) {
363 ptr = lp_local_ptr(snum, ptr);
366 switch (parm->type) {
368 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
372 if (!str_list_compare(*(char ***)ptr, (char **)(parm->def.lvalue))) continue;
377 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
382 if (!strcmp((char *)ptr,(char *)(parm->def.svalue))) continue;
387 if (*(BOOL *)ptr == (BOOL)(parm->def.bvalue)) continue;
392 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
397 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
403 if (printers && !(parm->flags & FLAG_PRINT)) continue;
406 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
408 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
410 if (heading && heading != last_heading) {
411 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
412 last_heading = heading;
414 show_parameter(snum, parm);
418 /****************************************************************************
419 load the smb.conf file into loadparm.
420 ****************************************************************************/
421 static BOOL load_config(BOOL save_def)
423 lp_resetnumservices();
424 return lp_load(dyn_CONFIGFILE,False,save_def,False,True);
427 /****************************************************************************
429 ****************************************************************************/
430 static void write_config(FILE *f, BOOL show_defaults)
432 fprintf(f, "# Samba config file created using SWAT\n");
433 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
434 fprintf(f, "# Date: %s\n\n", current_timestring(False));
436 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
439 /****************************************************************************
440 save and reload the smb.conf config file
441 ****************************************************************************/
442 static int save_reload(int snum)
447 f = sys_fopen(dyn_CONFIGFILE,"w");
449 printf(_("failed to open %s for writing"), dyn_CONFIGFILE);
454 /* just in case they have used the buggy xinetd to create the file */
455 if (fstat(fileno(f), &st) == 0 &&
456 (st.st_mode & S_IWOTH)) {
457 #if defined HAVE_FCHMOD
458 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
460 chmod(dyn_CONFIGFILE, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
464 write_config(f, False);
466 lp_dump_one(f, False, snum);
471 if (!load_config(False)) {
472 printf(_("Can't reload %s"), dyn_CONFIGFILE);
476 iNumNonAutoPrintServices = lp_numservices();
482 /****************************************************************************
484 ****************************************************************************/
485 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
490 if (snum < 0 && parm->p_class == P_LOCAL) {
491 /* this handles the case where we are changing a local
492 variable globally. We need to change the parameter in
493 all shares where it is currently set to the default */
494 for (i=0;i<lp_numservices();i++) {
495 s = lp_servicename(i);
496 if (s && (*s) && lp_is_default(i, parm)) {
497 lp_do_parameter(i, parm->label, v);
502 lp_do_parameter(snum, parm->label, v);
505 /****************************************************************************
506 commit a set of parameters for a service
507 ****************************************************************************/
508 static void commit_parameters(int snum)
511 struct parm_struct *parm;
515 while ((parm = lp_next_parameter(snum, &i, 1))) {
516 slprintf(label, sizeof(label)-1, "parm_%s", make_parm_name(parm->label));
517 if ((v = cgi_variable(label)) != NULL) {
518 if (parm->flags & FLAG_HIDE) continue;
519 commit_parameter(snum, parm, v);
524 /****************************************************************************
525 spit out the html for a link with an image
526 ****************************************************************************/
527 static void image_link(const char *name, const char *hlink, const char *src)
529 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
530 cgi_baseurl(), hlink, src, name);
533 /****************************************************************************
534 display the main navigation controls at the top of each page along
536 ****************************************************************************/
537 static void show_main_buttons(void)
541 if ((p = cgi_user_name()) && strcmp(p, "root")) {
542 printf(_("Logged in as <b>%s</b>"), p);
546 image_link(_("Home"), "", "images/home.gif");
547 if (have_write_access) {
548 image_link(_("Globals"), "globals", "images/globals.gif");
549 image_link(_("Shares"), "shares", "images/shares.gif");
550 image_link(_("Printers"), "printers", "images/printers.gif");
551 image_link(_("Wizard"), "wizard", "images/wizard.gif");
553 /* root always gets all buttons, otherwise look for -P */
554 if ( have_write_access || (!passwd_only && have_read_access) ) {
555 image_link(_("Status"), "status", "images/status.gif");
556 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
558 image_link(_("Password Management"), "passwd", "images/passwd.gif");
563 /****************************************************************************
564 * Handle Display/Edit Mode CGI
565 ****************************************************************************/
566 static void ViewModeBoxes(int mode)
568 printf("<p>%s: \n", _("Current View Is"));
569 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
570 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
571 printf("<br>%s: \n", _("Change View To"));
572 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
573 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
574 printf("</p><br>\n");
577 /****************************************************************************
578 display a welcome page
579 ****************************************************************************/
580 static void welcome_page(void)
582 if (file_exist("help/welcome.html", NULL)) {
583 include_html("help/welcome.html");
585 include_html("help/welcome-no-samba-doc.html");
589 /****************************************************************************
590 display the current smb.conf
591 ****************************************************************************/
592 static void viewconfig_page(void)
596 if (cgi_variable("full_view")) {
600 printf("<H2>%s</H2>\n", _("Current Config"));
601 printf("<form method=post>\n");
604 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
606 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
610 write_config(stdout, full_view);
615 /****************************************************************************
616 second screen of the wizard ... Fetch Configuration Parameters
617 ****************************************************************************/
618 static void wizard_params_page(void)
620 unsigned int parm_filter = FLAG_WIZARD;
622 /* Here we first set and commit all the parameters that were selected
623 in the previous screen. */
625 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
627 if (cgi_variable("Commit")) {
628 commit_parameters(GLOBAL_SECTION_SNUM);
632 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
634 if (have_write_access) {
635 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
638 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
642 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
643 printf("</table>\n");
647 /****************************************************************************
648 Utility to just rewrite the smb.conf file - effectively just cleans it up
649 ****************************************************************************/
650 static void rewritecfg_file(void)
652 commit_parameters(GLOBAL_SECTION_SNUM);
654 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
657 /****************************************************************************
658 wizard to create/modify the smb.conf file
659 ****************************************************************************/
660 static void wizard_page(void)
662 /* Set some variables to collect data from smb.conf */
669 if (cgi_variable("Rewrite")) {
670 (void) rewritecfg_file();
674 if (cgi_variable("GetWizardParams")){
675 (void) wizard_params_page();
679 if (cgi_variable("Commit")){
680 SerType = atoi(cgi_variable_nonull("ServerType"));
681 winstype = atoi(cgi_variable_nonull("WINSType"));
682 have_home = lp_servicenumber(HOMES_NAME);
683 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
685 /* Plain text passwords are too badly broken - use encrypted passwords only */
686 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
690 /* Stand-alone Server */
691 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
692 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
696 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
697 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
700 /* Domain Controller */
701 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
702 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
705 switch ( winstype ) {
707 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
708 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
711 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
712 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
715 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
716 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
720 /* Have to create Homes share? */
721 if ((HomeExpo == 1) && (have_home == -1)) {
724 pstrcpy(unix_share,HOMES_NAME);
726 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
727 iNumNonAutoPrintServices = lp_numservices();
728 have_home = lp_servicenumber(HOMES_NAME);
729 lp_do_parameter( have_home, "read only", "No");
730 lp_do_parameter( have_home, "valid users", "%S");
731 lp_do_parameter( have_home, "browseable", "No");
732 commit_parameters(have_home);
735 /* Need to Delete Homes share? */
736 if ((HomeExpo == 0) && (have_home != -1)) {
737 lp_remove_service(have_home);
741 commit_parameters(GLOBAL_SECTION_SNUM);
746 /* Now determine smb.conf WINS settings */
747 if (lp_wins_support())
749 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
753 /* Do we have a homes share? */
754 have_home = lp_servicenumber(HOMES_NAME);
756 if ((winstype == 2) && lp_wins_support())
759 role = lp_server_role();
762 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
763 printf("<form method=post action=wizard>\n");
765 if (have_write_access) {
766 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
767 printf("%s", _("The same will happen if you press the commit button."));
768 printf("<br><br>\n");
770 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
771 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
772 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
773 printf("</center>\n");
777 printf("<center><table border=0>");
778 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
779 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
780 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
781 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
783 if (role == ROLE_DOMAIN_BDC) {
784 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
786 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
787 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
788 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
789 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
791 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
793 /* Print out the list of wins servers */
794 if(lp_wins_server_list()) {
796 const char **wins_servers = lp_wins_server_list();
797 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
800 printf("\"></td></tr>\n");
802 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"));
803 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
805 printf("<tr><td><b>%s: </b></td>\n", _("Expose Home Directories"));
806 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
807 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
808 printf("<td></td></tr>\n");
810 /* Enable this when we are ready ....
811 * printf("<tr><td><b>%s: </b></td>\n", _("Is Print Server"));
812 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
813 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
814 * printf("<td></td></tr>\n");
817 printf("</table></center>");
820 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
825 /****************************************************************************
826 display a globals editing page
827 ****************************************************************************/
828 static void globals_page(void)
830 unsigned int parm_filter = FLAG_BASIC;
833 printf("<H2>%s</H2>\n", _("Global Parameters"));
835 if (cgi_variable("Commit")) {
836 commit_parameters(GLOBAL_SECTION_SNUM);
840 if ( cgi_variable("ViewMode") )
841 mode = atoi(cgi_variable_nonull("ViewMode"));
842 if ( cgi_variable("BasicMode"))
844 if ( cgi_variable("AdvMode"))
847 printf("<form name=\"swatform\" method=post action=globals>\n");
849 ViewModeBoxes( mode );
852 parm_filter = FLAG_BASIC;
855 parm_filter = FLAG_ADVANCED;
859 if (have_write_access) {
860 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
861 _("Commit Changes"));
864 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
869 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
870 printf("</table>\n");
874 /****************************************************************************
875 display a shares editing page. share is in unix codepage,
876 ****************************************************************************/
877 static void shares_page(void)
879 const char *share = cgi_variable("share");
885 unsigned int parm_filter = FLAG_BASIC;
888 snum = lp_servicenumber(share);
890 printf("<H2>%s</H2>\n", _("Share Parameters"));
892 if (cgi_variable("Commit") && snum >= 0) {
893 commit_parameters(snum);
897 if (cgi_variable("Delete") && snum >= 0) {
898 lp_remove_service(snum);
904 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
906 lp_copy_service(GLOBAL_SECTION_SNUM, share);
907 iNumNonAutoPrintServices = lp_numservices();
909 snum = lp_servicenumber(share);
912 printf("<FORM name=\"swatform\" method=post>\n");
916 if ( cgi_variable("ViewMode") )
917 mode = atoi(cgi_variable_nonull("ViewMode"));
918 if ( cgi_variable("BasicMode"))
920 if ( cgi_variable("AdvMode"))
923 ViewModeBoxes( mode );
926 parm_filter = FLAG_BASIC;
929 parm_filter = FLAG_ADVANCED;
932 printf("<br><tr>\n");
933 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
934 printf("<td><select name=share>\n");
936 printf("<option value=\" \"> \n");
937 for (i=0;i<lp_numservices();i++) {
938 s = lp_servicename(i);
939 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
940 push_utf8_allocate(&utf8_s, s);
941 printf("<option %s value=\"%s\">%s\n",
942 (share && strcmp(share,s)==0)?"SELECTED":"",
948 printf("</select></td>\n");
949 if (have_write_access) {
950 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
955 if (have_write_access) {
957 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
958 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
964 if (have_write_access) {
965 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
968 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
974 show_parameters(snum, 1, parm_filter, 0);
975 printf("</table>\n");
981 /*************************************************************
982 change a password either locally or remotely
983 *************************************************************/
984 static BOOL change_password(const char *remote_machine, const char *user_name,
985 const char *old_passwd, const char *new_passwd,
993 printf("%s\n<p>", _("password change in demo mode rejected"));
997 if (remote_machine != NULL) {
998 ret = remote_password_change(remote_machine, user_name, old_passwd,
999 new_passwd, err_str, sizeof(err_str));
1001 printf("%s\n<p>", err_str);
1002 return NT_STATUS_IS_OK(ret);
1005 if(!initialize_password_db(True, NULL)) {
1006 printf("%s\n<p>", _("Can't setup password database vectors."));
1010 ret = local_password_change(user_name, local_flags, new_passwd, err_str, sizeof(err_str),
1011 msg_str, sizeof(msg_str));
1014 printf("%s\n<p>", msg_str);
1016 printf("%s\n<p>", err_str);
1018 return NT_STATUS_IS_OK(ret);
1021 /****************************************************************************
1022 do the stuff required to add or change a password
1023 ****************************************************************************/
1024 static void chg_passwd(void)
1028 int local_flags = 0;
1030 /* Make sure users name has been specified */
1031 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1032 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1037 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1038 * so if that's what we're doing, skip the rest of the checks
1040 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1043 * If current user is not root, make sure old password has been specified
1044 * If REMOTE change, even root must provide old password
1046 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1047 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1048 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1052 /* If changing a users password on a remote hosts we have to know what host */
1053 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1054 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1058 /* Make sure new passwords have been specified */
1059 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1060 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1061 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1065 /* Make sure new passwords was typed correctly twice */
1066 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1067 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1072 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1073 host = cgi_variable(RHOST);
1074 } else if (am_root()) {
1081 * Set up the local flags.
1084 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1085 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1086 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1087 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1088 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1089 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1092 rslt = change_password(host,
1093 cgi_variable_nonull(SWAT_USER),
1094 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1097 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1100 printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER));
1103 printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER));
1111 /****************************************************************************
1112 display a password editing page
1113 ****************************************************************************/
1114 static void passwd_page(void)
1116 const char *new_name = cgi_user_name();
1119 * After the first time through here be nice. If the user
1120 * changed the User box text to another users name, remember it.
1122 if (cgi_variable(SWAT_USER)) {
1123 new_name = cgi_variable_nonull(SWAT_USER);
1126 if (!new_name) new_name = "";
1128 printf("<H2>%s</H2>\n", _("Server Password Management"));
1130 printf("<FORM name=\"swatform\" method=post>\n");
1132 printf("<table>\n");
1135 * Create all the dialog boxes for data collection
1137 printf("<tr><td> %s : </td>\n", _("User Name"));
1138 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1140 printf("<tr><td> %s : </td>\n", _("Old Password"));
1141 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1143 printf("<tr><td> %s : </td>\n", _("New Password"));
1144 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1145 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1146 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1147 printf("</table>\n");
1150 * Create all the control buttons for requesting action
1152 printf("<input type=submit name=%s value=\"%s\">\n",
1153 CHG_S_PASSWD_FLAG, _("Change Password"));
1154 if (demo_mode || am_root()) {
1155 printf("<input type=submit name=%s value=\"%s\">\n",
1156 ADD_USER_FLAG, _("Add New User"));
1157 printf("<input type=submit name=%s value=\"%s\">\n",
1158 DELETE_USER_FLAG, _("Delete User"));
1159 printf("<input type=submit name=%s value=\"%s\">\n",
1160 DISABLE_USER_FLAG, _("Disable User"));
1161 printf("<input type=submit name=%s value=\"%s\">\n",
1162 ENABLE_USER_FLAG, _("Enable User"));
1164 printf("<p></FORM>\n");
1167 * Do some work if change, add, disable or enable was
1168 * requested. It could be this is the first time through this
1169 * code, so there isn't anything to do. */
1170 if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1171 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1175 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1177 printf("<FORM name=\"swatform\" method=post>\n");
1179 printf("<table>\n");
1182 * Create all the dialog boxes for data collection
1184 printf("<tr><td> %s : </td>\n", _("User Name"));
1185 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1186 printf("<tr><td> %s : </td>\n", _("Old Password"));
1187 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1188 printf("<tr><td> %s : </td>\n", _("New Password"));
1189 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1190 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1191 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1192 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1193 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1198 * Create all the control buttons for requesting action
1200 printf("<input type=submit name=%s value=\"%s\">",
1201 CHG_R_PASSWD_FLAG, _("Change Password"));
1203 printf("<p></FORM>\n");
1206 * Do some work if a request has been made to change the
1207 * password somewhere other than the server. It could be this
1208 * is the first time through this code, so there isn't
1209 * anything to do. */
1210 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1216 /****************************************************************************
1217 display a printers editing page
1218 ****************************************************************************/
1219 static void printers_page(void)
1221 const char *share = cgi_variable("share");
1226 unsigned int parm_filter = FLAG_BASIC;
1229 snum = lp_servicenumber(share);
1231 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1233 printf("<H3>%s</H3>\n", _("Important Note:"));
1234 printf(_("Printer names marked with [*] in the Choose Printer drop-down box "));
1235 printf(_("are autoloaded printers from "));
1236 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1237 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1239 if (cgi_variable("Commit") && snum >= 0) {
1240 commit_parameters(snum);
1241 if (snum >= iNumNonAutoPrintServices)
1247 if (cgi_variable("Delete") && snum >= 0) {
1248 lp_remove_service(snum);
1254 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1256 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1257 iNumNonAutoPrintServices = lp_numservices();
1258 snum = lp_servicenumber(share);
1259 lp_do_parameter(snum, "print ok", "Yes");
1261 snum = lp_servicenumber(share);
1264 printf("<FORM name=\"swatform\" method=post>\n");
1266 if ( cgi_variable("ViewMode") )
1267 mode = atoi(cgi_variable_nonull("ViewMode"));
1268 if ( cgi_variable("BasicMode"))
1270 if ( cgi_variable("AdvMode"))
1273 ViewModeBoxes( mode );
1276 parm_filter = FLAG_BASIC;
1279 parm_filter = FLAG_ADVANCED;
1282 printf("<table>\n");
1283 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1284 printf("<td><select name=\"share\">\n");
1285 if (snum < 0 || !lp_print_ok(snum))
1286 printf("<option value=\" \"> \n");
1287 for (i=0;i<lp_numservices();i++) {
1288 s = lp_servicename(i);
1289 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1290 if (i >= iNumNonAutoPrintServices)
1291 printf("<option %s value=\"%s\">[*]%s\n",
1292 (share && strcmp(share,s)==0)?"SELECTED":"",
1295 printf("<option %s value=\"%s\">%s\n",
1296 (share && strcmp(share,s)==0)?"SELECTED":"",
1300 printf("</select></td>");
1301 if (have_write_access) {
1302 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1305 printf("</table>\n");
1307 if (have_write_access) {
1308 printf("<table>\n");
1309 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1310 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1316 if (have_write_access) {
1317 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1319 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1324 printf("<table>\n");
1325 show_parameters(snum, 1, parm_filter, 1);
1326 printf("</table>\n");
1328 printf("</FORM>\n");
1333 * main function for SWAT.
1335 int main(int argc, char *argv[])
1339 struct poptOption long_options[] = {
1341 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1342 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1348 umask(S_IWGRP | S_IWOTH);
1350 #if defined(HAVE_SET_AUTH_PARAMETERS)
1351 set_auth_parameters(argc, argv);
1352 #endif /* HAVE_SET_AUTH_PARAMETERS */
1354 /* just in case it goes wild ... */
1359 /* we don't want any SIGPIPE messages */
1360 BlockSignals(True,SIGPIPE);
1362 dbf = x_fopen("/dev/null", O_WRONLY, 0);
1363 if (!dbf) dbf = x_stderr;
1365 /* we don't want stderr screwing us up */
1367 open("/dev/null", O_WRONLY);
1369 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1371 /* Parse command line options */
1373 while(poptGetNextOpt(pc) != -1) { }
1375 poptFreeContext(pc);
1379 setup_logging(argv[0],False);
1382 iNumNonAutoPrintServices = lp_numservices();
1385 cgi_setup(dyn_SWATDIR, !demo_mode);
1389 cgi_load_variables();
1391 if (!file_exist(dyn_CONFIGFILE, NULL)) {
1392 have_read_access = True;
1393 have_write_access = True;
1395 /* check if the authenticated user has write access - if not then
1396 don't show write options */
1397 have_write_access = (access(dyn_CONFIGFILE,W_OK) == 0);
1399 /* if the user doesn't have read access to smb.conf then
1400 don't let them view it */
1401 have_read_access = (access(dyn_CONFIGFILE,R_OK) == 0);
1404 show_main_buttons();
1406 page = cgi_pathinfo();
1408 /* Root gets full functionality */
1409 if (have_read_access && strcmp(page, "globals")==0) {
1411 } else if (have_read_access && strcmp(page,"shares")==0) {
1413 } else if (have_read_access && strcmp(page,"printers")==0) {
1415 } else if (have_read_access && strcmp(page,"status")==0) {
1417 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1419 } else if (strcmp(page,"passwd")==0) {
1421 } else if (have_read_access && strcmp(page,"wizard")==0) {
1423 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1424 wizard_params_page();
1425 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {