1/*
2   Unix SMB/CIFS implementation.
3   Samba Web Administration Tool
4   Version 3.0.0
5   Copyright (C) Andrew Tridgell 1997-2002
6   Copyright (C) John H Terpstra 2002
7
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.
12
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.
17
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/>.
20*/
21
22/**
23 * @defgroup swat SWAT - Samba Web Administration Tool
24 * @{
25 * @file swat.c
26 *
27 * @brief Samba Web Administration Tool.
28 **/
29
30#include "includes.h"
31#include "web/swat_proto.h"
32
33static int demo_mode = False;
34static int passwd_only = False;
35static bool have_write_access = False;
36static bool have_read_access = False;
37static int iNumNonAutoPrintServices = 0;
38
39/*
40 * Password Management Globals
41 */
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"
53
54#define _(x) lang_msg_rotate(talloc_tos(),x)
55
56/****************************************************************************
57****************************************************************************/
58static int enum_index(int value, const struct enum_list *enumlist)
59{
60	int i;
61	for (i=0;enumlist[i].name;i++)
62		if (value == enumlist[i].value) break;
63	return(i);
64}
65
66static char *fix_backslash(const char *str)
67{
68	static char newstring[1024];
69	char *p = newstring;
70
71        while (*str) {
72                if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
73                else *p++ = *str;
74                ++str;
75        }
76	*p = '\0';
77	return newstring;
78}
79
80static const char *fix_quotes(TALLOC_CTX *ctx, const char *str)
81{
82	char *newstring = NULL;
83	char *p = NULL;
84	size_t newstring_len;
85	int quote_len = strlen("&quot;");
86
87	/* Count the number of quotes. */
88	newstring_len = 1;
89	p = (char *) str;
90	while (*p) {
91		if ( *p == '\"') {
92			newstring_len += quote_len;
93		} else {
94			newstring_len++;
95		}
96		++p;
97	}
98	newstring = TALLOC_ARRAY(ctx, char, newstring_len);
99	if (!newstring) {
100		return "";
101	}
102	for (p = newstring; *str; str++) {
103		if ( *str == '\"') {
104			strncpy( p, "&quot;", quote_len);
105			p += quote_len;
106		} else {
107			*p++ = *str;
108		}
109	}
110	*p = '\0';
111	return newstring;
112}
113
114static char *stripspaceupper(const char *str)
115{
116	static char newstring[1024];
117	char *p = newstring;
118
119	while (*str) {
120		if (*str != ' ') *p++ = toupper_ascii(*str);
121		++str;
122	}
123	*p = '\0';
124	return newstring;
125}
126
127static char *make_parm_name(const char *label)
128{
129	static char parmname[1024];
130	char *p = parmname;
131
132	while (*label) {
133		if (*label == ' ') *p++ = '_';
134		else *p++ = *label;
135		++label;
136	}
137	*p = '\0';
138	return parmname;
139}
140
141/****************************************************************************
142  include a lump of html in a page
143****************************************************************************/
144static int include_html(const char *fname)
145{
146	int fd;
147	char buf[1024];
148	int ret;
149
150	fd = web_open(fname, O_RDONLY, 0);
151
152	if (fd == -1) {
153		printf(_("ERROR: Can't open %s"), fname);
154		printf("\n");
155		return 0;
156	}
157
158	while ((ret = read(fd, buf, sizeof(buf))) > 0) {
159		if (write(1, buf, ret) == -1) {
160			break;
161		}
162	}
163
164	close(fd);
165	return 1;
166}
167
168/****************************************************************************
169  start the page with standard stuff
170****************************************************************************/
171static void print_header(void)
172{
173	if (!cgi_waspost()) {
174		printf("Expires: 0\r\n");
175	}
176	printf("Content-type: text/html\r\n\r\n");
177
178	if (!include_html("include/header.html")) {
179		printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
180		printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
181	}
182}
183
184/* *******************************************************************
185   show parameter label with translated name in the following form
186   because showing original and translated label in one line looks
187   too long, and showing translated label only is unusable for
188   heavy users.
189   -------------------------------
190   HELP       security   [combo box][button]
191   SECURITY
192   -------------------------------
193   (capital words are translated by gettext.)
194   if no translation is available, then same form as original is
195   used.
196   "i18n_translated_parm" class is used to change the color of the
197   translated parameter with CSS.
198   **************************************************************** */
199static const char *get_parm_translated(TALLOC_CTX *ctx,
200	const char* pAnchor, const char* pHelp, const char* pLabel)
201{
202	const char *pTranslated = _(pLabel);
203	char *output;
204	if(strcmp(pLabel, pTranslated) != 0) {
205		output = talloc_asprintf(ctx,
206		  "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s <br><span class=\"i18n_translated_parm\">%s</span>",
207		   pAnchor, pHelp, pLabel, pTranslated);
208		return output;
209	}
210	output = talloc_asprintf(ctx,
211	  "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
212	  pAnchor, pHelp, pLabel);
213	return output;
214}
215/****************************************************************************
216 finish off the page
217****************************************************************************/
218static void print_footer(void)
219{
220	if (!include_html("include/footer.html")) {
221		printf("\n</BODY>\n</HTML>\n");
222	}
223}
224
225/****************************************************************************
226  display one editable parameter in a form
227****************************************************************************/
228static void show_parameter(int snum, struct parm_struct *parm)
229{
230	int i;
231	void *ptr = parm->ptr;
232	char *utf8_s1, *utf8_s2;
233	size_t converted_size;
234	TALLOC_CTX *ctx = talloc_stackframe();
235
236	if (parm->p_class == P_LOCAL && snum >= 0) {
237		ptr = lp_local_ptr_by_snum(snum, ptr);
238	}
239
240	printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
241				stripspaceupper(parm->label), _("Help"), parm->label));
242	switch (parm->type) {
243	case P_CHAR:
244		printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
245		       make_parm_name(parm->label), *(char *)ptr);
246		printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
247			_("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
248		break;
249
250	case P_LIST:
251		printf("<input type=text size=40 name=\"parm_%s\" value=\"",
252			make_parm_name(parm->label));
253		if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
254			char **list = *(char ***)ptr;
255			for (;*list;list++) {
256				/* enclose in HTML encoded quotes if the string contains a space */
257				if ( strchr_m(*list, ' ') ) {
258					push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
259					push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
260					printf("&quot;%s&quot;%s", utf8_s1, utf8_s2);
261				} else {
262					push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
263					push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
264					printf("%s%s", utf8_s1, utf8_s2);
265				}
266				TALLOC_FREE(utf8_s1);
267				TALLOC_FREE(utf8_s2);
268			}
269		}
270		printf("\">");
271		printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
272			_("Set Default"), make_parm_name(parm->label));
273		if (parm->def.lvalue) {
274			char **list = (char **)(parm->def.lvalue);
275			for (; *list; list++) {
276				/* enclose in HTML encoded quotes if the string contains a space */
277				if ( strchr_m(*list, ' ') )
278					printf("&quot;%s&quot;%s", *list, ((*(list+1))?", ":""));
279				else
280					printf("%s%s", *list, ((*(list+1))?", ":""));
281			}
282		}
283		printf("\'\">");
284		break;
285
286	case P_STRING:
287	case P_USTRING:
288		push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
289		printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
290		       make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
291		TALLOC_FREE(utf8_s1);
292		printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
293			_("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
294		break;
295
296	case P_BOOL:
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");
300		printf("</select>");
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)?0:1);
303		break;
304
305	case P_BOOLREV:
306		printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
307		printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
308		printf("<option %s>No", (*(bool *)ptr)?"selected":"");
309		printf("</select>");
310		printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
311			_("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
312		break;
313
314	case P_INTEGER:
315		printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
316		printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
317			_("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
318		break;
319
320	case P_OCTAL: {
321		char *o;
322		o = octal_string(*(int *)ptr);
323		printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
324		       make_parm_name(parm->label), o);
325		TALLOC_FREE(o);
326		o = octal_string((int)(parm->def.ivalue));
327		printf("<input type=button value=\"%s\" "
328		       "onClick=\"swatform.parm_%s.value=\'%s\'\">",
329		       _("Set Default"), make_parm_name(parm->label), o);
330		TALLOC_FREE(o);
331		break;
332	}
333
334	case P_ENUM:
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);
339			}
340		}
341		printf("</select>");
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));
344		break;
345	case P_SEP:
346		break;
347	}
348	printf("</td></tr>\n");
349	TALLOC_FREE(ctx);
350}
351
352/****************************************************************************
353  display a set of parameters for a service
354****************************************************************************/
355static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
356{
357	int i = 0;
358	struct parm_struct *parm;
359	const char *heading = NULL;
360	const char *last_heading = NULL;
361
362	while ((parm = lp_next_parameter(snum, &i, allparameters))) {
363		if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
364			continue;
365		if (parm->p_class == P_SEPARATOR) {
366			heading = parm->label;
367			continue;
368		}
369		if (parm->flags & FLAG_HIDE) continue;
370		if (snum >= 0) {
371			if (printers & !(parm->flags & FLAG_PRINT)) continue;
372			if (!printers & !(parm->flags & FLAG_SHARE)) continue;
373		}
374
375		if (!( parm_filter & FLAG_ADVANCED )) {
376			if (!(parm->flags & FLAG_BASIC)) {
377					void *ptr = parm->ptr;
378
379				if (parm->p_class == P_LOCAL && snum >= 0) {
380					ptr = lp_local_ptr_by_snum(snum, ptr);
381				}
382
383				switch (parm->type) {
384				case P_CHAR:
385					if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
386					break;
387
388				case P_LIST:
389					if (!str_list_equal(*(const char ***)ptr,
390							    (const char **)(parm->def.lvalue))) continue;
391					break;
392
393				case P_STRING:
394				case P_USTRING:
395					if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
396					break;
397
398				case P_BOOL:
399				case P_BOOLREV:
400					if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
401					break;
402
403				case P_INTEGER:
404				case P_OCTAL:
405					if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
406					break;
407
408
409				case P_ENUM:
410					if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
411					break;
412				case P_SEP:
413					continue;
414					}
415			}
416			if (printers && !(parm->flags & FLAG_PRINT)) continue;
417		}
418
419		if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
420
421		if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
422
423		if (heading && heading != last_heading) {
424			printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
425			last_heading = heading;
426		}
427		show_parameter(snum, parm);
428	}
429}
430
431/****************************************************************************
432  load the smb.conf file into loadparm.
433****************************************************************************/
434static bool load_config(bool save_def)
435{
436	return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
437}
438
439/****************************************************************************
440  write a config file
441****************************************************************************/
442static void write_config(FILE *f, bool show_defaults)
443{
444	TALLOC_CTX *ctx = talloc_stackframe();
445
446	fprintf(f, "# Samba config file created using SWAT\n");
447	fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
448	fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
449
450	lp_dump(f, show_defaults, iNumNonAutoPrintServices);
451
452	TALLOC_FREE(ctx);
453}
454
455/****************************************************************************
456  save and reload the smb.conf config file
457****************************************************************************/
458static int save_reload(int snum)
459{
460	FILE *f;
461	struct stat st;
462
463	f = sys_fopen(get_dyn_CONFIGFILE(),"w");
464	if (!f) {
465		printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
466		printf("\n");
467		return 0;
468	}
469
470	/* just in case they have used the buggy xinetd to create the file */
471	if (fstat(fileno(f), &st) == 0 &&
472	    (st.st_mode & S_IWOTH)) {
473#if defined HAVE_FCHMOD
474		fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
475#else
476		chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
477#endif
478	}
479
480	write_config(f, False);
481	if (snum >= 0)
482		lp_dump_one(f, False, snum);
483	fclose(f);
484
485	lp_kill_all_services();
486
487	if (!load_config(False)) {
488                printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
489		printf("\n");
490                return 0;
491        }
492	iNumNonAutoPrintServices = lp_numservices();
493	load_printers();
494
495	return 1;
496}
497
498/****************************************************************************
499  commit one parameter
500****************************************************************************/
501static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
502{
503	int i;
504	char *s;
505
506	if (snum < 0 && parm->p_class == P_LOCAL) {
507		/* this handles the case where we are changing a local
508		   variable globally. We need to change the parameter in
509		   all shares where it is currently set to the default */
510		for (i=0;i<lp_numservices();i++) {
511			s = lp_servicename(i);
512			if (s && (*s) && lp_is_default(i, parm)) {
513				lp_do_parameter(i, parm->label, v);
514			}
515		}
516	}
517
518	lp_do_parameter(snum, parm->label, v);
519}
520
521/****************************************************************************
522  commit a set of parameters for a service
523****************************************************************************/
524static void commit_parameters(int snum)
525{
526	int i = 0;
527	struct parm_struct *parm;
528	char *label;
529	const char *v;
530
531	while ((parm = lp_next_parameter(snum, &i, 1))) {
532		if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
533			if ((v = cgi_variable(label)) != NULL) {
534				if (parm->flags & FLAG_HIDE)
535					continue;
536				commit_parameter(snum, parm, v);
537			}
538			SAFE_FREE(label);
539		}
540	}
541}
542
543/****************************************************************************
544  spit out the html for a link with an image
545****************************************************************************/
546static void image_link(const char *name, const char *hlink, const char *src)
547{
548	printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
549	       cgi_baseurl(), hlink, src, name);
550}
551
552/****************************************************************************
553  display the main navigation controls at the top of each page along
554  with a title
555****************************************************************************/
556static void show_main_buttons(void)
557{
558	char *p;
559
560	if ((p = cgi_user_name()) && strcmp(p, "root")) {
561		printf(_("Logged in as <b>%s</b>"), p);
562		printf("<p>\n");
563	}
564
565	image_link(_("Home"), "", "images/home.gif");
566	if (have_write_access) {
567		image_link(_("Globals"), "globals", "images/globals.gif");
568		image_link(_("Shares"), "shares", "images/shares.gif");
569		image_link(_("Printers"), "printers", "images/printers.gif");
570		image_link(_("Wizard"), "wizard", "images/wizard.gif");
571	}
572   /* root always gets all buttons, otherwise look for -P */
573	if ( have_write_access || (!passwd_only && have_read_access) ) {
574		image_link(_("Status"), "status", "images/status.gif");
575		image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
576	}
577	image_link(_("Password Management"), "passwd", "images/passwd.gif");
578
579	printf("<HR>\n");
580}
581
582/****************************************************************************
583 * Handle Display/Edit Mode CGI
584 ****************************************************************************/
585static void ViewModeBoxes(int mode)
586{
587	printf("<p>%s:&nbsp;\n", _("Current View Is"));
588	printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
589	printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
590	printf("<br>%s:&nbsp;\n", _("Change View To"));
591	printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
592	printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
593	printf("</p><br>\n");
594}
595
596/****************************************************************************
597  display a welcome page
598****************************************************************************/
599static void welcome_page(void)
600{
601	if (file_exist("help/welcome.html")) {
602		include_html("help/welcome.html");
603	} else {
604		include_html("help/welcome-no-samba-doc.html");
605	}
606}
607
608/****************************************************************************
609  display the current smb.conf
610****************************************************************************/
611static void viewconfig_page(void)
612{
613	int full_view=0;
614
615	if (cgi_variable("full_view")) {
616		full_view = 1;
617	}
618
619	printf("<H2>%s</H2>\n", _("Current Config"));
620	printf("<form method=post>\n");
621
622	if (full_view) {
623		printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
624	} else {
625		printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
626	}
627
628	printf("<p><pre>");
629	write_config(stdout, full_view);
630	printf("</pre>");
631	printf("</form>\n");
632}
633
634/****************************************************************************
635  second screen of the wizard ... Fetch Configuration Parameters
636****************************************************************************/
637static void wizard_params_page(void)
638{
639	unsigned int parm_filter = FLAG_WIZARD;
640
641	/* Here we first set and commit all the parameters that were selected
642 	   in the previous screen. */
643
644	printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
645
646	if (cgi_variable("Commit")) {
647		commit_parameters(GLOBAL_SECTION_SNUM);
648		save_reload(-1);
649	}
650
651	printf("<form name=\"swatform\" method=post action=wizard_params>\n");
652
653	if (have_write_access) {
654		printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
655	}
656
657	printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
658	printf("<p>\n");
659
660	printf("<table>\n");
661	show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
662	printf("</table>\n");
663	printf("</form>\n");
664}
665
666/****************************************************************************
667  Utility to just rewrite the smb.conf file - effectively just cleans it up
668****************************************************************************/
669static void rewritecfg_file(void)
670{
671	commit_parameters(GLOBAL_SECTION_SNUM);
672	save_reload(-1);
673	printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
674}
675
676/****************************************************************************
677  wizard to create/modify the smb.conf file
678****************************************************************************/
679static void wizard_page(void)
680{
681	/* Set some variables to collect data from smb.conf */
682	int role = 0;
683	int winstype = 0;
684	int have_home = -1;
685	int HomeExpo = 0;
686	int SerType = 0;
687
688	if (cgi_variable("Rewrite")) {
689		(void) rewritecfg_file();
690		return;
691	}
692
693	if (cgi_variable("GetWizardParams")){
694		(void) wizard_params_page();
695		return;
696	}
697
698	if (cgi_variable("Commit")){
699		SerType = atoi(cgi_variable_nonull("ServerType"));
700		winstype = atoi(cgi_variable_nonull("WINSType"));
701		have_home = lp_servicenumber(HOMES_NAME);
702		HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
703
704		/* Plain text passwords are too badly broken - use encrypted passwords only */
705		lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
706
707		switch ( SerType ){
708			case 0:
709				/* Stand-alone Server */
710				lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
711				lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
712				break;
713			case 1:
714				/* Domain Member */
715				lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
716				lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
717				break;
718			case 2:
719				/* Domain Controller */
720				lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
721				lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
722				break;
723		}
724		switch ( winstype ) {
725			case 0:
726				lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
727				lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
728				break;
729			case 1:
730				lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
731				lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
732				break;
733			case 2:
734				lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
735				lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
736				break;
737		}
738
739		/* Have to create Homes share? */
740		if ((HomeExpo == 1) && (have_home == -1)) {
741			const char *unix_share = HOMES_NAME;
742
743			load_config(False);
744			lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
745			have_home = lp_servicenumber(HOMES_NAME);
746			lp_do_parameter( have_home, "read only", "No");
747			lp_do_parameter( have_home, "valid users", "%S");
748			lp_do_parameter( have_home, "browseable", "No");
749			commit_parameters(have_home);
750			save_reload(have_home);
751		}
752
753		/* Need to Delete Homes share? */
754		if ((HomeExpo == 0) && (have_home != -1)) {
755			lp_remove_service(have_home);
756			have_home = -1;
757		}
758
759		commit_parameters(GLOBAL_SECTION_SNUM);
760		save_reload(-1);
761	}
762	else
763	{
764		/* Now determine smb.conf WINS settings */
765		if (lp_wins_support())
766			winstype = 1;
767		if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
768 		        winstype = 2;
769
770		/* Do we have a homes share? */
771		have_home = lp_servicenumber(HOMES_NAME);
772	}
773	if ((winstype == 2) && lp_wins_support())
774		winstype = 3;
775
776	role = lp_server_role();
777
778	/* Here we go ... */
779	printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
780	printf("<form method=post action=wizard>\n");
781
782	if (have_write_access) {
783		printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
784		printf("%s", _("The same will happen if you press the commit button."));
785		printf("<br><br>\n");
786		printf("<center>");
787		printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
788		printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
789		printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
790		printf("</center>\n");
791	}
792
793	printf("<hr>");
794	printf("<center><table border=0>");
795	printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
796	printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
797	printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
798	printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
799	printf("</tr>\n");
800	if (role == ROLE_DOMAIN_BDC) {
801		printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
802	}
803	printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
804	printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
805	printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
806	printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
807	printf("</tr>\n");
808	printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
809
810	/* Print out the list of wins servers */
811	if(lp_wins_server_list()) {
812		int i;
813		const char **wins_servers = lp_wins_server_list();
814		for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
815	}
816
817	printf("\"></td></tr>\n");
818	if (winstype == 3) {
819		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"));
820		printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
821	}
822	printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
823	printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
824	printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
825	printf("<td></td></tr>\n");
826
827	/* Enable this when we are ready ....
828	 * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
829	 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
830	 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
831	 * printf("<td></td></tr>\n");
832	 */
833
834	printf("</table></center>");
835	printf("<hr>");
836
837	printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
838	printf("</form>\n");
839}
840
841
842/****************************************************************************
843  display a globals editing page
844****************************************************************************/
845static void globals_page(void)
846{
847	unsigned int parm_filter = FLAG_BASIC;
848	int mode = 0;
849
850	printf("<H2>%s</H2>\n", _("Global Parameters"));
851
852	if (cgi_variable("Commit")) {
853		commit_parameters(GLOBAL_SECTION_SNUM);
854		save_reload(-1);
855	}
856
857	if ( cgi_variable("ViewMode") )
858		mode = atoi(cgi_variable_nonull("ViewMode"));
859	if ( cgi_variable("BasicMode"))
860		mode = 0;
861	if ( cgi_variable("AdvMode"))
862		mode = 1;
863
864	printf("<form name=\"swatform\" method=post action=globals>\n");
865
866	ViewModeBoxes( mode );
867	switch ( mode ) {
868		case 0:
869			parm_filter = FLAG_BASIC;
870			break;
871		case 1:
872			parm_filter = FLAG_ADVANCED;
873			break;
874	}
875	printf("<br>\n");
876	if (have_write_access) {
877		printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
878			_("Commit Changes"));
879	}
880
881	printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
882		 _("Reset Values"));
883
884	printf("<p>\n");
885	printf("<table>\n");
886	show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
887	printf("</table>\n");
888	printf("</form>\n");
889}
890
891/****************************************************************************
892  display a shares editing page. share is in unix codepage,
893****************************************************************************/
894static void shares_page(void)
895{
896	const char *share = cgi_variable("share");
897	char *s;
898	char *utf8_s;
899	int snum = -1;
900	int i;
901	int mode = 0;
902	unsigned int parm_filter = FLAG_BASIC;
903	size_t converted_size;
904
905	if (share)
906		snum = lp_servicenumber(share);
907
908	printf("<H2>%s</H2>\n", _("Share Parameters"));
909
910	if (cgi_variable("Commit") && snum >= 0) {
911		commit_parameters(snum);
912		save_reload(-1);
913		snum = lp_servicenumber(share);
914	}
915
916	if (cgi_variable("Delete") && snum >= 0) {
917		lp_remove_service(snum);
918		save_reload(-1);
919		share = NULL;
920		snum = -1;
921	}
922
923	if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
924		snum = lp_servicenumber(share);
925		if (snum < 0) {
926			load_config(False);
927			lp_copy_service(GLOBAL_SECTION_SNUM, share);
928			snum = lp_servicenumber(share);
929			save_reload(snum);
930			snum = lp_servicenumber(share);
931		}
932	}
933
934	printf("<FORM name=\"swatform\" method=post>\n");
935
936	printf("<table>\n");
937
938	if ( cgi_variable("ViewMode") )
939		mode = atoi(cgi_variable_nonull("ViewMode"));
940	if ( cgi_variable("BasicMode"))
941		mode = 0;
942	if ( cgi_variable("AdvMode"))
943		mode = 1;
944
945	ViewModeBoxes( mode );
946	switch ( mode ) {
947		case 0:
948			parm_filter = FLAG_BASIC;
949			break;
950		case 1:
951			parm_filter = FLAG_ADVANCED;
952			break;
953	}
954	printf("<br><tr>\n");
955	printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
956	printf("<td><select name=share>\n");
957	if (snum < 0)
958		printf("<option value=\" \"> \n");
959	for (i=0;i<lp_numservices();i++) {
960		s = lp_servicename(i);
961		if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
962			push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
963			printf("<option %s value=\"%s\">%s\n",
964			       (share && strcmp(share,s)==0)?"SELECTED":"",
965			       utf8_s, utf8_s);
966			TALLOC_FREE(utf8_s);
967		}
968	}
969	printf("</select></td>\n");
970	if (have_write_access) {
971		printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
972	}
973	printf("</tr>\n");
974	printf("</table>");
975	printf("<table>");
976	if (have_write_access) {
977		printf("<tr>\n");
978		printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
979		printf("<td><input type=text size=30 name=newshare></td></tr>\n");
980	}
981	printf("</table>");
982
983
984	if (snum >= 0) {
985		if (have_write_access) {
986			printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
987		}
988
989		printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
990		printf("<p>\n");
991	}
992
993	if (snum >= 0) {
994		printf("<table>\n");
995		show_parameters(snum, 1, parm_filter, 0);
996		printf("</table>\n");
997	}
998
999	printf("</FORM>\n");
1000}
1001
1002/*************************************************************
1003change a password either locally or remotely
1004*************************************************************/
1005static bool change_password(const char *remote_machine, const char *user_name,
1006			    const char *old_passwd, const char *new_passwd,
1007				int local_flags)
1008{
1009	NTSTATUS ret;
1010	char *err_str = NULL;
1011	char *msg_str = NULL;
1012
1013	if (demo_mode) {
1014		printf("%s\n<p>", _("password change in demo mode rejected"));
1015		return False;
1016	}
1017
1018	if (remote_machine != NULL) {
1019		ret = remote_password_change(remote_machine, user_name,
1020					     old_passwd, new_passwd, &err_str);
1021		if (err_str != NULL)
1022			printf("%s\n<p>", err_str);
1023		SAFE_FREE(err_str);
1024		return NT_STATUS_IS_OK(ret);
1025	}
1026
1027	if(!initialize_password_db(True, NULL)) {
1028		printf("%s\n<p>", _("Can't setup password database vectors."));
1029		return False;
1030	}
1031
1032	ret = local_password_change(user_name, local_flags, new_passwd,
1033					&err_str, &msg_str);
1034
1035	if(msg_str)
1036		printf("%s\n<p>", msg_str);
1037	if(err_str)
1038		printf("%s\n<p>", err_str);
1039
1040	SAFE_FREE(msg_str);
1041	SAFE_FREE(err_str);
1042	return NT_STATUS_IS_OK(ret);
1043}
1044
1045/****************************************************************************
1046  do the stuff required to add or change a password
1047****************************************************************************/
1048static void chg_passwd(void)
1049{
1050	const char *host;
1051	bool rslt;
1052	int local_flags = 0;
1053
1054	/* Make sure users name has been specified */
1055	if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1056		printf("<p>%s\n", _(" Must specify \"User Name\" "));
1057		return;
1058	}
1059
1060	/*
1061	 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1062	 * so if that's what we're doing, skip the rest of the checks
1063	 */
1064	if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1065
1066		/*
1067		 * If current user is not root, make sure old password has been specified
1068		 * If REMOTE change, even root must provide old password
1069		 */
1070		if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1071		    ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1072			printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1073			return;
1074		}
1075
1076		/* If changing a users password on a remote hosts we have to know what host */
1077		if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1078			printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1079			return;
1080		}
1081
1082		/* Make sure new passwords have been specified */
1083		if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1084		    (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1085			printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1086			return;
1087		}
1088
1089		/* Make sure new passwords was typed correctly twice */
1090		if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1091			printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1092			return;
1093		}
1094	}
1095
1096	if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1097		host = cgi_variable(RHOST);
1098	} else if (am_root()) {
1099		host = NULL;
1100	} else {
1101		host = "127.0.0.1";
1102	}
1103
1104	/*
1105	 * Set up the local flags.
1106	 */
1107
1108	local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1109	local_flags |= (cgi_variable(ADD_USER_FLAG) ?  LOCAL_SET_PASSWORD : 0);
1110	local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1111	local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1112	local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1113	local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1114
1115
1116	rslt = change_password(host,
1117			       cgi_variable_nonull(SWAT_USER),
1118			       cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1119				   local_flags);
1120
1121	if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1122		printf("<p>");
1123		if (rslt == True) {
1124			printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER));
1125			printf("\n");
1126		} else {
1127			printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER));
1128			printf("\n");
1129		}
1130	}
1131
1132	return;
1133}
1134
1135/****************************************************************************
1136  display a password editing page
1137****************************************************************************/
1138static void passwd_page(void)
1139{
1140	const char *new_name = cgi_user_name();
1141
1142	/*
1143	 * After the first time through here be nice. If the user
1144	 * changed the User box text to another users name, remember it.
1145	 */
1146	if (cgi_variable(SWAT_USER)) {
1147		new_name = cgi_variable_nonull(SWAT_USER);
1148	}
1149
1150	if (!new_name) new_name = "";
1151
1152	printf("<H2>%s</H2>\n", _("Server Password Management"));
1153
1154	printf("<FORM name=\"swatform\" method=post>\n");
1155
1156	printf("<table>\n");
1157
1158	/*
1159	 * Create all the dialog boxes for data collection
1160	 */
1161	printf("<tr><td> %s : </td>\n", _("User Name"));
1162	printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1163	if (!am_root()) {
1164		printf("<tr><td> %s : </td>\n", _("Old Password"));
1165		printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1166	}
1167	printf("<tr><td> %s : </td>\n", _("New Password"));
1168	printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1169	printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1170	printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1171	printf("</table>\n");
1172
1173	/*
1174	 * Create all the control buttons for requesting action
1175	 */
1176	printf("<input type=submit name=%s value=\"%s\">\n",
1177	       CHG_S_PASSWD_FLAG, _("Change Password"));
1178	if (demo_mode || am_root()) {
1179		printf("<input type=submit name=%s value=\"%s\">\n",
1180		       ADD_USER_FLAG, _("Add New User"));
1181		printf("<input type=submit name=%s value=\"%s\">\n",
1182		       DELETE_USER_FLAG, _("Delete User"));
1183		printf("<input type=submit name=%s value=\"%s\">\n",
1184		       DISABLE_USER_FLAG, _("Disable User"));
1185		printf("<input type=submit name=%s value=\"%s\">\n",
1186		       ENABLE_USER_FLAG, _("Enable User"));
1187	}
1188	printf("<p></FORM>\n");
1189
1190	/*
1191	 * Do some work if change, add, disable or enable was
1192	 * requested. It could be this is the first time through this
1193	 * code, so there isn't anything to do.  */
1194	if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1195	    (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1196		chg_passwd();
1197	}
1198
1199	printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1200
1201	printf("<FORM name=\"swatform\" method=post>\n");
1202
1203	printf("<table>\n");
1204
1205	/*
1206	 * Create all the dialog boxes for data collection
1207	 */
1208	printf("<tr><td> %s : </td>\n", _("User Name"));
1209	printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1210	printf("<tr><td> %s : </td>\n", _("Old Password"));
1211	printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1212	printf("<tr><td> %s : </td>\n", _("New Password"));
1213	printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1214	printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1215	printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1216	printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1217	printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1218
1219	printf("</table>");
1220
1221	/*
1222	 * Create all the control buttons for requesting action
1223	 */
1224	printf("<input type=submit name=%s value=\"%s\">",
1225	       CHG_R_PASSWD_FLAG, _("Change Password"));
1226
1227	printf("<p></FORM>\n");
1228
1229	/*
1230	 * Do some work if a request has been made to change the
1231	 * password somewhere other than the server. It could be this
1232	 * is the first time through this code, so there isn't
1233	 * anything to do.  */
1234	if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1235		chg_passwd();
1236	}
1237
1238}
1239
1240/****************************************************************************
1241  display a printers editing page
1242****************************************************************************/
1243static void printers_page(void)
1244{
1245	const char *share = cgi_variable("share");
1246	char *s;
1247	int snum=-1;
1248	int i;
1249	int mode = 0;
1250	unsigned int parm_filter = FLAG_BASIC;
1251
1252	if (share)
1253		snum = lp_servicenumber(share);
1254
1255        printf("<H2>%s</H2>\n", _("Printer Parameters"));
1256
1257        printf("<H3>%s</H3>\n", _("Important Note:"));
1258        printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1259        printf("%s",_("are autoloaded printers from "));
1260        printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1261        printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1262
1263	if (cgi_variable("Commit") && snum >= 0) {
1264		commit_parameters(snum);
1265		if (snum >= iNumNonAutoPrintServices)
1266		    save_reload(snum);
1267		else
1268		    save_reload(-1);
1269		snum = lp_servicenumber(share);
1270	}
1271
1272	if (cgi_variable("Delete") && snum >= 0) {
1273		lp_remove_service(snum);
1274		save_reload(-1);
1275		share = NULL;
1276		snum = -1;
1277	}
1278
1279	if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1280		snum = lp_servicenumber(share);
1281		if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1282			load_config(False);
1283			lp_copy_service(GLOBAL_SECTION_SNUM, share);
1284			snum = lp_servicenumber(share);
1285			lp_do_parameter(snum, "print ok", "Yes");
1286			save_reload(snum);
1287			snum = lp_servicenumber(share);
1288		}
1289	}
1290
1291	printf("<FORM name=\"swatform\" method=post>\n");
1292
1293	if ( cgi_variable("ViewMode") )
1294		mode = atoi(cgi_variable_nonull("ViewMode"));
1295        if ( cgi_variable("BasicMode"))
1296                mode = 0;
1297        if ( cgi_variable("AdvMode"))
1298                mode = 1;
1299
1300	ViewModeBoxes( mode );
1301	switch ( mode ) {
1302		case 0:
1303			parm_filter = FLAG_BASIC;
1304			break;
1305		case 1:
1306			parm_filter = FLAG_ADVANCED;
1307			break;
1308	}
1309	printf("<table>\n");
1310	printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1311	printf("<td><select name=\"share\">\n");
1312	if (snum < 0 || !lp_print_ok(snum))
1313		printf("<option value=\" \"> \n");
1314	for (i=0;i<lp_numservices();i++) {
1315		s = lp_servicename(i);
1316		if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1317                    if (i >= iNumNonAutoPrintServices)
1318                        printf("<option %s value=\"%s\">[*]%s\n",
1319                               (share && strcmp(share,s)==0)?"SELECTED":"",
1320                               s, s);
1321                    else
1322			printf("<option %s value=\"%s\">%s\n",
1323			       (share && strcmp(share,s)==0)?"SELECTED":"",
1324			       s, s);
1325		}
1326	}
1327	printf("</select></td>");
1328	if (have_write_access) {
1329		printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1330	}
1331	printf("</tr>");
1332	printf("</table>\n");
1333
1334	if (have_write_access) {
1335		printf("<table>\n");
1336		printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1337		printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1338		printf("</table>");
1339	}
1340
1341
1342	if (snum >= 0) {
1343		if (have_write_access) {
1344			printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1345		}
1346		printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1347		printf("<p>\n");
1348	}
1349
1350	if (snum >= 0) {
1351		printf("<table>\n");
1352		show_parameters(snum, 1, parm_filter, 1);
1353		printf("</table>\n");
1354	}
1355	printf("</FORM>\n");
1356}
1357
1358/*
1359  when the _() translation macro is used there is no obvious place to free
1360  the resulting string and there is no easy way to give a static pointer.
1361  All we can do is rotate between some static buffers and hope a single d_printf()
1362  doesn't have more calls to _() than the number of buffers
1363*/
1364
1365const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1366{
1367	const char *msgstr;
1368	const char *ret;
1369
1370	msgstr = lang_msg(msgid);
1371	if (!msgstr) {
1372		return msgid;
1373	}
1374
1375	ret = talloc_strdup(ctx, msgstr);
1376
1377	lang_msg_free(msgstr);
1378	if (!ret) {
1379		return msgid;
1380	}
1381
1382	return ret;
1383}
1384
1385/**
1386 * main function for SWAT.
1387 **/
1388 int main(int argc, char *argv[])
1389{
1390	const char *page;
1391	poptContext pc;
1392	struct poptOption long_options[] = {
1393		POPT_AUTOHELP
1394		{ "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1395        	{ "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1396		POPT_COMMON_SAMBA
1397		POPT_TABLEEND
1398	};
1399	TALLOC_CTX *frame = talloc_stackframe();
1400
1401	fault_setup(NULL);
1402	umask(S_IWGRP | S_IWOTH);
1403
1404#if defined(HAVE_SET_AUTH_PARAMETERS)
1405	set_auth_parameters(argc, argv);
1406#endif /* HAVE_SET_AUTH_PARAMETERS */
1407
1408	/* just in case it goes wild ... */
1409	alarm(300);
1410
1411	setlinebuf(stdout);
1412
1413	/* we don't want any SIGPIPE messages */
1414	BlockSignals(True,SIGPIPE);
1415
1416	dbf = x_fopen("/dev/null", O_WRONLY, 0);
1417	if (!dbf) dbf = x_stderr;
1418
1419	/* we don't want stderr screwing us up */
1420	close(2);
1421	open("/dev/null", O_WRONLY);
1422
1423	pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1424
1425	/* Parse command line options */
1426
1427	while(poptGetNextOpt(pc) != -1) { }
1428
1429	poptFreeContext(pc);
1430
1431	load_case_tables();
1432
1433	setup_logging(argv[0],False);
1434	load_config(True);
1435	load_interfaces();
1436	iNumNonAutoPrintServices = lp_numservices();
1437	load_printers();
1438
1439	cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1440
1441	print_header();
1442
1443	cgi_load_variables();
1444
1445	if (!file_exist(get_dyn_CONFIGFILE())) {
1446		have_read_access = True;
1447		have_write_access = True;
1448	} else {
1449		/* check if the authenticated user has write access - if not then
1450		   don't show write options */
1451		have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1452
1453		/* if the user doesn't have read access to smb.conf then
1454		   don't let them view it */
1455		have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1456	}
1457
1458	show_main_buttons();
1459
1460	page = cgi_pathinfo();
1461
1462	/* Root gets full functionality */
1463	if (have_read_access && strcmp(page, "globals")==0) {
1464		globals_page();
1465	} else if (have_read_access && strcmp(page,"shares")==0) {
1466		shares_page();
1467	} else if (have_read_access && strcmp(page,"printers")==0) {
1468		printers_page();
1469	} else if (have_read_access && strcmp(page,"status")==0) {
1470		status_page();
1471	} else if (have_read_access && strcmp(page,"viewconfig")==0) {
1472		viewconfig_page();
1473	} else if (strcmp(page,"passwd")==0) {
1474		passwd_page();
1475	} else if (have_read_access && strcmp(page,"wizard")==0) {
1476		wizard_page();
1477	} else if (have_read_access && strcmp(page,"wizard_params")==0) {
1478		wizard_params_page();
1479	} else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1480		rewritecfg_file();
1481	} else {
1482		welcome_page();
1483	}
1484
1485	print_footer();
1486
1487	TALLOC_FREE(frame);
1488	return 0;
1489}
1490
1491/** @} **/
1492