s3 swat: Add XSRF protection to password page
[Samba.git] / source3 / web / swat.c
blob8f64a5426f88947d36b4d33cdf7700267129246f
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
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/>.
22 /**
23 * @defgroup swat SWAT - Samba Web Administration Tool
24 * @{
25 * @file swat.c
27 * @brief Samba Web Administration Tool.
28 **/
30 #include "includes.h"
31 #include "system/filesys.h"
32 #include "popt_common.h"
33 #include "web/swat_proto.h"
34 #include "printing/pcap.h"
35 #include "printing/load.h"
36 #include "passdb.h"
37 #include "intl/lang_tdb.h"
38 #include "../lib/crypto/md5.h"
39 #include "lib/param/loadparm.h"
41 static int demo_mode = False;
42 static int passwd_only = False;
43 static bool have_write_access = False;
44 static bool have_read_access = False;
45 static int iNumNonAutoPrintServices = 0;
48 * Password Management Globals
50 #define SWAT_USER "username"
51 #define OLD_PSWD "old_passwd"
52 #define NEW_PSWD "new_passwd"
53 #define NEW2_PSWD "new2_passwd"
54 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
55 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
56 #define ADD_USER_FLAG "add_user_flag"
57 #define DELETE_USER_FLAG "delete_user_flag"
58 #define DISABLE_USER_FLAG "disable_user_flag"
59 #define ENABLE_USER_FLAG "enable_user_flag"
60 #define RHOST "remote_host"
61 #define XSRF_TOKEN "xsrf"
63 #define _(x) lang_msg_rotate(talloc_tos(),x)
65 /****************************************************************************
66 ****************************************************************************/
67 static int enum_index(int value, const struct enum_list *enumlist)
69 int i;
70 for (i=0;enumlist[i].name;i++)
71 if (value == enumlist[i].value) break;
72 return(i);
75 static char *fix_backslash(const char *str)
77 static char newstring[1024];
78 char *p = newstring;
80 while (*str) {
81 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
82 else *p++ = *str;
83 ++str;
85 *p = '\0';
86 return newstring;
89 static const char *fix_quotes(TALLOC_CTX *ctx, char *str)
91 char *newstring = NULL;
92 char *p = NULL;
93 size_t newstring_len;
94 int quote_len = strlen("&quot;");
96 /* Count the number of quotes. */
97 newstring_len = 1;
98 p = (char *) str;
99 while (*p) {
100 if ( *p == '\"') {
101 newstring_len += quote_len;
102 } else {
103 newstring_len++;
105 ++p;
107 newstring = talloc_array(ctx, char, newstring_len);
108 if (!newstring) {
109 return "";
111 for (p = newstring; *str; str++) {
112 if ( *str == '\"') {
113 strncpy( p, "&quot;", quote_len);
114 p += quote_len;
115 } else {
116 *p++ = *str;
119 *p = '\0';
120 return newstring;
123 static char *stripspaceupper(const char *str)
125 static char newstring[1024];
126 char *p = newstring;
128 while (*str) {
129 if (*str != ' ') *p++ = toupper_m(*str);
130 ++str;
132 *p = '\0';
133 return newstring;
136 static char *make_parm_name(const char *label)
138 static char parmname[1024];
139 char *p = parmname;
141 while (*label) {
142 if (*label == ' ') *p++ = '_';
143 else *p++ = *label;
144 ++label;
146 *p = '\0';
147 return parmname;
150 void get_xsrf_token(const char *username, const char *pass,
151 const char *formname, char token_str[33])
153 struct MD5Context md5_ctx;
154 uint8_t token[16];
155 int i;
157 token_str[0] = '\0';
158 ZERO_STRUCT(md5_ctx);
159 MD5Init(&md5_ctx);
161 MD5Update(&md5_ctx, (uint8_t *)formname, strlen(formname));
162 if (username != NULL) {
163 MD5Update(&md5_ctx, (uint8_t *)username, strlen(username));
165 if (pass != NULL) {
166 MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
169 MD5Final(token, &md5_ctx);
171 for(i = 0; i < sizeof(token); i++) {
172 char tmp[3];
174 snprintf(tmp, sizeof(tmp), "%02x", token[i]);
175 strncat(token_str, tmp, sizeof(tmp));
179 void print_xsrf_token(const char *username, const char *pass,
180 const char *formname)
182 char token[33];
184 get_xsrf_token(username, pass, formname, token);
185 printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
186 XSRF_TOKEN, token);
190 bool verify_xsrf_token(const char *formname)
192 char expected[33];
193 const char *username = cgi_user_name();
194 const char *pass = cgi_user_pass();
195 const char *token = cgi_variable_nonull(XSRF_TOKEN);
197 get_xsrf_token(username, pass, formname, expected);
198 return (strncmp(expected, token, sizeof(expected)) == 0);
202 /****************************************************************************
203 include a lump of html in a page
204 ****************************************************************************/
205 static int include_html(const char *fname)
207 int fd;
208 char buf[1024];
209 int ret;
211 fd = web_open(fname, O_RDONLY, 0);
213 if (fd == -1) {
214 printf(_("ERROR: Can't open %s"), fname);
215 printf("\n");
216 return 0;
219 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
220 if (write(1, buf, ret) == -1) {
221 break;
225 close(fd);
226 return 1;
229 /****************************************************************************
230 start the page with standard stuff
231 ****************************************************************************/
232 static void print_header(void)
234 if (!cgi_waspost()) {
235 printf("Expires: 0\r\n");
237 printf("Content-type: text/html\r\n\r\n");
239 if (!include_html("include/header.html")) {
240 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
241 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
245 /* *******************************************************************
246 show parameter label with translated name in the following form
247 because showing original and translated label in one line looks
248 too long, and showing translated label only is unusable for
249 heavy users.
250 -------------------------------
251 HELP security [combo box][button]
252 SECURITY
253 -------------------------------
254 (capital words are translated by gettext.)
255 if no translation is available, then same form as original is
256 used.
257 "i18n_translated_parm" class is used to change the color of the
258 translated parameter with CSS.
259 **************************************************************** */
260 static const char *get_parm_translated(TALLOC_CTX *ctx,
261 const char* pAnchor, const char* pHelp, const char* pLabel)
263 const char *pTranslated = _(pLabel);
264 char *output;
265 if(strcmp(pLabel, pTranslated) != 0) {
266 output = talloc_asprintf(ctx,
267 "<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>",
268 pAnchor, pHelp, pLabel, pTranslated);
269 return output;
271 output = talloc_asprintf(ctx,
272 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
273 pAnchor, pHelp, pLabel);
274 return output;
276 /****************************************************************************
277 finish off the page
278 ****************************************************************************/
279 static void print_footer(void)
281 if (!include_html("include/footer.html")) {
282 printf("\n</BODY>\n</HTML>\n");
286 /****************************************************************************
287 display one editable parameter in a form
288 ****************************************************************************/
289 static void show_parameter(int snum, struct parm_struct *parm)
291 int i;
292 void *ptr;
293 char *utf8_s1, *utf8_s2;
294 size_t converted_size;
295 TALLOC_CTX *ctx = talloc_stackframe();
297 if (parm->p_class == P_LOCAL && snum >= 0) {
298 ptr = lp_local_ptr_by_snum(snum, parm);
299 } else {
300 ptr = lp_parm_ptr(NULL, parm);
303 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
304 stripspaceupper(parm->label), _("Help"), parm->label));
305 switch (parm->type) {
306 case P_CHAR:
307 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
308 make_parm_name(parm->label), *(char *)ptr);
309 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
310 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
311 break;
313 case P_LIST:
314 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
315 make_parm_name(parm->label));
316 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
317 char **list = *(char ***)ptr;
318 for (;*list;list++) {
319 /* enclose in HTML encoded quotes if the string contains a space */
320 if ( strchr_m(*list, ' ') ) {
321 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
322 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
323 printf("&quot;%s&quot;%s", utf8_s1, utf8_s2);
324 } else {
325 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
326 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
327 printf("%s%s", utf8_s1, utf8_s2);
329 TALLOC_FREE(utf8_s1);
330 TALLOC_FREE(utf8_s2);
333 printf("\">");
334 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
335 _("Set Default"), make_parm_name(parm->label));
336 if (parm->def.lvalue) {
337 char **list = (char **)(parm->def.lvalue);
338 for (; *list; list++) {
339 /* enclose in HTML encoded quotes if the string contains a space */
340 if ( strchr_m(*list, ' ') )
341 printf("&quot;%s&quot;%s", *list, ((*(list+1))?", ":""));
342 else
343 printf("%s%s", *list, ((*(list+1))?", ":""));
346 printf("\'\">");
347 break;
349 case P_STRING:
350 case P_USTRING:
351 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
352 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
353 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
354 TALLOC_FREE(utf8_s1);
355 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
356 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
357 break;
359 case P_BOOL:
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");
363 printf("</select>");
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)?0:1);
366 break;
368 case P_BOOLREV:
369 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
370 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
371 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
372 printf("</select>");
373 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
374 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
375 break;
377 case P_INTEGER:
378 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
379 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
380 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
381 break;
383 case P_OCTAL: {
384 char *o;
385 o = octal_string(*(int *)ptr);
386 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
387 make_parm_name(parm->label), o);
388 TALLOC_FREE(o);
389 o = octal_string((int)(parm->def.ivalue));
390 printf("<input type=button value=\"%s\" "
391 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
392 _("Set Default"), make_parm_name(parm->label), o);
393 TALLOC_FREE(o);
394 break;
397 case P_ENUM:
398 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
399 for (i=0;parm->enum_list[i].name;i++) {
400 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
401 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
404 printf("</select>");
405 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
406 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
407 break;
408 case P_SEP:
409 break;
411 printf("</td></tr>\n");
412 TALLOC_FREE(ctx);
415 /****************************************************************************
416 display a set of parameters for a service
417 ****************************************************************************/
418 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
420 int i = 0;
421 struct parm_struct *parm;
422 const char *heading = NULL;
423 const char *last_heading = NULL;
425 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
426 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
427 continue;
428 if (parm->p_class == P_SEPARATOR) {
429 heading = parm->label;
430 continue;
432 if (parm->flags & FLAG_HIDE) continue;
433 if (snum >= 0) {
434 if (printers & !(parm->flags & FLAG_PRINT)) continue;
435 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
438 if (!( parm_filter & FLAG_ADVANCED )) {
439 if (!(parm->flags & FLAG_BASIC)) {
440 void *ptr;
441 if (parm->p_class == P_LOCAL && snum >= 0) {
442 ptr = lp_local_ptr_by_snum(snum, parm);
443 } else {
444 ptr = lp_parm_ptr(NULL, parm);
447 switch (parm->type) {
448 case P_CHAR:
449 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
450 break;
452 case P_LIST:
453 if (!str_list_equal(*(const char ***)ptr,
454 (const char **)(parm->def.lvalue))) continue;
455 break;
457 case P_STRING:
458 case P_USTRING:
459 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
460 break;
462 case P_BOOL:
463 case P_BOOLREV:
464 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
465 break;
467 case P_INTEGER:
468 case P_OCTAL:
469 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
470 break;
473 case P_ENUM:
474 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
475 break;
476 case P_SEP:
477 continue;
480 if (printers && !(parm->flags & FLAG_PRINT)) continue;
483 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
485 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
487 if (heading && heading != last_heading) {
488 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
489 last_heading = heading;
491 show_parameter(snum, parm);
495 /****************************************************************************
496 load the smb.conf file into loadparm.
497 ****************************************************************************/
498 static bool load_config(bool save_def)
500 return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
503 /****************************************************************************
504 write a config file
505 ****************************************************************************/
506 static void write_config(FILE *f, bool show_defaults)
508 TALLOC_CTX *ctx = talloc_stackframe();
510 fprintf(f, "# Samba config file created using SWAT\n");
511 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
512 fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
514 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
516 TALLOC_FREE(ctx);
519 /****************************************************************************
520 save and reload the smb.conf config file
521 ****************************************************************************/
522 static int save_reload(int snum)
524 FILE *f;
525 struct stat st;
527 f = sys_fopen(get_dyn_CONFIGFILE(),"w");
528 if (!f) {
529 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
530 printf("\n");
531 return 0;
534 /* just in case they have used the buggy xinetd to create the file */
535 if (fstat(fileno(f), &st) == 0 &&
536 (st.st_mode & S_IWOTH)) {
537 #if defined HAVE_FCHMOD
538 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
539 #else
540 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
541 #endif
544 write_config(f, False);
545 if (snum >= 0)
546 lp_dump_one(f, False, snum);
547 fclose(f);
549 lp_kill_all_services();
551 if (!load_config(False)) {
552 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
553 printf("\n");
554 return 0;
556 iNumNonAutoPrintServices = lp_numservices();
557 if (pcap_cache_loaded()) {
558 load_printers(server_event_context(),
559 server_messaging_context());
562 return 1;
565 /****************************************************************************
566 commit one parameter
567 ****************************************************************************/
568 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
570 int i;
571 char *s;
573 if (snum < 0 && parm->p_class == P_LOCAL) {
574 /* this handles the case where we are changing a local
575 variable globally. We need to change the parameter in
576 all shares where it is currently set to the default */
577 for (i=0;i<lp_numservices();i++) {
578 s = lp_servicename(i);
579 if (s && (*s) && lp_is_default(i, parm)) {
580 lp_do_parameter(i, parm->label, v);
585 lp_do_parameter(snum, parm->label, v);
588 /****************************************************************************
589 commit a set of parameters for a service
590 ****************************************************************************/
591 static void commit_parameters(int snum)
593 int i = 0;
594 struct parm_struct *parm;
595 char *label;
596 const char *v;
598 while ((parm = lp_next_parameter(snum, &i, 1))) {
599 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
600 if ((v = cgi_variable(label)) != NULL) {
601 if (parm->flags & FLAG_HIDE)
602 continue;
603 commit_parameter(snum, parm, v);
605 SAFE_FREE(label);
610 /****************************************************************************
611 spit out the html for a link with an image
612 ****************************************************************************/
613 static void image_link(const char *name, const char *hlink, const char *src)
615 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
616 cgi_baseurl(), hlink, src, name);
619 /****************************************************************************
620 display the main navigation controls at the top of each page along
621 with a title
622 ****************************************************************************/
623 static void show_main_buttons(void)
625 char *p;
627 if ((p = cgi_user_name()) && strcmp(p, "root")) {
628 printf(_("Logged in as <b>%s</b>"), p);
629 printf("<p>\n");
632 image_link(_("Home"), "", "images/home.gif");
633 if (have_write_access) {
634 image_link(_("Globals"), "globals", "images/globals.gif");
635 image_link(_("Shares"), "shares", "images/shares.gif");
636 image_link(_("Printers"), "printers", "images/printers.gif");
637 image_link(_("Wizard"), "wizard", "images/wizard.gif");
639 /* root always gets all buttons, otherwise look for -P */
640 if ( have_write_access || (!passwd_only && have_read_access) ) {
641 image_link(_("Status"), "status", "images/status.gif");
642 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
644 image_link(_("Password Management"), "passwd", "images/passwd.gif");
646 printf("<HR>\n");
649 /****************************************************************************
650 * Handle Display/Edit Mode CGI
651 ****************************************************************************/
652 static void ViewModeBoxes(int mode)
654 printf("<p>%s:&nbsp;\n", _("Current View Is"));
655 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
656 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
657 printf("<br>%s:&nbsp;\n", _("Change View To"));
658 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
659 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
660 printf("</p><br>\n");
663 /****************************************************************************
664 display a welcome page
665 ****************************************************************************/
666 static void welcome_page(void)
668 if (file_exist("help/welcome.html")) {
669 include_html("help/welcome.html");
670 } else {
671 include_html("help/welcome-no-samba-doc.html");
675 /****************************************************************************
676 display the current smb.conf
677 ****************************************************************************/
678 static void viewconfig_page(void)
680 int full_view=0;
681 const char form_name[] = "viewconfig";
683 if (!verify_xsrf_token(form_name)) {
684 goto output_page;
687 if (cgi_variable("full_view")) {
688 full_view = 1;
691 output_page:
692 printf("<H2>%s</H2>\n", _("Current Config"));
693 printf("<form method=post>\n");
694 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
696 if (full_view) {
697 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
698 } else {
699 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
702 printf("<p><pre>");
703 write_config(stdout, full_view);
704 printf("</pre>");
705 printf("</form>\n");
708 /****************************************************************************
709 second screen of the wizard ... Fetch Configuration Parameters
710 ****************************************************************************/
711 static void wizard_params_page(void)
713 unsigned int parm_filter = FLAG_WIZARD;
714 const char form_name[] = "wizard_params";
716 /* Here we first set and commit all the parameters that were selected
717 in the previous screen. */
719 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
721 if (!verify_xsrf_token(form_name)) {
722 goto output_page;
725 if (cgi_variable("Commit")) {
726 commit_parameters(GLOBAL_SECTION_SNUM);
727 save_reload(-1);
730 output_page:
731 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
732 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
734 if (have_write_access) {
735 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
738 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
739 printf("<p>\n");
741 printf("<table>\n");
742 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
743 printf("</table>\n");
744 printf("</form>\n");
747 /****************************************************************************
748 Utility to just rewrite the smb.conf file - effectively just cleans it up
749 ****************************************************************************/
750 static void rewritecfg_file(void)
752 commit_parameters(GLOBAL_SECTION_SNUM);
753 save_reload(-1);
754 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
757 /****************************************************************************
758 wizard to create/modify the smb.conf file
759 ****************************************************************************/
760 static void wizard_page(void)
762 /* Set some variables to collect data from smb.conf */
763 int role = 0;
764 int winstype = 0;
765 int have_home = -1;
766 int HomeExpo = 0;
767 int SerType = 0;
768 const char form_name[] = "wizard";
770 if (!verify_xsrf_token(form_name)) {
771 goto output_page;
774 if (cgi_variable("Rewrite")) {
775 (void) rewritecfg_file();
776 return;
779 if (cgi_variable("GetWizardParams")){
780 (void) wizard_params_page();
781 return;
784 if (cgi_variable("Commit")){
785 SerType = atoi(cgi_variable_nonull("ServerType"));
786 winstype = atoi(cgi_variable_nonull("WINSType"));
787 have_home = lp_servicenumber(HOMES_NAME);
788 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
790 /* Plain text passwords are too badly broken - use encrypted passwords only */
791 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
793 switch ( SerType ){
794 case 0:
795 /* Stand-alone Server */
796 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
797 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
798 break;
799 case 1:
800 /* Domain Member */
801 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
802 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
803 break;
804 case 2:
805 /* Domain Controller */
806 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
807 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
808 break;
810 switch ( winstype ) {
811 case 0:
812 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
813 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
814 break;
815 case 1:
816 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
817 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
818 break;
819 case 2:
820 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
821 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
822 break;
825 /* Have to create Homes share? */
826 if ((HomeExpo == 1) && (have_home == -1)) {
827 const char *unix_share = HOMES_NAME;
829 load_config(False);
830 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
831 have_home = lp_servicenumber(HOMES_NAME);
832 lp_do_parameter( have_home, "read only", "No");
833 lp_do_parameter( have_home, "valid users", "%S");
834 lp_do_parameter( have_home, "browseable", "No");
835 commit_parameters(have_home);
836 save_reload(have_home);
839 /* Need to Delete Homes share? */
840 if ((HomeExpo == 0) && (have_home != -1)) {
841 lp_remove_service(have_home);
842 have_home = -1;
845 commit_parameters(GLOBAL_SECTION_SNUM);
846 save_reload(-1);
848 else
850 /* Now determine smb.conf WINS settings */
851 if (lp_we_are_a_wins_server())
852 winstype = 1;
853 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
854 winstype = 2;
856 /* Do we have a homes share? */
857 have_home = lp_servicenumber(HOMES_NAME);
859 if ((winstype == 2) && lp_we_are_a_wins_server())
860 winstype = 3;
862 role = lp_server_role();
864 output_page:
865 /* Here we go ... */
866 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
867 printf("<form method=post action=wizard>\n");
868 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
870 if (have_write_access) {
871 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
872 printf("%s", _("The same will happen if you press the commit button."));
873 printf("<br><br>\n");
874 printf("<center>");
875 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
876 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
877 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
878 printf("</center>\n");
881 printf("<hr>");
882 printf("<center><table border=0>");
883 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
884 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
885 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
886 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
887 printf("</tr>\n");
888 if (role == ROLE_DOMAIN_BDC) {
889 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
891 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
892 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
893 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
894 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
895 printf("</tr>\n");
896 printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
898 /* Print out the list of wins servers */
899 if(lp_wins_server_list()) {
900 int i;
901 const char **wins_servers = lp_wins_server_list();
902 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
905 printf("\"></td></tr>\n");
906 if (winstype == 3) {
907 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"));
908 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
910 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
911 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
912 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
913 printf("<td></td></tr>\n");
915 /* Enable this when we are ready ....
916 * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
917 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
918 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
919 * printf("<td></td></tr>\n");
922 printf("</table></center>");
923 printf("<hr>");
925 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
926 printf("</form>\n");
930 /****************************************************************************
931 display a globals editing page
932 ****************************************************************************/
933 static void globals_page(void)
935 unsigned int parm_filter = FLAG_BASIC;
936 int mode = 0;
937 const char form_name[] = "globals";
939 printf("<H2>%s</H2>\n", _("Global Parameters"));
941 if (!verify_xsrf_token(form_name)) {
942 goto output_page;
945 if (cgi_variable("Commit")) {
946 commit_parameters(GLOBAL_SECTION_SNUM);
947 save_reload(-1);
950 if ( cgi_variable("ViewMode") )
951 mode = atoi(cgi_variable_nonull("ViewMode"));
952 if ( cgi_variable("BasicMode"))
953 mode = 0;
954 if ( cgi_variable("AdvMode"))
955 mode = 1;
957 output_page:
958 printf("<form name=\"swatform\" method=post action=globals>\n");
959 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
961 ViewModeBoxes( mode );
962 switch ( mode ) {
963 case 0:
964 parm_filter = FLAG_BASIC;
965 break;
966 case 1:
967 parm_filter = FLAG_ADVANCED;
968 break;
970 printf("<br>\n");
971 if (have_write_access) {
972 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
973 _("Commit Changes"));
976 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
977 _("Reset Values"));
979 printf("<p>\n");
980 printf("<table>\n");
981 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
982 printf("</table>\n");
983 printf("</form>\n");
986 /****************************************************************************
987 display a shares editing page. share is in unix codepage,
988 ****************************************************************************/
989 static void shares_page(void)
991 const char *share = cgi_variable("share");
992 char *s;
993 char *utf8_s;
994 int snum = -1;
995 int i;
996 int mode = 0;
997 unsigned int parm_filter = FLAG_BASIC;
998 size_t converted_size;
999 const char form_name[] = "shares";
1001 printf("<H2>%s</H2>\n", _("Share Parameters"));
1003 if (!verify_xsrf_token(form_name)) {
1004 goto output_page;
1007 if (share)
1008 snum = lp_servicenumber(share);
1011 if (cgi_variable("Commit") && snum >= 0) {
1012 commit_parameters(snum);
1013 save_reload(-1);
1014 snum = lp_servicenumber(share);
1017 if (cgi_variable("Delete") && snum >= 0) {
1018 lp_remove_service(snum);
1019 save_reload(-1);
1020 share = NULL;
1021 snum = -1;
1024 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1025 snum = lp_servicenumber(share);
1026 if (snum < 0) {
1027 load_config(False);
1028 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1029 snum = lp_servicenumber(share);
1030 save_reload(snum);
1031 snum = lp_servicenumber(share);
1035 if ( cgi_variable("ViewMode") )
1036 mode = atoi(cgi_variable_nonull("ViewMode"));
1037 if ( cgi_variable("BasicMode"))
1038 mode = 0;
1039 if ( cgi_variable("AdvMode"))
1040 mode = 1;
1042 output_page:
1043 printf("<FORM name=\"swatform\" method=post>\n");
1044 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1046 printf("<table>\n");
1048 ViewModeBoxes( mode );
1049 switch ( mode ) {
1050 case 0:
1051 parm_filter = FLAG_BASIC;
1052 break;
1053 case 1:
1054 parm_filter = FLAG_ADVANCED;
1055 break;
1057 printf("<br><tr>\n");
1058 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1059 printf("<td><select name=share>\n");
1060 if (snum < 0)
1061 printf("<option value=\" \"> \n");
1062 for (i=0;i<lp_numservices();i++) {
1063 s = lp_servicename(i);
1064 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1065 push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1066 printf("<option %s value=\"%s\">%s\n",
1067 (share && strcmp(share,s)==0)?"SELECTED":"",
1068 utf8_s, utf8_s);
1069 TALLOC_FREE(utf8_s);
1072 printf("</select></td>\n");
1073 if (have_write_access) {
1074 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1076 printf("</tr>\n");
1077 printf("</table>");
1078 printf("<table>");
1079 if (have_write_access) {
1080 printf("<tr>\n");
1081 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1082 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1084 printf("</table>");
1087 if (snum >= 0) {
1088 if (have_write_access) {
1089 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1092 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1093 printf("<p>\n");
1096 if (snum >= 0) {
1097 printf("<table>\n");
1098 show_parameters(snum, 1, parm_filter, 0);
1099 printf("</table>\n");
1102 printf("</FORM>\n");
1105 /*************************************************************
1106 change a password either locally or remotely
1107 *************************************************************/
1108 static bool change_password(const char *remote_machine, const char *user_name,
1109 const char *old_passwd, const char *new_passwd,
1110 int local_flags)
1112 NTSTATUS ret;
1113 char *err_str = NULL;
1114 char *msg_str = NULL;
1116 if (demo_mode) {
1117 printf("%s\n<p>", _("password change in demo mode rejected"));
1118 return False;
1121 if (remote_machine != NULL) {
1122 ret = remote_password_change(remote_machine, user_name,
1123 old_passwd, new_passwd, &err_str);
1124 if (err_str != NULL)
1125 printf("%s\n<p>", err_str);
1126 SAFE_FREE(err_str);
1127 return NT_STATUS_IS_OK(ret);
1130 if(!initialize_password_db(True, NULL)) {
1131 printf("%s\n<p>", _("Can't setup password database vectors."));
1132 return False;
1135 ret = local_password_change(user_name, local_flags, new_passwd,
1136 &err_str, &msg_str);
1138 if(msg_str)
1139 printf("%s\n<p>", msg_str);
1140 if(err_str)
1141 printf("%s\n<p>", err_str);
1143 SAFE_FREE(msg_str);
1144 SAFE_FREE(err_str);
1145 return NT_STATUS_IS_OK(ret);
1148 /****************************************************************************
1149 do the stuff required to add or change a password
1150 ****************************************************************************/
1151 static void chg_passwd(void)
1153 const char *host;
1154 bool rslt;
1155 int local_flags = 0;
1157 /* Make sure users name has been specified */
1158 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1159 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1160 return;
1164 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1165 * so if that's what we're doing, skip the rest of the checks
1167 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1170 * If current user is not root, make sure old password has been specified
1171 * If REMOTE change, even root must provide old password
1173 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1174 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1175 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1176 return;
1179 /* If changing a users password on a remote hosts we have to know what host */
1180 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1181 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1182 return;
1185 /* Make sure new passwords have been specified */
1186 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1187 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1188 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1189 return;
1192 /* Make sure new passwords was typed correctly twice */
1193 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1194 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1195 return;
1199 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1200 host = cgi_variable(RHOST);
1201 } else if (am_root()) {
1202 host = NULL;
1203 } else {
1204 host = "127.0.0.1";
1208 * Set up the local flags.
1211 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1212 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1213 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1214 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1215 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1216 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1218 rslt = change_password(host,
1219 cgi_variable_nonull(SWAT_USER),
1220 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1221 local_flags);
1223 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1224 printf("<p>");
1225 if (rslt == True) {
1226 printf("%s\n", _(" The passwd has been changed."));
1227 } else {
1228 printf("%s\n", _(" The passwd has NOT been changed."));
1232 return;
1235 /****************************************************************************
1236 display a password editing page
1237 ****************************************************************************/
1238 static void passwd_page(void)
1240 const char *new_name = cgi_user_name();
1241 const char passwd_form[] = "passwd";
1242 const char rpasswd_form[] = "rpasswd";
1244 if (!new_name) new_name = "";
1246 printf("<H2>%s</H2>\n", _("Server Password Management"));
1248 printf("<FORM name=\"swatform\" method=post>\n");
1249 print_xsrf_token(cgi_user_name(), cgi_user_pass(), passwd_form);
1251 printf("<table>\n");
1254 * Create all the dialog boxes for data collection
1256 printf("<tr><td> %s : </td>\n", _("User Name"));
1257 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1258 if (!am_root()) {
1259 printf("<tr><td> %s : </td>\n", _("Old Password"));
1260 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1262 printf("<tr><td> %s : </td>\n", _("New Password"));
1263 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1264 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1265 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1266 printf("</table>\n");
1269 * Create all the control buttons for requesting action
1271 printf("<input type=submit name=%s value=\"%s\">\n",
1272 CHG_S_PASSWD_FLAG, _("Change Password"));
1273 if (demo_mode || am_root()) {
1274 printf("<input type=submit name=%s value=\"%s\">\n",
1275 ADD_USER_FLAG, _("Add New User"));
1276 printf("<input type=submit name=%s value=\"%s\">\n",
1277 DELETE_USER_FLAG, _("Delete User"));
1278 printf("<input type=submit name=%s value=\"%s\">\n",
1279 DISABLE_USER_FLAG, _("Disable User"));
1280 printf("<input type=submit name=%s value=\"%s\">\n",
1281 ENABLE_USER_FLAG, _("Enable User"));
1283 printf("<p></FORM>\n");
1286 * Do some work if change, add, disable or enable was
1287 * requested. It could be this is the first time through this
1288 * code, so there isn't anything to do. */
1289 if (verify_xsrf_token(passwd_form) &&
1290 ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1291 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG)))) {
1292 chg_passwd();
1295 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1297 printf("<FORM name=\"swatform\" method=post>\n");
1298 print_xsrf_token(cgi_user_name(), cgi_user_pass(), rpasswd_form);
1300 printf("<table>\n");
1303 * Create all the dialog boxes for data collection
1305 printf("<tr><td> %s : </td>\n", _("User Name"));
1306 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1307 printf("<tr><td> %s : </td>\n", _("Old Password"));
1308 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1309 printf("<tr><td> %s : </td>\n", _("New Password"));
1310 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1311 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1312 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1313 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1314 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1316 printf("</table>");
1319 * Create all the control buttons for requesting action
1321 printf("<input type=submit name=%s value=\"%s\">",
1322 CHG_R_PASSWD_FLAG, _("Change Password"));
1324 printf("<p></FORM>\n");
1327 * Do some work if a request has been made to change the
1328 * password somewhere other than the server. It could be this
1329 * is the first time through this code, so there isn't
1330 * anything to do. */
1331 if (verify_xsrf_token(passwd_form) && cgi_variable(CHG_R_PASSWD_FLAG)) {
1332 chg_passwd();
1337 /****************************************************************************
1338 display a printers editing page
1339 ****************************************************************************/
1340 static void printers_page(void)
1342 const char *share = cgi_variable("share");
1343 char *s;
1344 int snum=-1;
1345 int i;
1346 int mode = 0;
1347 unsigned int parm_filter = FLAG_BASIC;
1349 if (share)
1350 snum = lp_servicenumber(share);
1352 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1354 printf("<H3>%s</H3>\n", _("Important Note:"));
1355 printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1356 printf("%s",_("are autoloaded printers from "));
1357 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1358 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1360 if (cgi_variable("Commit") && snum >= 0) {
1361 commit_parameters(snum);
1362 if (snum >= iNumNonAutoPrintServices)
1363 save_reload(snum);
1364 else
1365 save_reload(-1);
1366 snum = lp_servicenumber(share);
1369 if (cgi_variable("Delete") && snum >= 0) {
1370 lp_remove_service(snum);
1371 save_reload(-1);
1372 share = NULL;
1373 snum = -1;
1376 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1377 snum = lp_servicenumber(share);
1378 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1379 load_config(False);
1380 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1381 snum = lp_servicenumber(share);
1382 lp_do_parameter(snum, "print ok", "Yes");
1383 save_reload(snum);
1384 snum = lp_servicenumber(share);
1388 printf("<FORM name=\"swatform\" method=post>\n");
1390 if ( cgi_variable("ViewMode") )
1391 mode = atoi(cgi_variable_nonull("ViewMode"));
1392 if ( cgi_variable("BasicMode"))
1393 mode = 0;
1394 if ( cgi_variable("AdvMode"))
1395 mode = 1;
1397 ViewModeBoxes( mode );
1398 switch ( mode ) {
1399 case 0:
1400 parm_filter = FLAG_BASIC;
1401 break;
1402 case 1:
1403 parm_filter = FLAG_ADVANCED;
1404 break;
1406 printf("<table>\n");
1407 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1408 printf("<td><select name=\"share\">\n");
1409 if (snum < 0 || !lp_print_ok(snum))
1410 printf("<option value=\" \"> \n");
1411 for (i=0;i<lp_numservices();i++) {
1412 s = lp_servicename(i);
1413 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1414 if (i >= iNumNonAutoPrintServices)
1415 printf("<option %s value=\"%s\">[*]%s\n",
1416 (share && strcmp(share,s)==0)?"SELECTED":"",
1417 s, s);
1418 else
1419 printf("<option %s value=\"%s\">%s\n",
1420 (share && strcmp(share,s)==0)?"SELECTED":"",
1421 s, s);
1424 printf("</select></td>");
1425 if (have_write_access) {
1426 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1428 printf("</tr>");
1429 printf("</table>\n");
1431 if (have_write_access) {
1432 printf("<table>\n");
1433 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1434 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1435 printf("</table>");
1439 if (snum >= 0) {
1440 if (have_write_access) {
1441 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1443 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1444 printf("<p>\n");
1447 if (snum >= 0) {
1448 printf("<table>\n");
1449 show_parameters(snum, 1, parm_filter, 1);
1450 printf("</table>\n");
1452 printf("</FORM>\n");
1456 when the _() translation macro is used there is no obvious place to free
1457 the resulting string and there is no easy way to give a static pointer.
1458 All we can do is rotate between some static buffers and hope a single d_printf()
1459 doesn't have more calls to _() than the number of buffers
1462 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1464 const char *msgstr;
1465 const char *ret;
1467 msgstr = lang_msg(msgid);
1468 if (!msgstr) {
1469 return msgid;
1472 ret = talloc_strdup(ctx, msgstr);
1474 lang_msg_free(msgstr);
1475 if (!ret) {
1476 return msgid;
1479 return ret;
1483 * main function for SWAT.
1485 int main(int argc, char *argv[])
1487 const char *page;
1488 poptContext pc;
1489 struct poptOption long_options[] = {
1490 POPT_AUTOHELP
1491 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1492 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1493 POPT_COMMON_SAMBA
1494 POPT_TABLEEND
1496 TALLOC_CTX *frame = talloc_stackframe();
1498 fault_setup();
1499 umask(S_IWGRP | S_IWOTH);
1501 #if defined(HAVE_SET_AUTH_PARAMETERS)
1502 set_auth_parameters(argc, argv);
1503 #endif /* HAVE_SET_AUTH_PARAMETERS */
1505 /* just in case it goes wild ... */
1506 alarm(300);
1508 setlinebuf(stdout);
1510 /* we don't want any SIGPIPE messages */
1511 BlockSignals(True,SIGPIPE);
1513 debug_set_logfile("/dev/null");
1515 /* we don't want stderr screwing us up */
1516 close(2);
1517 open("/dev/null", O_WRONLY);
1518 setup_logging("swat", DEBUG_FILE);
1520 load_case_tables();
1522 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1524 /* Parse command line options */
1526 while(poptGetNextOpt(pc) != -1) { }
1528 poptFreeContext(pc);
1530 /* This should set a more apporiate log file */
1531 load_config(True);
1532 reopen_logs();
1533 load_interfaces();
1534 iNumNonAutoPrintServices = lp_numservices();
1535 if (pcap_cache_loaded()) {
1536 load_printers(server_event_context(),
1537 server_messaging_context());
1540 cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1542 print_header();
1544 cgi_load_variables();
1546 if (!file_exist(get_dyn_CONFIGFILE())) {
1547 have_read_access = True;
1548 have_write_access = True;
1549 } else {
1550 /* check if the authenticated user has write access - if not then
1551 don't show write options */
1552 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1554 /* if the user doesn't have read access to smb.conf then
1555 don't let them view it */
1556 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1559 show_main_buttons();
1561 page = cgi_pathinfo();
1563 /* Root gets full functionality */
1564 if (have_read_access && strcmp(page, "globals")==0) {
1565 globals_page();
1566 } else if (have_read_access && strcmp(page,"shares")==0) {
1567 shares_page();
1568 } else if (have_read_access && strcmp(page,"printers")==0) {
1569 printers_page();
1570 } else if (have_read_access && strcmp(page,"status")==0) {
1571 status_page();
1572 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1573 viewconfig_page();
1574 } else if (strcmp(page,"passwd")==0) {
1575 passwd_page();
1576 } else if (have_read_access && strcmp(page,"wizard")==0) {
1577 wizard_page();
1578 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1579 wizard_params_page();
1580 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1581 rewritecfg_file();
1582 } else {
1583 welcome_page();
1586 print_footer();
1588 TALLOC_FREE(frame);
1589 return 0;
1592 /** @} **/