2 Unix SMB/CIFS implementation.
3 Samba Web Administration Tool
5 Copyright (C) Andrew Tridgell 1997-2002
6 Copyright (C) John H Terpstra 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 * @defgroup swat SWAT - Samba Web Administration Tool
27 * @brief Samba Web Administration Tool.
31 #include "web/swat_proto.h"
33 static int demo_mode = False;
34 static int passwd_only = False;
35 static bool have_write_access = False;
36 static bool have_read_access = False;
37 static int iNumNonAutoPrintServices = 0;
40 * Password Management Globals
42 #define SWAT_USER "username"
43 #define OLD_PSWD "old_passwd"
44 #define NEW_PSWD "new_passwd"
45 #define NEW2_PSWD "new2_passwd"
46 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
47 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
48 #define ADD_USER_FLAG "add_user_flag"
49 #define DELETE_USER_FLAG "delete_user_flag"
50 #define DISABLE_USER_FLAG "disable_user_flag"
51 #define ENABLE_USER_FLAG "enable_user_flag"
52 #define RHOST "remote_host"
54 #define _(x) lang_msg_rotate(talloc_tos(),x)
56 /****************************************************************************
57 ****************************************************************************/
58 static int enum_index(int value, const struct enum_list *enumlist)
61 for (i=0;enumlist[i].name;i++)
62 if (value == enumlist[i].value) break;
66 static char *fix_backslash(const char *str)
68 static char newstring[1024];
72 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
80 static const char *fix_quotes(TALLOC_CTX *ctx, const char *str)
82 char *newstring = NULL;
85 int quote_len = strlen(""");
87 /* Count the number of quotes. */
91 newstring_len += quote_len;
97 newstring = TALLOC_ARRAY(ctx, char, newstring_len);
101 for (p = newstring; *str; str++) {
103 strncpy( p, """, quote_len);
114 static char *stripspaceupper(const char *str)
116 static char newstring[1024];
120 if (*str != ' ') *p++ = toupper_ascii(*str);
127 static char *make_parm_name(const char *label)
129 static char parmname[1024];
133 if (*label == ' ') *p++ = '_';
141 /****************************************************************************
142 include a lump of html in a page
143 ****************************************************************************/
144 static int include_html(const char *fname)
150 fd = web_open(fname, O_RDONLY, 0);
153 printf(_("ERROR: Can't open %s"), fname);
158 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
166 /****************************************************************************
167 start the page with standard stuff
168 ****************************************************************************/
169 static void print_header(void)
171 if (!cgi_waspost()) {
172 printf("Expires: 0\r\n");
174 printf("Content-type: text/html\r\n\r\n");
176 if (!include_html("include/header.html")) {
177 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
178 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
182 /* *******************************************************************
183 show parameter label with translated name in the following form
184 because showing original and translated label in one line looks
185 too long, and showing translated label only is unusable for
187 -------------------------------
188 HELP security [combo box][button]
190 -------------------------------
191 (capital words are translated by gettext.)
192 if no translation is available, then same form as original is
194 "i18n_translated_parm" class is used to change the color of the
195 translated parameter with CSS.
196 **************************************************************** */
197 static const char *get_parm_translated(TALLOC_CTX *ctx,
198 const char* pAnchor, const char* pHelp, const char* pLabel)
200 const char *pTranslated = _(pLabel);
202 if(strcmp(pLabel, pTranslated) != 0) {
203 output = talloc_asprintf(ctx,
204 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>",
205 pAnchor, pHelp, pLabel, pTranslated);
208 output = talloc_asprintf(ctx,
209 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
210 pAnchor, pHelp, pLabel);
213 /****************************************************************************
215 ****************************************************************************/
216 static void print_footer(void)
218 if (!include_html("include/footer.html")) {
219 printf("\n</BODY>\n</HTML>\n");
223 /****************************************************************************
224 display one editable parameter in a form
225 ****************************************************************************/
226 static void show_parameter(int snum, struct parm_struct *parm)
229 void *ptr = parm->ptr;
230 char *utf8_s1, *utf8_s2;
231 TALLOC_CTX *ctx = talloc_stackframe();
233 if (parm->p_class == P_LOCAL && snum >= 0) {
234 ptr = lp_local_ptr(snum, ptr);
237 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
238 stripspaceupper(parm->label), _("Help"), parm->label));
239 switch (parm->type) {
241 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
242 make_parm_name(parm->label), *(char *)ptr);
243 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
244 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
248 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
249 make_parm_name(parm->label));
250 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
251 char **list = *(char ***)ptr;
252 for (;*list;list++) {
253 /* enclose in HTML encoded quotes if the string contains a space */
254 if ( strchr_m(*list, ' ') ) {
255 push_utf8_allocate(&utf8_s1, *list);
256 push_utf8_allocate(&utf8_s2, ((*(list+1))?", ":""));
257 printf(""%s"%s", utf8_s1, utf8_s2);
259 push_utf8_allocate(&utf8_s1, *list);
260 push_utf8_allocate(&utf8_s2, ((*(list+1))?", ":""));
261 printf("%s%s", utf8_s1, utf8_s2);
268 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
269 _("Set Default"), make_parm_name(parm->label));
270 if (parm->def.lvalue) {
271 char **list = (char **)(parm->def.lvalue);
272 for (; *list; list++) {
273 /* enclose in HTML encoded quotes if the string contains a space */
274 if ( strchr_m(*list, ' ') )
275 printf(""%s"%s", *list, ((*(list+1))?", ":""));
277 printf("%s%s", *list, ((*(list+1))?", ":""));
285 push_utf8_allocate(&utf8_s1, *(char **)ptr);
286 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
287 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
289 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
290 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
295 push_utf8_allocate(&utf8_s1, (char *)ptr);
296 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
297 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
299 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
300 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
304 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
305 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
306 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
308 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
309 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
313 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
314 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
315 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
317 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
318 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
322 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
323 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
324 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
328 printf("<input type=text size=8 name=\"parm_%s\" value=%s>", make_parm_name(parm->label), octal_string(*(int *)ptr));
329 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
330 _("Set Default"), make_parm_name(parm->label),
331 octal_string((int)(parm->def.ivalue)));
335 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
336 for (i=0;parm->enum_list[i].name;i++) {
337 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
338 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
342 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
343 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
348 printf("</td></tr>\n");
352 /****************************************************************************
353 display a set of parameters for a service
354 ****************************************************************************/
355 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
358 struct parm_struct *parm;
359 const char *heading = NULL;
360 const char *last_heading = NULL;
362 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
363 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
365 if (parm->p_class == P_SEPARATOR) {
366 heading = parm->label;
369 if (parm->flags & FLAG_HIDE) continue;
371 if (printers & !(parm->flags & FLAG_PRINT)) continue;
372 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
375 if (!( parm_filter & FLAG_ADVANCED )) {
376 if (!(parm->flags & FLAG_BASIC)) {
377 void *ptr = parm->ptr;
379 if (parm->p_class == P_LOCAL && snum >= 0) {
380 ptr = lp_local_ptr(snum, ptr);
383 switch (parm->type) {
385 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
389 if (!str_list_compare(*(char ***)ptr, (char **)(parm->def.lvalue))) continue;
394 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
399 if (!strcmp((char *)ptr,(char *)(parm->def.svalue))) continue;
404 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
409 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
414 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
420 if (printers && !(parm->flags & FLAG_PRINT)) continue;
423 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
425 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
427 if (heading && heading != last_heading) {
428 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
429 last_heading = heading;
431 show_parameter(snum, parm);
435 /****************************************************************************
436 load the smb.conf file into loadparm.
437 ****************************************************************************/
438 static bool load_config(bool save_def)
440 lp_resetnumservices();
441 return lp_load(dyn_CONFIGFILE,False,save_def,False,True);
444 /****************************************************************************
446 ****************************************************************************/
447 static void write_config(FILE *f, bool show_defaults)
449 fprintf(f, "# Samba config file created using SWAT\n");
450 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
451 fprintf(f, "# Date: %s\n\n", current_timestring(False));
453 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(dyn_CONFIGFILE,"w");
466 printf(_("failed to open %s for writing"), 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(dyn_CONFIGFILE, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
481 write_config(f, False);
483 lp_dump_one(f, False, snum);
488 if (!load_config(False)) {
489 printf(_("Can't reload %s"), dyn_CONFIGFILE);
493 iNumNonAutoPrintServices = lp_numservices();
499 /****************************************************************************
501 ****************************************************************************/
502 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
507 if (snum < 0 && parm->p_class == P_LOCAL) {
508 /* this handles the case where we are changing a local
509 variable globally. We need to change the parameter in
510 all shares where it is currently set to the default */
511 for (i=0;i<lp_numservices();i++) {
512 s = lp_servicename(i);
513 if (s && (*s) && lp_is_default(i, parm)) {
514 lp_do_parameter(i, parm->label, v);
519 lp_do_parameter(snum, parm->label, v);
522 /****************************************************************************
523 commit a set of parameters for a service
524 ****************************************************************************/
525 static void commit_parameters(int snum)
528 struct parm_struct *parm;
532 while ((parm = lp_next_parameter(snum, &i, 1))) {
533 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
534 if ((v = cgi_variable(label)) != NULL) {
535 if (parm->flags & FLAG_HIDE)
537 commit_parameter(snum, parm, v);
544 /****************************************************************************
545 spit out the html for a link with an image
546 ****************************************************************************/
547 static void image_link(const char *name, const char *hlink, const char *src)
549 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
550 cgi_baseurl(), hlink, src, name);
553 /****************************************************************************
554 display the main navigation controls at the top of each page along
556 ****************************************************************************/
557 static void show_main_buttons(void)
561 if ((p = cgi_user_name()) && strcmp(p, "root")) {
562 printf(_("Logged in as <b>%s</b>"), p);
566 image_link(_("Home"), "", "images/home.gif");
567 if (have_write_access) {
568 image_link(_("Globals"), "globals", "images/globals.gif");
569 image_link(_("Shares"), "shares", "images/shares.gif");
570 image_link(_("Printers"), "printers", "images/printers.gif");
571 image_link(_("Wizard"), "wizard", "images/wizard.gif");
573 /* root always gets all buttons, otherwise look for -P */
574 if ( have_write_access || (!passwd_only && have_read_access) ) {
575 image_link(_("Status"), "status", "images/status.gif");
576 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
578 image_link(_("Password Management"), "passwd", "images/passwd.gif");
583 /****************************************************************************
584 * Handle Display/Edit Mode CGI
585 ****************************************************************************/
586 static void ViewModeBoxes(int mode)
588 printf("<p>%s: \n", _("Current View Is"));
589 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
590 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
591 printf("<br>%s: \n", _("Change View To"));
592 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
593 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
594 printf("</p><br>\n");
597 /****************************************************************************
598 display a welcome page
599 ****************************************************************************/
600 static void welcome_page(void)
602 if (file_exist("help/welcome.html", NULL)) {
603 include_html("help/welcome.html");
605 include_html("help/welcome-no-samba-doc.html");
609 /****************************************************************************
610 display the current smb.conf
611 ****************************************************************************/
612 static void viewconfig_page(void)
616 if (cgi_variable("full_view")) {
620 printf("<H2>%s</H2>\n", _("Current Config"));
621 printf("<form method=post>\n");
624 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
626 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
630 write_config(stdout, full_view);
635 /****************************************************************************
636 second screen of the wizard ... Fetch Configuration Parameters
637 ****************************************************************************/
638 static void wizard_params_page(void)
640 unsigned int parm_filter = FLAG_WIZARD;
642 /* Here we first set and commit all the parameters that were selected
643 in the previous screen. */
645 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
647 if (cgi_variable("Commit")) {
648 commit_parameters(GLOBAL_SECTION_SNUM);
652 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
654 if (have_write_access) {
655 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
658 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
662 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
663 printf("</table>\n");
667 /****************************************************************************
668 Utility to just rewrite the smb.conf file - effectively just cleans it up
669 ****************************************************************************/
670 static void rewritecfg_file(void)
672 commit_parameters(GLOBAL_SECTION_SNUM);
674 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
677 /****************************************************************************
678 wizard to create/modify the smb.conf file
679 ****************************************************************************/
680 static void wizard_page(void)
682 /* Set some variables to collect data from smb.conf */
689 if (cgi_variable("Rewrite")) {
690 (void) rewritecfg_file();
694 if (cgi_variable("GetWizardParams")){
695 (void) wizard_params_page();
699 if (cgi_variable("Commit")){
700 SerType = atoi(cgi_variable_nonull("ServerType"));
701 winstype = atoi(cgi_variable_nonull("WINSType"));
702 have_home = lp_servicenumber(HOMES_NAME);
703 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
705 /* Plain text passwords are too badly broken - use encrypted passwords only */
706 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
710 /* Stand-alone Server */
711 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
712 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
716 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
717 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
720 /* Domain Controller */
721 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
722 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
725 switch ( winstype ) {
727 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
728 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
731 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
732 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
735 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
736 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
740 /* Have to create Homes share? */
741 if ((HomeExpo == 1) && (have_home == -1)) {
742 const char *unix_share = HOMES_NAME;
745 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
746 iNumNonAutoPrintServices = lp_numservices();
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);
754 /* Need to Delete Homes share? */
755 if ((HomeExpo == 0) && (have_home != -1)) {
756 lp_remove_service(have_home);
760 commit_parameters(GLOBAL_SECTION_SNUM);
765 /* Now determine smb.conf WINS settings */
766 if (lp_wins_support())
768 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
771 /* Do we have a homes share? */
772 have_home = lp_servicenumber(HOMES_NAME);
774 if ((winstype == 2) && lp_wins_support())
777 role = lp_server_role();
780 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
781 printf("<form method=post action=wizard>\n");
783 if (have_write_access) {
784 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
785 printf("%s", _("The same will happen if you press the commit button."));
786 printf("<br><br>\n");
788 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
789 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
790 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
791 printf("</center>\n");
795 printf("<center><table border=0>");
796 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
797 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
798 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
799 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
801 if (role == ROLE_DOMAIN_BDC) {
802 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
804 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
805 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
806 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
807 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
809 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
811 /* Print out the list of wins servers */
812 if(lp_wins_server_list()) {
814 const char **wins_servers = lp_wins_server_list();
815 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
818 printf("\"></td></tr>\n");
820 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"));
821 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
823 printf("<tr><td><b>%s: </b></td>\n", _("Expose Home Directories"));
824 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
825 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
826 printf("<td></td></tr>\n");
828 /* Enable this when we are ready ....
829 * printf("<tr><td><b>%s: </b></td>\n", _("Is Print Server"));
830 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
831 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
832 * printf("<td></td></tr>\n");
835 printf("</table></center>");
838 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
843 /****************************************************************************
844 display a globals editing page
845 ****************************************************************************/
846 static void globals_page(void)
848 unsigned int parm_filter = FLAG_BASIC;
851 printf("<H2>%s</H2>\n", _("Global Parameters"));
853 if (cgi_variable("Commit")) {
854 commit_parameters(GLOBAL_SECTION_SNUM);
858 if ( cgi_variable("ViewMode") )
859 mode = atoi(cgi_variable_nonull("ViewMode"));
860 if ( cgi_variable("BasicMode"))
862 if ( cgi_variable("AdvMode"))
865 printf("<form name=\"swatform\" method=post action=globals>\n");
867 ViewModeBoxes( mode );
870 parm_filter = FLAG_BASIC;
873 parm_filter = FLAG_ADVANCED;
877 if (have_write_access) {
878 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
879 _("Commit Changes"));
882 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
887 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
888 printf("</table>\n");
892 /****************************************************************************
893 display a shares editing page. share is in unix codepage,
894 ****************************************************************************/
895 static void shares_page(void)
897 const char *share = cgi_variable("share");
903 unsigned int parm_filter = FLAG_BASIC;
906 snum = lp_servicenumber(share);
908 printf("<H2>%s</H2>\n", _("Share Parameters"));
910 if (cgi_variable("Commit") && snum >= 0) {
911 commit_parameters(snum);
915 if (cgi_variable("Delete") && snum >= 0) {
916 lp_remove_service(snum);
922 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
924 lp_copy_service(GLOBAL_SECTION_SNUM, share);
925 iNumNonAutoPrintServices = lp_numservices();
927 snum = lp_servicenumber(share);
930 printf("<FORM name=\"swatform\" method=post>\n");
934 if ( cgi_variable("ViewMode") )
935 mode = atoi(cgi_variable_nonull("ViewMode"));
936 if ( cgi_variable("BasicMode"))
938 if ( cgi_variable("AdvMode"))
941 ViewModeBoxes( mode );
944 parm_filter = FLAG_BASIC;
947 parm_filter = FLAG_ADVANCED;
950 printf("<br><tr>\n");
951 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
952 printf("<td><select name=share>\n");
954 printf("<option value=\" \"> \n");
955 for (i=0;i<lp_numservices();i++) {
956 s = lp_servicename(i);
957 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
958 push_utf8_allocate(&utf8_s, s);
959 printf("<option %s value=\"%s\">%s\n",
960 (share && strcmp(share,s)==0)?"SELECTED":"",
966 printf("</select></td>\n");
967 if (have_write_access) {
968 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
973 if (have_write_access) {
975 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
976 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
982 if (have_write_access) {
983 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
986 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
992 show_parameters(snum, 1, parm_filter, 0);
993 printf("</table>\n");
999 /*************************************************************
1000 change a password either locally or remotely
1001 *************************************************************/
1002 static bool change_password(const char *remote_machine, const char *user_name,
1003 const char *old_passwd, const char *new_passwd,
1007 char *err_str = NULL;
1008 char *msg_str = NULL;
1011 printf("%s\n<p>", _("password change in demo mode rejected"));
1015 if (remote_machine != NULL) {
1016 ret = remote_password_change(remote_machine, user_name,
1017 old_passwd, new_passwd, &err_str);
1018 if (err_str != NULL)
1019 printf("%s\n<p>", err_str);
1021 return NT_STATUS_IS_OK(ret);
1024 if(!initialize_password_db(True, NULL)) {
1025 printf("%s\n<p>", _("Can't setup password database vectors."));
1029 ret = local_password_change(user_name, local_flags, new_passwd,
1030 &err_str, &msg_str);
1033 printf("%s\n<p>", msg_str);
1035 printf("%s\n<p>", err_str);
1039 return NT_STATUS_IS_OK(ret);
1042 /****************************************************************************
1043 do the stuff required to add or change a password
1044 ****************************************************************************/
1045 static void chg_passwd(void)
1049 int local_flags = 0;
1051 /* Make sure users name has been specified */
1052 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1053 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1058 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1059 * so if that's what we're doing, skip the rest of the checks
1061 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1064 * If current user is not root, make sure old password has been specified
1065 * If REMOTE change, even root must provide old password
1067 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1068 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1069 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1073 /* If changing a users password on a remote hosts we have to know what host */
1074 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1075 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1079 /* Make sure new passwords have been specified */
1080 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1081 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1082 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1086 /* Make sure new passwords was typed correctly twice */
1087 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1088 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1093 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1094 host = cgi_variable(RHOST);
1095 } else if (am_root()) {
1102 * Set up the local flags.
1105 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1106 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1107 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1108 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1109 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1110 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1113 rslt = change_password(host,
1114 cgi_variable_nonull(SWAT_USER),
1115 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1118 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1121 printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER));
1124 printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER));
1132 /****************************************************************************
1133 display a password editing page
1134 ****************************************************************************/
1135 static void passwd_page(void)
1137 const char *new_name = cgi_user_name();
1140 * After the first time through here be nice. If the user
1141 * changed the User box text to another users name, remember it.
1143 if (cgi_variable(SWAT_USER)) {
1144 new_name = cgi_variable_nonull(SWAT_USER);
1147 if (!new_name) new_name = "";
1149 printf("<H2>%s</H2>\n", _("Server Password Management"));
1151 printf("<FORM name=\"swatform\" method=post>\n");
1153 printf("<table>\n");
1156 * Create all the dialog boxes for data collection
1158 printf("<tr><td> %s : </td>\n", _("User Name"));
1159 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1161 printf("<tr><td> %s : </td>\n", _("Old Password"));
1162 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1164 printf("<tr><td> %s : </td>\n", _("New Password"));
1165 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1166 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1167 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1168 printf("</table>\n");
1171 * Create all the control buttons for requesting action
1173 printf("<input type=submit name=%s value=\"%s\">\n",
1174 CHG_S_PASSWD_FLAG, _("Change Password"));
1175 if (demo_mode || am_root()) {
1176 printf("<input type=submit name=%s value=\"%s\">\n",
1177 ADD_USER_FLAG, _("Add New User"));
1178 printf("<input type=submit name=%s value=\"%s\">\n",
1179 DELETE_USER_FLAG, _("Delete User"));
1180 printf("<input type=submit name=%s value=\"%s\">\n",
1181 DISABLE_USER_FLAG, _("Disable User"));
1182 printf("<input type=submit name=%s value=\"%s\">\n",
1183 ENABLE_USER_FLAG, _("Enable User"));
1185 printf("<p></FORM>\n");
1188 * Do some work if change, add, disable or enable was
1189 * requested. It could be this is the first time through this
1190 * code, so there isn't anything to do. */
1191 if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1192 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1196 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1198 printf("<FORM name=\"swatform\" method=post>\n");
1200 printf("<table>\n");
1203 * Create all the dialog boxes for data collection
1205 printf("<tr><td> %s : </td>\n", _("User Name"));
1206 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1207 printf("<tr><td> %s : </td>\n", _("Old Password"));
1208 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1209 printf("<tr><td> %s : </td>\n", _("New Password"));
1210 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1211 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1212 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1213 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1214 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1219 * Create all the control buttons for requesting action
1221 printf("<input type=submit name=%s value=\"%s\">",
1222 CHG_R_PASSWD_FLAG, _("Change Password"));
1224 printf("<p></FORM>\n");
1227 * Do some work if a request has been made to change the
1228 * password somewhere other than the server. It could be this
1229 * is the first time through this code, so there isn't
1230 * anything to do. */
1231 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1237 /****************************************************************************
1238 display a printers editing page
1239 ****************************************************************************/
1240 static void printers_page(void)
1242 const char *share = cgi_variable("share");
1247 unsigned int parm_filter = FLAG_BASIC;
1250 snum = lp_servicenumber(share);
1252 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1254 printf("<H3>%s</H3>\n", _("Important Note:"));
1255 printf(_("Printer names marked with [*] in the Choose Printer drop-down box "));
1256 printf(_("are autoloaded printers from "));
1257 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1258 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1260 if (cgi_variable("Commit") && snum >= 0) {
1261 commit_parameters(snum);
1262 if (snum >= iNumNonAutoPrintServices)
1268 if (cgi_variable("Delete") && snum >= 0) {
1269 lp_remove_service(snum);
1275 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1277 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1278 iNumNonAutoPrintServices = lp_numservices();
1279 snum = lp_servicenumber(share);
1280 lp_do_parameter(snum, "print ok", "Yes");
1282 snum = lp_servicenumber(share);
1285 printf("<FORM name=\"swatform\" method=post>\n");
1287 if ( cgi_variable("ViewMode") )
1288 mode = atoi(cgi_variable_nonull("ViewMode"));
1289 if ( cgi_variable("BasicMode"))
1291 if ( cgi_variable("AdvMode"))
1294 ViewModeBoxes( mode );
1297 parm_filter = FLAG_BASIC;
1300 parm_filter = FLAG_ADVANCED;
1303 printf("<table>\n");
1304 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1305 printf("<td><select name=\"share\">\n");
1306 if (snum < 0 || !lp_print_ok(snum))
1307 printf("<option value=\" \"> \n");
1308 for (i=0;i<lp_numservices();i++) {
1309 s = lp_servicename(i);
1310 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1311 if (i >= iNumNonAutoPrintServices)
1312 printf("<option %s value=\"%s\">[*]%s\n",
1313 (share && strcmp(share,s)==0)?"SELECTED":"",
1316 printf("<option %s value=\"%s\">%s\n",
1317 (share && strcmp(share,s)==0)?"SELECTED":"",
1321 printf("</select></td>");
1322 if (have_write_access) {
1323 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1326 printf("</table>\n");
1328 if (have_write_access) {
1329 printf("<table>\n");
1330 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1331 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1337 if (have_write_access) {
1338 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1340 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1345 printf("<table>\n");
1346 show_parameters(snum, 1, parm_filter, 1);
1347 printf("</table>\n");
1349 printf("</FORM>\n");
1353 when the _() translation macro is used there is no obvious place to free
1354 the resulting string and there is no easy way to give a static pointer.
1355 All we can do is rotate between some static buffers and hope a single d_printf()
1356 doesn't have more calls to _() than the number of buffers
1359 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1364 msgstr = lang_msg(msgid);
1369 ret = talloc_strdup(ctx, msgstr);
1371 lang_msg_free(msgstr);
1380 * main function for SWAT.
1382 int main(int argc, char *argv[])
1386 struct poptOption long_options[] = {
1388 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1389 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1393 TALLOC_CTX *frame = talloc_stackframe();
1396 umask(S_IWGRP | S_IWOTH);
1398 #if defined(HAVE_SET_AUTH_PARAMETERS)
1399 set_auth_parameters(argc, argv);
1400 #endif /* HAVE_SET_AUTH_PARAMETERS */
1402 /* just in case it goes wild ... */
1407 /* we don't want any SIGPIPE messages */
1408 BlockSignals(True,SIGPIPE);
1410 dbf = x_fopen("/dev/null", O_WRONLY, 0);
1411 if (!dbf) dbf = x_stderr;
1413 /* we don't want stderr screwing us up */
1415 open("/dev/null", O_WRONLY);
1417 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1419 /* Parse command line options */
1421 while(poptGetNextOpt(pc) != -1) { }
1423 poptFreeContext(pc);
1427 setup_logging(argv[0],False);
1430 iNumNonAutoPrintServices = lp_numservices();
1433 cgi_setup(dyn_SWATDIR, !demo_mode);
1437 cgi_load_variables();
1439 if (!file_exist(dyn_CONFIGFILE, NULL)) {
1440 have_read_access = True;
1441 have_write_access = True;
1443 /* check if the authenticated user has write access - if not then
1444 don't show write options */
1445 have_write_access = (access(dyn_CONFIGFILE,W_OK) == 0);
1447 /* if the user doesn't have read access to smb.conf then
1448 don't let them view it */
1449 have_read_access = (access(dyn_CONFIGFILE,R_OK) == 0);
1452 show_main_buttons();
1454 page = cgi_pathinfo();
1456 /* Root gets full functionality */
1457 if (have_read_access && strcmp(page, "globals")==0) {
1459 } else if (have_read_access && strcmp(page,"shares")==0) {
1461 } else if (have_read_access && strcmp(page,"printers")==0) {
1463 } else if (have_read_access && strcmp(page,"status")==0) {
1465 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1467 } else if (strcmp(page,"passwd")==0) {
1469 } else if (have_read_access && strcmp(page,"wizard")==0) {
1471 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1472 wizard_params_page();
1473 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {