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"
32 #include "../lib/crypto/md5.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"
54 #define XSRF_TOKEN "xsrf"
56 #define _(x) lang_msg_rotate(talloc_tos(),x)
58 /****************************************************************************
59 ****************************************************************************/
60 static int enum_index(int value, const struct enum_list *enumlist)
63 for (i=0;enumlist[i].name;i++)
64 if (value == enumlist[i].value) break;
68 static char *fix_backslash(const char *str)
70 static char newstring[1024];
74 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
82 static const char *fix_quotes(TALLOC_CTX *ctx, const char *str)
84 char *newstring = NULL;
87 int quote_len = strlen(""");
89 /* Count the number of quotes. */
94 newstring_len += quote_len;
100 newstring = TALLOC_ARRAY(ctx, char, newstring_len);
104 for (p = newstring; *str; str++) {
106 strncpy( p, """, quote_len);
116 static char *stripspaceupper(const char *str)
118 static char newstring[1024];
122 if (*str != ' ') *p++ = toupper_ascii(*str);
129 static char *make_parm_name(const char *label)
131 static char parmname[1024];
135 if (*label == ' ') *p++ = '_';
143 void get_xsrf_token(const char *username, const char *pass,
144 const char *formname, char token_str[33])
146 struct MD5Context md5_ctx;
151 ZERO_STRUCT(md5_ctx);
154 MD5Update(&md5_ctx, (uint8_t *)formname, strlen(formname));
155 if (username != NULL) {
156 MD5Update(&md5_ctx, (uint8_t *)username, strlen(username));
159 MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
162 MD5Final(token, &md5_ctx);
164 for(i = 0; i < sizeof(token); i++) {
167 snprintf(tmp, sizeof(tmp), "%02x", token[i]);
168 strncat(token_str, tmp, sizeof(tmp));
172 void print_xsrf_token(const char *username, const char *pass,
173 const char *formname)
177 get_xsrf_token(username, pass, formname, token);
178 printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
183 bool verify_xsrf_token(const char *formname)
186 const char *username = cgi_user_name();
187 const char *pass = cgi_user_pass();
188 const char *token = cgi_variable_nonull(XSRF_TOKEN);
190 get_xsrf_token(username, pass, formname, expected);
191 return (strncmp(expected, token, sizeof(expected)) == 0);
195 /****************************************************************************
196 include a lump of html in a page
197 ****************************************************************************/
198 static int include_html(const char *fname)
204 fd = web_open(fname, O_RDONLY, 0);
207 printf(_("ERROR: Can't open %s"), fname);
212 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
213 if (write(1, buf, ret) == -1) {
222 /****************************************************************************
223 start the page with standard stuff
224 ****************************************************************************/
225 static void print_header(void)
227 if (!cgi_waspost()) {
228 printf("Expires: 0\r\n");
230 printf("Content-type: text/html\r\n\r\n");
232 if (!include_html("include/header.html")) {
233 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
234 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
238 /* *******************************************************************
239 show parameter label with translated name in the following form
240 because showing original and translated label in one line looks
241 too long, and showing translated label only is unusable for
243 -------------------------------
244 HELP security [combo box][button]
246 -------------------------------
247 (capital words are translated by gettext.)
248 if no translation is available, then same form as original is
250 "i18n_translated_parm" class is used to change the color of the
251 translated parameter with CSS.
252 **************************************************************** */
253 static const char *get_parm_translated(TALLOC_CTX *ctx,
254 const char* pAnchor, const char* pHelp, const char* pLabel)
256 const char *pTranslated = _(pLabel);
258 if(strcmp(pLabel, pTranslated) != 0) {
259 output = talloc_asprintf(ctx,
260 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s <br><span class=\"i18n_translated_parm\">%s</span>",
261 pAnchor, pHelp, pLabel, pTranslated);
264 output = talloc_asprintf(ctx,
265 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A> %s",
266 pAnchor, pHelp, pLabel);
269 /****************************************************************************
271 ****************************************************************************/
272 static void print_footer(void)
274 if (!include_html("include/footer.html")) {
275 printf("\n</BODY>\n</HTML>\n");
279 /****************************************************************************
280 display one editable parameter in a form
281 ****************************************************************************/
282 static void show_parameter(int snum, struct parm_struct *parm)
285 void *ptr = parm->ptr;
286 char *utf8_s1, *utf8_s2;
287 size_t converted_size;
288 TALLOC_CTX *ctx = talloc_stackframe();
290 if (parm->p_class == P_LOCAL && snum >= 0) {
291 ptr = lp_local_ptr_by_snum(snum, ptr);
294 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
295 stripspaceupper(parm->label), _("Help"), parm->label));
296 switch (parm->type) {
298 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
299 make_parm_name(parm->label), *(char *)ptr);
300 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
301 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
305 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
306 make_parm_name(parm->label));
307 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
308 char **list = *(char ***)ptr;
309 for (;*list;list++) {
310 /* enclose in HTML encoded quotes if the string contains a space */
311 if ( strchr_m(*list, ' ') ) {
312 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
313 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
314 printf(""%s"%s", utf8_s1, utf8_s2);
316 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
317 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
318 printf("%s%s", utf8_s1, utf8_s2);
320 TALLOC_FREE(utf8_s1);
321 TALLOC_FREE(utf8_s2);
325 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
326 _("Set Default"), make_parm_name(parm->label));
327 if (parm->def.lvalue) {
328 char **list = (char **)(parm->def.lvalue);
329 for (; *list; list++) {
330 /* enclose in HTML encoded quotes if the string contains a space */
331 if ( strchr_m(*list, ' ') )
332 printf(""%s"%s", *list, ((*(list+1))?", ":""));
334 printf("%s%s", *list, ((*(list+1))?", ":""));
342 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
343 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
344 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
345 TALLOC_FREE(utf8_s1);
346 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
347 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
351 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
352 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
353 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
355 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
356 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
360 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
361 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
362 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
364 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
365 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
369 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
370 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
371 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
376 o = octal_string(*(int *)ptr);
377 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
378 make_parm_name(parm->label), o);
380 o = octal_string((int)(parm->def.ivalue));
381 printf("<input type=button value=\"%s\" "
382 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
383 _("Set Default"), make_parm_name(parm->label), o);
389 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
390 for (i=0;parm->enum_list[i].name;i++) {
391 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
392 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
396 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
397 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
402 printf("</td></tr>\n");
406 /****************************************************************************
407 display a set of parameters for a service
408 ****************************************************************************/
409 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
412 struct parm_struct *parm;
413 const char *heading = NULL;
414 const char *last_heading = NULL;
416 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
417 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
419 if (parm->p_class == P_SEPARATOR) {
420 heading = parm->label;
423 if (parm->flags & FLAG_HIDE) continue;
425 if (printers & !(parm->flags & FLAG_PRINT)) continue;
426 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
429 if (!( parm_filter & FLAG_ADVANCED )) {
430 if (!(parm->flags & FLAG_BASIC)) {
431 void *ptr = parm->ptr;
433 if (parm->p_class == P_LOCAL && snum >= 0) {
434 ptr = lp_local_ptr_by_snum(snum, ptr);
437 switch (parm->type) {
439 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
443 if (!str_list_equal(*(const char ***)ptr,
444 (const char **)(parm->def.lvalue))) continue;
449 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
454 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
459 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
464 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
470 if (printers && !(parm->flags & FLAG_PRINT)) continue;
473 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
475 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
477 if (heading && heading != last_heading) {
478 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
479 last_heading = heading;
481 show_parameter(snum, parm);
485 /****************************************************************************
486 load the smb.conf file into loadparm.
487 ****************************************************************************/
488 static bool load_config(bool save_def)
490 return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
493 /****************************************************************************
495 ****************************************************************************/
496 static void write_config(FILE *f, bool show_defaults)
498 TALLOC_CTX *ctx = talloc_stackframe();
500 fprintf(f, "# Samba config file created using SWAT\n");
501 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
502 fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
504 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
509 /****************************************************************************
510 save and reload the smb.conf config file
511 ****************************************************************************/
512 static int save_reload(int snum)
517 f = sys_fopen(get_dyn_CONFIGFILE(),"w");
519 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
524 /* just in case they have used the buggy xinetd to create the file */
525 if (fstat(fileno(f), &st) == 0 &&
526 (st.st_mode & S_IWOTH)) {
527 #if defined HAVE_FCHMOD
528 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
530 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
534 write_config(f, False);
536 lp_dump_one(f, False, snum);
539 lp_kill_all_services();
541 if (!load_config(False)) {
542 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
546 iNumNonAutoPrintServices = lp_numservices();
547 pcap_cache_reload(&load_printers);
552 /****************************************************************************
554 ****************************************************************************/
555 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
560 if (snum < 0 && parm->p_class == P_LOCAL) {
561 /* this handles the case where we are changing a local
562 variable globally. We need to change the parameter in
563 all shares where it is currently set to the default */
564 for (i=0;i<lp_numservices();i++) {
565 s = lp_servicename(i);
566 if (s && (*s) && lp_is_default(i, parm)) {
567 lp_do_parameter(i, parm->label, v);
572 lp_do_parameter(snum, parm->label, v);
575 /****************************************************************************
576 commit a set of parameters for a service
577 ****************************************************************************/
578 static void commit_parameters(int snum)
581 struct parm_struct *parm;
585 while ((parm = lp_next_parameter(snum, &i, 1))) {
586 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
587 if ((v = cgi_variable(label)) != NULL) {
588 if (parm->flags & FLAG_HIDE)
590 commit_parameter(snum, parm, v);
597 /****************************************************************************
598 spit out the html for a link with an image
599 ****************************************************************************/
600 static void image_link(const char *name, const char *hlink, const char *src)
602 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
603 cgi_baseurl(), hlink, src, name);
606 /****************************************************************************
607 display the main navigation controls at the top of each page along
609 ****************************************************************************/
610 static void show_main_buttons(void)
614 if ((p = cgi_user_name()) && strcmp(p, "root")) {
615 printf(_("Logged in as <b>%s</b>"), p);
619 image_link(_("Home"), "", "images/home.gif");
620 if (have_write_access) {
621 image_link(_("Globals"), "globals", "images/globals.gif");
622 image_link(_("Shares"), "shares", "images/shares.gif");
623 image_link(_("Printers"), "printers", "images/printers.gif");
624 image_link(_("Wizard"), "wizard", "images/wizard.gif");
626 /* root always gets all buttons, otherwise look for -P */
627 if ( have_write_access || (!passwd_only && have_read_access) ) {
628 image_link(_("Status"), "status", "images/status.gif");
629 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
631 image_link(_("Password Management"), "passwd", "images/passwd.gif");
636 /****************************************************************************
637 * Handle Display/Edit Mode CGI
638 ****************************************************************************/
639 static void ViewModeBoxes(int mode)
641 printf("<p>%s: \n", _("Current View Is"));
642 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
643 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
644 printf("<br>%s: \n", _("Change View To"));
645 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
646 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
647 printf("</p><br>\n");
650 /****************************************************************************
651 display a welcome page
652 ****************************************************************************/
653 static void welcome_page(void)
655 if (file_exist("help/welcome.html")) {
656 include_html("help/welcome.html");
658 include_html("help/welcome-no-samba-doc.html");
662 /****************************************************************************
663 display the current smb.conf
664 ****************************************************************************/
665 static void viewconfig_page(void)
668 const char form_name[] = "viewconfig";
670 if (!verify_xsrf_token(form_name)) {
674 if (cgi_variable("full_view")) {
679 printf("<H2>%s</H2>\n", _("Current Config"));
680 printf("<form method=post>\n");
681 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
684 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
686 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
690 write_config(stdout, full_view);
695 /****************************************************************************
696 second screen of the wizard ... Fetch Configuration Parameters
697 ****************************************************************************/
698 static void wizard_params_page(void)
700 unsigned int parm_filter = FLAG_WIZARD;
701 const char form_name[] = "wizard_params";
703 /* Here we first set and commit all the parameters that were selected
704 in the previous screen. */
706 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
708 if (!verify_xsrf_token(form_name)) {
712 if (cgi_variable("Commit")) {
713 commit_parameters(GLOBAL_SECTION_SNUM);
718 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
719 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
721 if (have_write_access) {
722 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
725 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
729 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
730 printf("</table>\n");
734 /****************************************************************************
735 Utility to just rewrite the smb.conf file - effectively just cleans it up
736 ****************************************************************************/
737 static void rewritecfg_file(void)
739 commit_parameters(GLOBAL_SECTION_SNUM);
741 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
744 /****************************************************************************
745 wizard to create/modify the smb.conf file
746 ****************************************************************************/
747 static void wizard_page(void)
749 /* Set some variables to collect data from smb.conf */
755 const char form_name[] = "wizard";
757 if (!verify_xsrf_token(form_name)) {
761 if (cgi_variable("Rewrite")) {
762 (void) rewritecfg_file();
766 if (cgi_variable("GetWizardParams")){
767 (void) wizard_params_page();
771 if (cgi_variable("Commit")){
772 SerType = atoi(cgi_variable_nonull("ServerType"));
773 winstype = atoi(cgi_variable_nonull("WINSType"));
774 have_home = lp_servicenumber(HOMES_NAME);
775 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
777 /* Plain text passwords are too badly broken - use encrypted passwords only */
778 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
782 /* Stand-alone Server */
783 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
784 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
788 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
789 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
792 /* Domain Controller */
793 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
794 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
797 switch ( winstype ) {
799 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
800 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
803 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
804 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
807 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
808 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
812 /* Have to create Homes share? */
813 if ((HomeExpo == 1) && (have_home == -1)) {
814 const char *unix_share = HOMES_NAME;
817 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
818 have_home = lp_servicenumber(HOMES_NAME);
819 lp_do_parameter( have_home, "read only", "No");
820 lp_do_parameter( have_home, "valid users", "%S");
821 lp_do_parameter( have_home, "browseable", "No");
822 commit_parameters(have_home);
823 save_reload(have_home);
826 /* Need to Delete Homes share? */
827 if ((HomeExpo == 0) && (have_home != -1)) {
828 lp_remove_service(have_home);
832 commit_parameters(GLOBAL_SECTION_SNUM);
837 /* Now determine smb.conf WINS settings */
838 if (lp_wins_support())
840 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
843 /* Do we have a homes share? */
844 have_home = lp_servicenumber(HOMES_NAME);
846 if ((winstype == 2) && lp_wins_support())
849 role = lp_server_role();
853 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
854 printf("<form method=post action=wizard>\n");
855 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
857 if (have_write_access) {
858 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
859 printf("%s", _("The same will happen if you press the commit button."));
860 printf("<br><br>\n");
862 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> ",_("Rewrite smb.conf file"));
863 printf("<input type=submit name=\"Commit\" value=\"%s\"> ",_("Commit"));
864 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
865 printf("</center>\n");
869 printf("<center><table border=0>");
870 printf("<tr><td><b>%s: </b></td>\n", _("Server Type"));
871 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s </td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
872 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s </td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
873 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s </td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
875 if (role == ROLE_DOMAIN_BDC) {
876 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
878 printf("<tr><td><b>%s: </b></td>\n", _("Configure WINS As"));
879 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s </td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
880 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s </td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
881 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s </td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
883 printf("<tr><td></td><td></td><td></td><td>%s <input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
885 /* Print out the list of wins servers */
886 if(lp_wins_server_list()) {
888 const char **wins_servers = lp_wins_server_list();
889 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
892 printf("\"></td></tr>\n");
894 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"));
895 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
897 printf("<tr><td><b>%s: </b></td>\n", _("Expose Home Directories"));
898 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
899 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
900 printf("<td></td></tr>\n");
902 /* Enable this when we are ready ....
903 * printf("<tr><td><b>%s: </b></td>\n", _("Is Print Server"));
904 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
905 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
906 * printf("<td></td></tr>\n");
909 printf("</table></center>");
912 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
917 /****************************************************************************
918 display a globals editing page
919 ****************************************************************************/
920 static void globals_page(void)
922 unsigned int parm_filter = FLAG_BASIC;
925 printf("<H2>%s</H2>\n", _("Global Parameters"));
927 if (cgi_variable("Commit")) {
928 commit_parameters(GLOBAL_SECTION_SNUM);
932 if ( cgi_variable("ViewMode") )
933 mode = atoi(cgi_variable_nonull("ViewMode"));
934 if ( cgi_variable("BasicMode"))
936 if ( cgi_variable("AdvMode"))
939 printf("<form name=\"swatform\" method=post action=globals>\n");
941 ViewModeBoxes( mode );
944 parm_filter = FLAG_BASIC;
947 parm_filter = FLAG_ADVANCED;
951 if (have_write_access) {
952 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
953 _("Commit Changes"));
956 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
961 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
962 printf("</table>\n");
966 /****************************************************************************
967 display a shares editing page. share is in unix codepage,
968 ****************************************************************************/
969 static void shares_page(void)
971 const char *share = cgi_variable("share");
977 unsigned int parm_filter = FLAG_BASIC;
978 size_t converted_size;
981 snum = lp_servicenumber(share);
983 printf("<H2>%s</H2>\n", _("Share Parameters"));
985 if (cgi_variable("Commit") && snum >= 0) {
986 commit_parameters(snum);
988 snum = lp_servicenumber(share);
991 if (cgi_variable("Delete") && snum >= 0) {
992 lp_remove_service(snum);
998 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
999 snum = lp_servicenumber(share);
1002 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1003 snum = lp_servicenumber(share);
1005 snum = lp_servicenumber(share);
1009 printf("<FORM name=\"swatform\" method=post>\n");
1011 printf("<table>\n");
1013 if ( cgi_variable("ViewMode") )
1014 mode = atoi(cgi_variable_nonull("ViewMode"));
1015 if ( cgi_variable("BasicMode"))
1017 if ( cgi_variable("AdvMode"))
1020 ViewModeBoxes( mode );
1023 parm_filter = FLAG_BASIC;
1026 parm_filter = FLAG_ADVANCED;
1029 printf("<br><tr>\n");
1030 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1031 printf("<td><select name=share>\n");
1033 printf("<option value=\" \"> \n");
1034 for (i=0;i<lp_numservices();i++) {
1035 s = lp_servicename(i);
1036 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1037 push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1038 printf("<option %s value=\"%s\">%s\n",
1039 (share && strcmp(share,s)==0)?"SELECTED":"",
1041 TALLOC_FREE(utf8_s);
1044 printf("</select></td>\n");
1045 if (have_write_access) {
1046 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1051 if (have_write_access) {
1053 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1054 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1060 if (have_write_access) {
1061 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1064 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1069 printf("<table>\n");
1070 show_parameters(snum, 1, parm_filter, 0);
1071 printf("</table>\n");
1074 printf("</FORM>\n");
1077 /*************************************************************
1078 change a password either locally or remotely
1079 *************************************************************/
1080 static bool change_password(const char *remote_machine, const char *user_name,
1081 const char *old_passwd, const char *new_passwd,
1085 char *err_str = NULL;
1086 char *msg_str = NULL;
1089 printf("%s\n<p>", _("password change in demo mode rejected"));
1093 if (remote_machine != NULL) {
1094 ret = remote_password_change(remote_machine, user_name,
1095 old_passwd, new_passwd, &err_str);
1096 if (err_str != NULL)
1097 printf("%s\n<p>", err_str);
1099 return NT_STATUS_IS_OK(ret);
1102 if(!initialize_password_db(True, NULL)) {
1103 printf("%s\n<p>", _("Can't setup password database vectors."));
1107 ret = local_password_change(user_name, local_flags, new_passwd,
1108 &err_str, &msg_str);
1111 printf("%s\n<p>", msg_str);
1113 printf("%s\n<p>", err_str);
1117 return NT_STATUS_IS_OK(ret);
1120 /****************************************************************************
1121 do the stuff required to add or change a password
1122 ****************************************************************************/
1123 static void chg_passwd(void)
1127 int local_flags = 0;
1129 /* Make sure users name has been specified */
1130 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1131 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1136 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1137 * so if that's what we're doing, skip the rest of the checks
1139 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1142 * If current user is not root, make sure old password has been specified
1143 * If REMOTE change, even root must provide old password
1145 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1146 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1147 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1151 /* If changing a users password on a remote hosts we have to know what host */
1152 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1153 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1157 /* Make sure new passwords have been specified */
1158 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1159 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1160 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1164 /* Make sure new passwords was typed correctly twice */
1165 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1166 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1171 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1172 host = cgi_variable(RHOST);
1173 } else if (am_root()) {
1180 * Set up the local flags.
1183 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1184 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1185 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1186 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1187 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1188 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1191 rslt = change_password(host,
1192 cgi_variable_nonull(SWAT_USER),
1193 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1196 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1199 printf("%s\n", _(" The passwd has been changed."));
1201 printf("%s\n", _(" The passwd for has NOT been changed."));
1208 /****************************************************************************
1209 display a password editing page
1210 ****************************************************************************/
1211 static void passwd_page(void)
1213 const char *new_name = cgi_user_name();
1215 if (!new_name) new_name = "";
1217 printf("<H2>%s</H2>\n", _("Server Password Management"));
1219 printf("<FORM name=\"swatform\" method=post>\n");
1221 printf("<table>\n");
1224 * Create all the dialog boxes for data collection
1226 printf("<tr><td> %s : </td>\n", _("User Name"));
1227 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1229 printf("<tr><td> %s : </td>\n", _("Old Password"));
1230 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1232 printf("<tr><td> %s : </td>\n", _("New Password"));
1233 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1234 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1235 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1236 printf("</table>\n");
1239 * Create all the control buttons for requesting action
1241 printf("<input type=submit name=%s value=\"%s\">\n",
1242 CHG_S_PASSWD_FLAG, _("Change Password"));
1243 if (demo_mode || am_root()) {
1244 printf("<input type=submit name=%s value=\"%s\">\n",
1245 ADD_USER_FLAG, _("Add New User"));
1246 printf("<input type=submit name=%s value=\"%s\">\n",
1247 DELETE_USER_FLAG, _("Delete User"));
1248 printf("<input type=submit name=%s value=\"%s\">\n",
1249 DISABLE_USER_FLAG, _("Disable User"));
1250 printf("<input type=submit name=%s value=\"%s\">\n",
1251 ENABLE_USER_FLAG, _("Enable User"));
1253 printf("<p></FORM>\n");
1256 * Do some work if change, add, disable or enable was
1257 * requested. It could be this is the first time through this
1258 * code, so there isn't anything to do. */
1259 if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1260 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1264 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1266 printf("<FORM name=\"swatform\" method=post>\n");
1268 printf("<table>\n");
1271 * Create all the dialog boxes for data collection
1273 printf("<tr><td> %s : </td>\n", _("User Name"));
1274 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1275 printf("<tr><td> %s : </td>\n", _("Old Password"));
1276 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1277 printf("<tr><td> %s : </td>\n", _("New Password"));
1278 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1279 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1280 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1281 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1282 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1287 * Create all the control buttons for requesting action
1289 printf("<input type=submit name=%s value=\"%s\">",
1290 CHG_R_PASSWD_FLAG, _("Change Password"));
1292 printf("<p></FORM>\n");
1295 * Do some work if a request has been made to change the
1296 * password somewhere other than the server. It could be this
1297 * is the first time through this code, so there isn't
1298 * anything to do. */
1299 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1305 /****************************************************************************
1306 display a printers editing page
1307 ****************************************************************************/
1308 static void printers_page(void)
1310 const char *share = cgi_variable("share");
1315 unsigned int parm_filter = FLAG_BASIC;
1318 snum = lp_servicenumber(share);
1320 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1322 printf("<H3>%s</H3>\n", _("Important Note:"));
1323 printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1324 printf("%s",_("are autoloaded printers from "));
1325 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1326 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1328 if (cgi_variable("Commit") && snum >= 0) {
1329 commit_parameters(snum);
1330 if (snum >= iNumNonAutoPrintServices)
1334 snum = lp_servicenumber(share);
1337 if (cgi_variable("Delete") && snum >= 0) {
1338 lp_remove_service(snum);
1344 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1345 snum = lp_servicenumber(share);
1346 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1348 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1349 snum = lp_servicenumber(share);
1350 lp_do_parameter(snum, "print ok", "Yes");
1352 snum = lp_servicenumber(share);
1356 printf("<FORM name=\"swatform\" method=post>\n");
1358 if ( cgi_variable("ViewMode") )
1359 mode = atoi(cgi_variable_nonull("ViewMode"));
1360 if ( cgi_variable("BasicMode"))
1362 if ( cgi_variable("AdvMode"))
1365 ViewModeBoxes( mode );
1368 parm_filter = FLAG_BASIC;
1371 parm_filter = FLAG_ADVANCED;
1374 printf("<table>\n");
1375 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1376 printf("<td><select name=\"share\">\n");
1377 if (snum < 0 || !lp_print_ok(snum))
1378 printf("<option value=\" \"> \n");
1379 for (i=0;i<lp_numservices();i++) {
1380 s = lp_servicename(i);
1381 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1382 if (i >= iNumNonAutoPrintServices)
1383 printf("<option %s value=\"%s\">[*]%s\n",
1384 (share && strcmp(share,s)==0)?"SELECTED":"",
1387 printf("<option %s value=\"%s\">%s\n",
1388 (share && strcmp(share,s)==0)?"SELECTED":"",
1392 printf("</select></td>");
1393 if (have_write_access) {
1394 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1397 printf("</table>\n");
1399 if (have_write_access) {
1400 printf("<table>\n");
1401 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1402 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1408 if (have_write_access) {
1409 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1411 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1416 printf("<table>\n");
1417 show_parameters(snum, 1, parm_filter, 1);
1418 printf("</table>\n");
1420 printf("</FORM>\n");
1424 when the _() translation macro is used there is no obvious place to free
1425 the resulting string and there is no easy way to give a static pointer.
1426 All we can do is rotate between some static buffers and hope a single d_printf()
1427 doesn't have more calls to _() than the number of buffers
1430 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1435 msgstr = lang_msg(msgid);
1440 ret = talloc_strdup(ctx, msgstr);
1442 lang_msg_free(msgstr);
1451 * main function for SWAT.
1453 int main(int argc, char *argv[])
1457 struct poptOption long_options[] = {
1459 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1460 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1464 TALLOC_CTX *frame = talloc_stackframe();
1467 umask(S_IWGRP | S_IWOTH);
1469 #if defined(HAVE_SET_AUTH_PARAMETERS)
1470 set_auth_parameters(argc, argv);
1471 #endif /* HAVE_SET_AUTH_PARAMETERS */
1473 /* just in case it goes wild ... */
1478 /* we don't want any SIGPIPE messages */
1479 BlockSignals(True,SIGPIPE);
1481 dbf = x_fopen("/dev/null", O_WRONLY, 0);
1482 if (!dbf) dbf = x_stderr;
1484 /* we don't want stderr screwing us up */
1486 open("/dev/null", O_WRONLY);
1488 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1490 /* Parse command line options */
1492 while(poptGetNextOpt(pc) != -1) { }
1494 poptFreeContext(pc);
1498 setup_logging(argv[0],False);
1501 iNumNonAutoPrintServices = lp_numservices();
1502 pcap_cache_reload(&load_printers);
1504 cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1508 cgi_load_variables();
1510 if (!file_exist(get_dyn_CONFIGFILE())) {
1511 have_read_access = True;
1512 have_write_access = True;
1514 /* check if the authenticated user has write access - if not then
1515 don't show write options */
1516 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1518 /* if the user doesn't have read access to smb.conf then
1519 don't let them view it */
1520 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1523 show_main_buttons();
1525 page = cgi_pathinfo();
1527 /* Root gets full functionality */
1528 if (have_read_access && strcmp(page, "globals")==0) {
1530 } else if (have_read_access && strcmp(page,"shares")==0) {
1532 } else if (have_read_access && strcmp(page,"printers")==0) {
1534 } else if (have_read_access && strcmp(page,"status")==0) {
1536 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1538 } else if (strcmp(page,"passwd")==0) {
1540 } else if (have_read_access && strcmp(page,"wizard")==0) {
1542 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1543 wizard_params_page();
1544 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {