swat: Use X-Frame-Options header to avoid clickjacking
[Samba.git] / source3 / web / swat.c
blobed80c383dc8cdf7bdaf2befe7108731f60bc23c9
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"
40 static int demo_mode = False;
41 static int passwd_only = False;
42 static bool have_write_access = False;
43 static bool have_read_access = False;
44 static int iNumNonAutoPrintServices = 0;
47 * Password Management Globals
49 #define SWAT_USER "username"
50 #define OLD_PSWD "old_passwd"
51 #define NEW_PSWD "new_passwd"
52 #define NEW2_PSWD "new2_passwd"
53 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
54 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
55 #define ADD_USER_FLAG "add_user_flag"
56 #define DELETE_USER_FLAG "delete_user_flag"
57 #define DISABLE_USER_FLAG "disable_user_flag"
58 #define ENABLE_USER_FLAG "enable_user_flag"
59 #define RHOST "remote_host"
60 #define XSRF_TOKEN "xsrf"
61 #define XSRF_TIME "xsrf_time"
62 #define XSRF_TIMEOUT 300
64 #define _(x) lang_msg_rotate(talloc_tos(),x)
66 /****************************************************************************
67 ****************************************************************************/
68 static int enum_index(int value, const struct enum_list *enumlist)
70 int i;
71 for (i=0;enumlist[i].name;i++)
72 if (value == enumlist[i].value) break;
73 return(i);
76 static char *fix_backslash(const char *str)
78 static char newstring[1024];
79 char *p = newstring;
81 while (*str) {
82 if (*str == '\\') {*p++ = '\\';*p++ = '\\';}
83 else *p++ = *str;
84 ++str;
86 *p = '\0';
87 return newstring;
90 static const char *fix_quotes(TALLOC_CTX *ctx, const char *str)
92 char *newstring = NULL;
93 char *p = NULL;
94 size_t newstring_len;
95 int quote_len = strlen("&quot;");
97 /* Count the number of quotes. */
98 newstring_len = 1;
99 p = (char *) str;
100 while (*p) {
101 if ( *p == '\"') {
102 newstring_len += quote_len;
103 } else {
104 newstring_len++;
106 ++p;
108 newstring = TALLOC_ARRAY(ctx, char, newstring_len);
109 if (!newstring) {
110 return "";
112 for (p = newstring; *str; str++) {
113 if ( *str == '\"') {
114 strncpy( p, "&quot;", quote_len);
115 p += quote_len;
116 } else {
117 *p++ = *str;
120 *p = '\0';
121 return newstring;
124 static char *stripspaceupper(const char *str)
126 static char newstring[1024];
127 char *p = newstring;
129 while (*str) {
130 if (*str != ' ') *p++ = toupper_m(*str);
131 ++str;
133 *p = '\0';
134 return newstring;
137 static char *make_parm_name(const char *label)
139 static char parmname[1024];
140 char *p = parmname;
142 while (*label) {
143 if (*label == ' ') *p++ = '_';
144 else *p++ = *label;
145 ++label;
147 *p = '\0';
148 return parmname;
151 void get_xsrf_token(const char *username, const char *pass,
152 const char *formname, time_t xsrf_time, char token_str[33])
154 MD5_CTX md5_ctx;
155 uint8_t token[16];
156 int i;
158 token_str[0] = '\0';
159 ZERO_STRUCT(md5_ctx);
160 MD5Init(&md5_ctx);
162 MD5Update(&md5_ctx, (uint8_t *)formname, strlen(formname));
163 MD5Update(&md5_ctx, (uint8_t *)&xsrf_time, sizeof(time_t));
164 if (username != NULL) {
165 MD5Update(&md5_ctx, (uint8_t *)username, strlen(username));
167 if (pass != NULL) {
168 MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
171 MD5Final(token, &md5_ctx);
173 for(i = 0; i < sizeof(token); i++) {
174 char tmp[3];
176 snprintf(tmp, sizeof(tmp), "%02x", token[i]);
177 strlcat(token_str, tmp, sizeof(tmp));
181 void print_xsrf_token(const char *username, const char *pass,
182 const char *formname)
184 char token[33];
185 time_t xsrf_time = time(NULL);
187 get_xsrf_token(username, pass, formname, xsrf_time, token);
188 printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
189 XSRF_TOKEN, token);
190 printf("<input type=\"hidden\" name=\"%s\" value=\"%lld\">\n",
191 XSRF_TIME, (long long int)xsrf_time);
194 bool verify_xsrf_token(const char *formname)
196 char expected[33];
197 const char *username = cgi_user_name();
198 const char *pass = cgi_user_pass();
199 const char *token = cgi_variable_nonull(XSRF_TOKEN);
200 const char *time_str = cgi_variable_nonull(XSRF_TIME);
201 char *p = NULL;
202 long long xsrf_time_ll = 0;
203 time_t xsrf_time = 0;
204 time_t now = time(NULL);
206 errno = 0;
207 xsrf_time_ll = strtoll(time_str, &p, 10);
208 if (errno != 0) {
209 return false;
211 if (p == NULL) {
212 return false;
214 if (PTR_DIFF(p, time_str) > strlen(time_str)) {
215 return false;
217 if (xsrf_time_ll > _TYPE_MAXIMUM(time_t)) {
218 return false;
220 if (xsrf_time_ll < _TYPE_MINIMUM(time_t)) {
221 return false;
223 xsrf_time = xsrf_time_ll;
225 if (abs(now - xsrf_time) > XSRF_TIMEOUT) {
226 return false;
229 get_xsrf_token(username, pass, formname, xsrf_time, expected);
230 return (strncmp(expected, token, sizeof(expected)) == 0);
234 /****************************************************************************
235 include a lump of html in a page
236 ****************************************************************************/
237 static int include_html(const char *fname)
239 int fd;
240 char buf[1024];
241 int ret;
243 fd = web_open(fname, O_RDONLY, 0);
245 if (fd == -1) {
246 printf(_("ERROR: Can't open %s"), fname);
247 printf("\n");
248 return 0;
251 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
252 if (write(1, buf, ret) == -1) {
253 break;
257 close(fd);
258 return 1;
261 /****************************************************************************
262 start the page with standard stuff
263 ****************************************************************************/
264 static void print_header(void)
266 if (!cgi_waspost()) {
267 printf("Expires: 0\r\n");
269 printf("Content-type: text/html\r\n");
270 printf("X-Frame-Options: DENY\r\n\r\n");
272 if (!include_html("include/header.html")) {
273 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
274 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
278 /* *******************************************************************
279 show parameter label with translated name in the following form
280 because showing original and translated label in one line looks
281 too long, and showing translated label only is unusable for
282 heavy users.
283 -------------------------------
284 HELP security [combo box][button]
285 SECURITY
286 -------------------------------
287 (capital words are translated by gettext.)
288 if no translation is available, then same form as original is
289 used.
290 "i18n_translated_parm" class is used to change the color of the
291 translated parameter with CSS.
292 **************************************************************** */
293 static const char *get_parm_translated(TALLOC_CTX *ctx,
294 const char* pAnchor, const char* pHelp, const char* pLabel)
296 const char *pTranslated = _(pLabel);
297 char *output;
298 if(strcmp(pLabel, pTranslated) != 0) {
299 output = talloc_asprintf(ctx,
300 "<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>",
301 pAnchor, pHelp, pLabel, pTranslated);
302 return output;
304 output = talloc_asprintf(ctx,
305 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
306 pAnchor, pHelp, pLabel);
307 return output;
309 /****************************************************************************
310 finish off the page
311 ****************************************************************************/
312 static void print_footer(void)
314 if (!include_html("include/footer.html")) {
315 printf("\n</BODY>\n</HTML>\n");
319 /****************************************************************************
320 display one editable parameter in a form
321 ****************************************************************************/
322 static void show_parameter(int snum, struct parm_struct *parm)
324 int i;
325 void *ptr = parm->ptr;
326 char *utf8_s1, *utf8_s2;
327 size_t converted_size;
328 TALLOC_CTX *ctx = talloc_stackframe();
330 if (parm->p_class == P_LOCAL && snum >= 0) {
331 ptr = lp_local_ptr_by_snum(snum, ptr);
334 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
335 stripspaceupper(parm->label), _("Help"), parm->label));
336 switch (parm->type) {
337 case P_CHAR:
338 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
339 make_parm_name(parm->label), *(char *)ptr);
340 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
341 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
342 break;
344 case P_LIST:
345 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
346 make_parm_name(parm->label));
347 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
348 char **list = *(char ***)ptr;
349 for (;*list;list++) {
350 /* enclose in HTML encoded quotes if the string contains a space */
351 if ( strchr_m(*list, ' ') ) {
352 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
353 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
354 printf("&quot;%s&quot;%s", utf8_s1, utf8_s2);
355 } else {
356 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
357 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
358 printf("%s%s", utf8_s1, utf8_s2);
360 TALLOC_FREE(utf8_s1);
361 TALLOC_FREE(utf8_s2);
364 printf("\">");
365 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
366 _("Set Default"), make_parm_name(parm->label));
367 if (parm->def.lvalue) {
368 char **list = (char **)(parm->def.lvalue);
369 for (; *list; list++) {
370 /* enclose in HTML encoded quotes if the string contains a space */
371 if ( strchr_m(*list, ' ') )
372 printf("&quot;%s&quot;%s", *list, ((*(list+1))?", ":""));
373 else
374 printf("%s%s", *list, ((*(list+1))?", ":""));
377 printf("\'\">");
378 break;
380 case P_STRING:
381 case P_USTRING:
382 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
383 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
384 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
385 TALLOC_FREE(utf8_s1);
386 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
387 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
388 break;
390 case P_BOOL:
391 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
392 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
393 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
394 printf("</select>");
395 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
396 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
397 break;
399 case P_BOOLREV:
400 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
401 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
402 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
403 printf("</select>");
404 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
405 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
406 break;
408 case P_INTEGER:
409 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
410 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
411 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
412 break;
414 case P_OCTAL: {
415 char *o;
416 o = octal_string(*(int *)ptr);
417 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
418 make_parm_name(parm->label), o);
419 TALLOC_FREE(o);
420 o = octal_string((int)(parm->def.ivalue));
421 printf("<input type=button value=\"%s\" "
422 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
423 _("Set Default"), make_parm_name(parm->label), o);
424 TALLOC_FREE(o);
425 break;
428 case P_ENUM:
429 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
430 for (i=0;parm->enum_list[i].name;i++) {
431 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
432 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
435 printf("</select>");
436 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
437 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
438 break;
439 case P_SEP:
440 break;
442 printf("</td></tr>\n");
443 TALLOC_FREE(ctx);
446 /****************************************************************************
447 display a set of parameters for a service
448 ****************************************************************************/
449 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
451 int i = 0;
452 struct parm_struct *parm;
453 const char *heading = NULL;
454 const char *last_heading = NULL;
456 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
457 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
458 continue;
459 if (parm->p_class == P_SEPARATOR) {
460 heading = parm->label;
461 continue;
463 if (parm->flags & FLAG_HIDE) continue;
464 if (snum >= 0) {
465 if (printers & !(parm->flags & FLAG_PRINT)) continue;
466 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
469 if (!( parm_filter & FLAG_ADVANCED )) {
470 if (!(parm->flags & FLAG_BASIC)) {
471 void *ptr = parm->ptr;
473 if (parm->p_class == P_LOCAL && snum >= 0) {
474 ptr = lp_local_ptr_by_snum(snum, ptr);
477 switch (parm->type) {
478 case P_CHAR:
479 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
480 break;
482 case P_LIST:
483 if (!str_list_equal(*(const char ***)ptr,
484 (const char **)(parm->def.lvalue))) continue;
485 break;
487 case P_STRING:
488 case P_USTRING:
489 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
490 break;
492 case P_BOOL:
493 case P_BOOLREV:
494 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
495 break;
497 case P_INTEGER:
498 case P_OCTAL:
499 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
500 break;
503 case P_ENUM:
504 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
505 break;
506 case P_SEP:
507 continue;
510 if (printers && !(parm->flags & FLAG_PRINT)) continue;
513 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
515 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
517 if (heading && heading != last_heading) {
518 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
519 last_heading = heading;
521 show_parameter(snum, parm);
525 /****************************************************************************
526 load the smb.conf file into loadparm.
527 ****************************************************************************/
528 static bool load_config(bool save_def)
530 return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
533 /****************************************************************************
534 write a config file
535 ****************************************************************************/
536 static void write_config(FILE *f, bool show_defaults)
538 TALLOC_CTX *ctx = talloc_stackframe();
540 fprintf(f, "# Samba config file created using SWAT\n");
541 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
542 fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
544 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
546 TALLOC_FREE(ctx);
549 /****************************************************************************
550 save and reload the smb.conf config file
551 ****************************************************************************/
552 static int save_reload(int snum)
554 FILE *f;
555 struct stat st;
557 f = sys_fopen(get_dyn_CONFIGFILE(),"w");
558 if (!f) {
559 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
560 printf("\n");
561 return 0;
564 /* just in case they have used the buggy xinetd to create the file */
565 if (fstat(fileno(f), &st) == 0 &&
566 (st.st_mode & S_IWOTH)) {
567 #if defined HAVE_FCHMOD
568 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
569 #else
570 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
571 #endif
574 write_config(f, False);
575 if (snum >= 0)
576 lp_dump_one(f, False, snum);
577 fclose(f);
579 lp_kill_all_services();
581 if (!load_config(False)) {
582 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
583 printf("\n");
584 return 0;
586 iNumNonAutoPrintServices = lp_numservices();
587 if (pcap_cache_loaded()) {
588 load_printers(server_event_context(),
589 server_messaging_context());
592 return 1;
595 /****************************************************************************
596 commit one parameter
597 ****************************************************************************/
598 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
600 int i;
601 char *s;
603 if (snum < 0 && parm->p_class == P_LOCAL) {
604 /* this handles the case where we are changing a local
605 variable globally. We need to change the parameter in
606 all shares where it is currently set to the default */
607 for (i=0;i<lp_numservices();i++) {
608 s = lp_servicename(i);
609 if (s && (*s) && lp_is_default(i, parm)) {
610 lp_do_parameter(i, parm->label, v);
615 lp_do_parameter(snum, parm->label, v);
618 /****************************************************************************
619 commit a set of parameters for a service
620 ****************************************************************************/
621 static void commit_parameters(int snum)
623 int i = 0;
624 struct parm_struct *parm;
625 char *label;
626 const char *v;
628 while ((parm = lp_next_parameter(snum, &i, 1))) {
629 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
630 if ((v = cgi_variable(label)) != NULL) {
631 if (parm->flags & FLAG_HIDE)
632 continue;
633 commit_parameter(snum, parm, v);
635 SAFE_FREE(label);
640 /****************************************************************************
641 spit out the html for a link with an image
642 ****************************************************************************/
643 static void image_link(const char *name, const char *hlink, const char *src)
645 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
646 cgi_baseurl(), hlink, src, name);
649 /****************************************************************************
650 display the main navigation controls at the top of each page along
651 with a title
652 ****************************************************************************/
653 static void show_main_buttons(void)
655 char *p;
657 if ((p = cgi_user_name()) && strcmp(p, "root")) {
658 printf(_("Logged in as <b>%s</b>"), p);
659 printf("<p>\n");
662 image_link(_("Home"), "", "images/home.gif");
663 if (have_write_access) {
664 image_link(_("Globals"), "globals", "images/globals.gif");
665 image_link(_("Shares"), "shares", "images/shares.gif");
666 image_link(_("Printers"), "printers", "images/printers.gif");
667 image_link(_("Wizard"), "wizard", "images/wizard.gif");
669 /* root always gets all buttons, otherwise look for -P */
670 if ( have_write_access || (!passwd_only && have_read_access) ) {
671 image_link(_("Status"), "status", "images/status.gif");
672 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
674 image_link(_("Password Management"), "passwd", "images/passwd.gif");
676 printf("<HR>\n");
679 /****************************************************************************
680 * Handle Display/Edit Mode CGI
681 ****************************************************************************/
682 static void ViewModeBoxes(int mode)
684 printf("<p>%s:&nbsp;\n", _("Current View Is"));
685 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
686 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
687 printf("<br>%s:&nbsp;\n", _("Change View To"));
688 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
689 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
690 printf("</p><br>\n");
693 /****************************************************************************
694 display a welcome page
695 ****************************************************************************/
696 static void welcome_page(void)
698 if (file_exist("help/welcome.html")) {
699 include_html("help/welcome.html");
700 } else {
701 include_html("help/welcome-no-samba-doc.html");
705 /****************************************************************************
706 display the current smb.conf
707 ****************************************************************************/
708 static void viewconfig_page(void)
710 int full_view=0;
711 const char form_name[] = "viewconfig";
713 if (!verify_xsrf_token(form_name)) {
714 goto output_page;
717 if (cgi_variable("full_view")) {
718 full_view = 1;
721 output_page:
722 printf("<H2>%s</H2>\n", _("Current Config"));
723 printf("<form method=post>\n");
724 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
726 if (full_view) {
727 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
728 } else {
729 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
732 printf("<p><pre>");
733 write_config(stdout, full_view);
734 printf("</pre>");
735 printf("</form>\n");
738 /****************************************************************************
739 second screen of the wizard ... Fetch Configuration Parameters
740 ****************************************************************************/
741 static void wizard_params_page(void)
743 unsigned int parm_filter = FLAG_WIZARD;
744 const char form_name[] = "wizard_params";
746 /* Here we first set and commit all the parameters that were selected
747 in the previous screen. */
749 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
751 if (!verify_xsrf_token(form_name)) {
752 goto output_page;
755 if (cgi_variable("Commit")) {
756 commit_parameters(GLOBAL_SECTION_SNUM);
757 save_reload(-1);
760 output_page:
761 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
762 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
764 if (have_write_access) {
765 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
768 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
769 printf("<p>\n");
771 printf("<table>\n");
772 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
773 printf("</table>\n");
774 printf("</form>\n");
777 /****************************************************************************
778 Utility to just rewrite the smb.conf file - effectively just cleans it up
779 ****************************************************************************/
780 static void rewritecfg_file(void)
782 commit_parameters(GLOBAL_SECTION_SNUM);
783 save_reload(-1);
784 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
787 /****************************************************************************
788 wizard to create/modify the smb.conf file
789 ****************************************************************************/
790 static void wizard_page(void)
792 /* Set some variables to collect data from smb.conf */
793 int role = 0;
794 int winstype = 0;
795 int have_home = -1;
796 int HomeExpo = 0;
797 int SerType = 0;
798 const char form_name[] = "wizard";
800 if (!verify_xsrf_token(form_name)) {
801 goto output_page;
804 if (cgi_variable("Rewrite")) {
805 (void) rewritecfg_file();
806 return;
809 if (cgi_variable("GetWizardParams")){
810 (void) wizard_params_page();
811 return;
814 if (cgi_variable("Commit")){
815 SerType = atoi(cgi_variable_nonull("ServerType"));
816 winstype = atoi(cgi_variable_nonull("WINSType"));
817 have_home = lp_servicenumber(HOMES_NAME);
818 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
820 /* Plain text passwords are too badly broken - use encrypted passwords only */
821 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
823 switch ( SerType ){
824 case 0:
825 /* Stand-alone Server */
826 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
827 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
828 break;
829 case 1:
830 /* Domain Member */
831 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
832 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
833 break;
834 case 2:
835 /* Domain Controller */
836 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
837 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
838 break;
840 switch ( winstype ) {
841 case 0:
842 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
843 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
844 break;
845 case 1:
846 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
847 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
848 break;
849 case 2:
850 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
851 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
852 break;
855 /* Have to create Homes share? */
856 if ((HomeExpo == 1) && (have_home == -1)) {
857 const char *unix_share = HOMES_NAME;
859 load_config(False);
860 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
861 have_home = lp_servicenumber(HOMES_NAME);
862 lp_do_parameter( have_home, "read only", "No");
863 lp_do_parameter( have_home, "valid users", "%S");
864 lp_do_parameter( have_home, "browseable", "No");
865 commit_parameters(have_home);
866 save_reload(have_home);
869 /* Need to Delete Homes share? */
870 if ((HomeExpo == 0) && (have_home != -1)) {
871 lp_remove_service(have_home);
872 have_home = -1;
875 commit_parameters(GLOBAL_SECTION_SNUM);
876 save_reload(-1);
878 else
880 /* Now determine smb.conf WINS settings */
881 if (lp_wins_support())
882 winstype = 1;
883 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
884 winstype = 2;
886 /* Do we have a homes share? */
887 have_home = lp_servicenumber(HOMES_NAME);
889 if ((winstype == 2) && lp_wins_support())
890 winstype = 3;
892 role = lp_server_role();
894 output_page:
895 /* Here we go ... */
896 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
897 printf("<form method=post action=wizard>\n");
898 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
900 if (have_write_access) {
901 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
902 printf("%s", _("The same will happen if you press the commit button."));
903 printf("<br><br>\n");
904 printf("<center>");
905 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
906 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
907 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
908 printf("</center>\n");
911 printf("<hr>");
912 printf("<center><table border=0>");
913 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
914 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
915 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
916 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
917 printf("</tr>\n");
918 if (role == ROLE_DOMAIN_BDC) {
919 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
921 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
922 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
923 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
924 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
925 printf("</tr>\n");
926 printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
928 /* Print out the list of wins servers */
929 if(lp_wins_server_list()) {
930 int i;
931 const char **wins_servers = lp_wins_server_list();
932 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
935 printf("\"></td></tr>\n");
936 if (winstype == 3) {
937 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"));
938 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
940 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
941 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
942 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
943 printf("<td></td></tr>\n");
945 /* Enable this when we are ready ....
946 * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
947 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
948 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
949 * printf("<td></td></tr>\n");
952 printf("</table></center>");
953 printf("<hr>");
955 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
956 printf("</form>\n");
960 /****************************************************************************
961 display a globals editing page
962 ****************************************************************************/
963 static void globals_page(void)
965 unsigned int parm_filter = FLAG_BASIC;
966 int mode = 0;
967 const char form_name[] = "globals";
969 printf("<H2>%s</H2>\n", _("Global Parameters"));
971 if (!verify_xsrf_token(form_name)) {
972 goto output_page;
975 if (cgi_variable("Commit")) {
976 commit_parameters(GLOBAL_SECTION_SNUM);
977 save_reload(-1);
980 if ( cgi_variable("ViewMode") )
981 mode = atoi(cgi_variable_nonull("ViewMode"));
982 if ( cgi_variable("BasicMode"))
983 mode = 0;
984 if ( cgi_variable("AdvMode"))
985 mode = 1;
987 output_page:
988 printf("<form name=\"swatform\" method=post action=globals>\n");
989 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
991 ViewModeBoxes( mode );
992 switch ( mode ) {
993 case 0:
994 parm_filter = FLAG_BASIC;
995 break;
996 case 1:
997 parm_filter = FLAG_ADVANCED;
998 break;
1000 printf("<br>\n");
1001 if (have_write_access) {
1002 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
1003 _("Commit Changes"));
1006 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
1007 _("Reset Values"));
1009 printf("<p>\n");
1010 printf("<table>\n");
1011 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
1012 printf("</table>\n");
1013 printf("</form>\n");
1016 /****************************************************************************
1017 display a shares editing page. share is in unix codepage,
1018 ****************************************************************************/
1019 static void shares_page(void)
1021 const char *share = cgi_variable("share");
1022 char *s;
1023 char *utf8_s;
1024 int snum = -1;
1025 int i;
1026 int mode = 0;
1027 unsigned int parm_filter = FLAG_BASIC;
1028 size_t converted_size;
1029 const char form_name[] = "shares";
1031 printf("<H2>%s</H2>\n", _("Share Parameters"));
1033 if (!verify_xsrf_token(form_name)) {
1034 goto output_page;
1037 if (share)
1038 snum = lp_servicenumber(share);
1041 if (cgi_variable("Commit") && snum >= 0) {
1042 commit_parameters(snum);
1043 save_reload(-1);
1044 snum = lp_servicenumber(share);
1047 if (cgi_variable("Delete") && snum >= 0) {
1048 lp_remove_service(snum);
1049 save_reload(-1);
1050 share = NULL;
1051 snum = -1;
1054 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1055 snum = lp_servicenumber(share);
1056 if (snum < 0) {
1057 load_config(False);
1058 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1059 snum = lp_servicenumber(share);
1060 save_reload(snum);
1061 snum = lp_servicenumber(share);
1065 if ( cgi_variable("ViewMode") )
1066 mode = atoi(cgi_variable_nonull("ViewMode"));
1067 if ( cgi_variable("BasicMode"))
1068 mode = 0;
1069 if ( cgi_variable("AdvMode"))
1070 mode = 1;
1072 output_page:
1073 printf("<FORM name=\"swatform\" method=post>\n");
1074 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1076 printf("<table>\n");
1078 ViewModeBoxes( mode );
1079 switch ( mode ) {
1080 case 0:
1081 parm_filter = FLAG_BASIC;
1082 break;
1083 case 1:
1084 parm_filter = FLAG_ADVANCED;
1085 break;
1087 printf("<br><tr>\n");
1088 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1089 printf("<td><select name=share>\n");
1090 if (snum < 0)
1091 printf("<option value=\" \"> \n");
1092 for (i=0;i<lp_numservices();i++) {
1093 s = lp_servicename(i);
1094 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1095 push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1096 printf("<option %s value=\"%s\">%s\n",
1097 (share && strcmp(share,s)==0)?"SELECTED":"",
1098 utf8_s, utf8_s);
1099 TALLOC_FREE(utf8_s);
1102 printf("</select></td>\n");
1103 if (have_write_access) {
1104 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1106 printf("</tr>\n");
1107 printf("</table>");
1108 printf("<table>");
1109 if (have_write_access) {
1110 printf("<tr>\n");
1111 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1112 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1114 printf("</table>");
1117 if (snum >= 0) {
1118 if (have_write_access) {
1119 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1122 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1123 printf("<p>\n");
1126 if (snum >= 0) {
1127 printf("<table>\n");
1128 show_parameters(snum, 1, parm_filter, 0);
1129 printf("</table>\n");
1132 printf("</FORM>\n");
1135 /*************************************************************
1136 change a password either locally or remotely
1137 *************************************************************/
1138 static bool change_password(const char *remote_machine, const char *user_name,
1139 const char *old_passwd, const char *new_passwd,
1140 int local_flags)
1142 NTSTATUS ret;
1143 char *err_str = NULL;
1144 char *msg_str = NULL;
1146 if (demo_mode) {
1147 printf("%s\n<p>", _("password change in demo mode rejected"));
1148 return False;
1151 if (remote_machine != NULL) {
1152 ret = remote_password_change(remote_machine, user_name,
1153 old_passwd, new_passwd, &err_str);
1154 if (err_str != NULL)
1155 printf("%s\n<p>", err_str);
1156 SAFE_FREE(err_str);
1157 return NT_STATUS_IS_OK(ret);
1160 if(!initialize_password_db(True, NULL)) {
1161 printf("%s\n<p>", _("Can't setup password database vectors."));
1162 return False;
1165 ret = local_password_change(user_name, local_flags, new_passwd,
1166 &err_str, &msg_str);
1168 if(msg_str)
1169 printf("%s\n<p>", msg_str);
1170 if(err_str)
1171 printf("%s\n<p>", err_str);
1173 SAFE_FREE(msg_str);
1174 SAFE_FREE(err_str);
1175 return NT_STATUS_IS_OK(ret);
1178 /****************************************************************************
1179 do the stuff required to add or change a password
1180 ****************************************************************************/
1181 static void chg_passwd(void)
1183 const char *host;
1184 bool rslt;
1185 int local_flags = 0;
1187 /* Make sure users name has been specified */
1188 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1189 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1190 return;
1194 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1195 * so if that's what we're doing, skip the rest of the checks
1197 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1200 * If current user is not root, make sure old password has been specified
1201 * If REMOTE change, even root must provide old password
1203 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1204 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1205 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1206 return;
1209 /* If changing a users password on a remote hosts we have to know what host */
1210 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1211 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1212 return;
1215 /* Make sure new passwords have been specified */
1216 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1217 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1218 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1219 return;
1222 /* Make sure new passwords was typed correctly twice */
1223 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1224 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1225 return;
1229 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1230 host = cgi_variable(RHOST);
1231 } else if (am_root()) {
1232 host = NULL;
1233 } else {
1234 host = "127.0.0.1";
1238 * Set up the local flags.
1241 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1242 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1243 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1244 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1245 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1246 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1248 rslt = change_password(host,
1249 cgi_variable_nonull(SWAT_USER),
1250 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1251 local_flags);
1253 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1254 printf("<p>");
1255 if (rslt == True) {
1256 printf("%s\n", _(" The passwd has been changed."));
1257 } else {
1258 printf("%s\n", _(" The passwd has NOT been changed."));
1262 return;
1265 /****************************************************************************
1266 display a password editing page
1267 ****************************************************************************/
1268 static void passwd_page(void)
1270 const char *new_name = cgi_user_name();
1271 const char passwd_form[] = "passwd";
1272 const char rpasswd_form[] = "rpasswd";
1274 if (!new_name) new_name = "";
1276 printf("<H2>%s</H2>\n", _("Server Password Management"));
1278 printf("<FORM name=\"swatform\" method=post>\n");
1279 print_xsrf_token(cgi_user_name(), cgi_user_pass(), passwd_form);
1281 printf("<table>\n");
1284 * Create all the dialog boxes for data collection
1286 printf("<tr><td> %s : </td>\n", _("User Name"));
1287 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1288 if (!am_root()) {
1289 printf("<tr><td> %s : </td>\n", _("Old Password"));
1290 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1292 printf("<tr><td> %s : </td>\n", _("New Password"));
1293 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1294 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1295 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1296 printf("</table>\n");
1299 * Create all the control buttons for requesting action
1301 printf("<input type=submit name=%s value=\"%s\">\n",
1302 CHG_S_PASSWD_FLAG, _("Change Password"));
1303 if (demo_mode || am_root()) {
1304 printf("<input type=submit name=%s value=\"%s\">\n",
1305 ADD_USER_FLAG, _("Add New User"));
1306 printf("<input type=submit name=%s value=\"%s\">\n",
1307 DELETE_USER_FLAG, _("Delete User"));
1308 printf("<input type=submit name=%s value=\"%s\">\n",
1309 DISABLE_USER_FLAG, _("Disable User"));
1310 printf("<input type=submit name=%s value=\"%s\">\n",
1311 ENABLE_USER_FLAG, _("Enable User"));
1313 printf("<p></FORM>\n");
1316 * Do some work if change, add, disable or enable was
1317 * requested. It could be this is the first time through this
1318 * code, so there isn't anything to do. */
1319 if (verify_xsrf_token(passwd_form) &&
1320 ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1321 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG)))) {
1322 chg_passwd();
1325 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1327 printf("<FORM name=\"swatform\" method=post>\n");
1328 print_xsrf_token(cgi_user_name(), cgi_user_pass(), rpasswd_form);
1330 printf("<table>\n");
1333 * Create all the dialog boxes for data collection
1335 printf("<tr><td> %s : </td>\n", _("User Name"));
1336 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1337 printf("<tr><td> %s : </td>\n", _("Old Password"));
1338 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1339 printf("<tr><td> %s : </td>\n", _("New Password"));
1340 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1341 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1342 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1343 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1344 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1346 printf("</table>");
1349 * Create all the control buttons for requesting action
1351 printf("<input type=submit name=%s value=\"%s\">",
1352 CHG_R_PASSWD_FLAG, _("Change Password"));
1354 printf("<p></FORM>\n");
1357 * Do some work if a request has been made to change the
1358 * password somewhere other than the server. It could be this
1359 * is the first time through this code, so there isn't
1360 * anything to do. */
1361 if (verify_xsrf_token(passwd_form) && cgi_variable(CHG_R_PASSWD_FLAG)) {
1362 chg_passwd();
1367 /****************************************************************************
1368 display a printers editing page
1369 ****************************************************************************/
1370 static void printers_page(void)
1372 const char *share = cgi_variable("share");
1373 char *s;
1374 int snum=-1;
1375 int i;
1376 int mode = 0;
1377 unsigned int parm_filter = FLAG_BASIC;
1378 const char form_name[] = "printers";
1380 if (!verify_xsrf_token(form_name)) {
1381 goto output_page;
1384 if (share)
1385 snum = lp_servicenumber(share);
1387 if (cgi_variable("Commit") && snum >= 0) {
1388 commit_parameters(snum);
1389 if (snum >= iNumNonAutoPrintServices)
1390 save_reload(snum);
1391 else
1392 save_reload(-1);
1393 snum = lp_servicenumber(share);
1396 if (cgi_variable("Delete") && snum >= 0) {
1397 lp_remove_service(snum);
1398 save_reload(-1);
1399 share = NULL;
1400 snum = -1;
1403 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1404 snum = lp_servicenumber(share);
1405 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1406 load_config(False);
1407 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1408 snum = lp_servicenumber(share);
1409 lp_do_parameter(snum, "print ok", "Yes");
1410 save_reload(snum);
1411 snum = lp_servicenumber(share);
1415 if ( cgi_variable("ViewMode") )
1416 mode = atoi(cgi_variable_nonull("ViewMode"));
1417 if ( cgi_variable("BasicMode"))
1418 mode = 0;
1419 if ( cgi_variable("AdvMode"))
1420 mode = 1;
1422 output_page:
1423 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1425 printf("<H3>%s</H3>\n", _("Important Note:"));
1426 printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1427 printf("%s",_("are autoloaded printers from "));
1428 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1429 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1432 printf("<FORM name=\"swatform\" method=post>\n");
1433 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1435 ViewModeBoxes( mode );
1436 switch ( mode ) {
1437 case 0:
1438 parm_filter = FLAG_BASIC;
1439 break;
1440 case 1:
1441 parm_filter = FLAG_ADVANCED;
1442 break;
1444 printf("<table>\n");
1445 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1446 printf("<td><select name=\"share\">\n");
1447 if (snum < 0 || !lp_print_ok(snum))
1448 printf("<option value=\" \"> \n");
1449 for (i=0;i<lp_numservices();i++) {
1450 s = lp_servicename(i);
1451 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1452 if (i >= iNumNonAutoPrintServices)
1453 printf("<option %s value=\"%s\">[*]%s\n",
1454 (share && strcmp(share,s)==0)?"SELECTED":"",
1455 s, s);
1456 else
1457 printf("<option %s value=\"%s\">%s\n",
1458 (share && strcmp(share,s)==0)?"SELECTED":"",
1459 s, s);
1462 printf("</select></td>");
1463 if (have_write_access) {
1464 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1466 printf("</tr>");
1467 printf("</table>\n");
1469 if (have_write_access) {
1470 printf("<table>\n");
1471 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1472 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1473 printf("</table>");
1477 if (snum >= 0) {
1478 if (have_write_access) {
1479 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1481 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1482 printf("<p>\n");
1485 if (snum >= 0) {
1486 printf("<table>\n");
1487 show_parameters(snum, 1, parm_filter, 1);
1488 printf("</table>\n");
1490 printf("</FORM>\n");
1494 when the _() translation macro is used there is no obvious place to free
1495 the resulting string and there is no easy way to give a static pointer.
1496 All we can do is rotate between some static buffers and hope a single d_printf()
1497 doesn't have more calls to _() than the number of buffers
1500 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1502 const char *msgstr;
1503 const char *ret;
1505 msgstr = lang_msg(msgid);
1506 if (!msgstr) {
1507 return msgid;
1510 ret = talloc_strdup(ctx, msgstr);
1512 lang_msg_free(msgstr);
1513 if (!ret) {
1514 return msgid;
1517 return ret;
1521 * main function for SWAT.
1523 int main(int argc, char *argv[])
1525 const char *page;
1526 poptContext pc;
1527 struct poptOption long_options[] = {
1528 POPT_AUTOHELP
1529 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1530 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1531 POPT_COMMON_SAMBA
1532 POPT_TABLEEND
1534 TALLOC_CTX *frame = talloc_stackframe();
1536 fault_setup(NULL);
1537 umask(S_IWGRP | S_IWOTH);
1539 #if defined(HAVE_SET_AUTH_PARAMETERS)
1540 set_auth_parameters(argc, argv);
1541 #endif /* HAVE_SET_AUTH_PARAMETERS */
1543 /* just in case it goes wild ... */
1544 alarm(300);
1546 setlinebuf(stdout);
1548 /* we don't want any SIGPIPE messages */
1549 BlockSignals(True,SIGPIPE);
1551 debug_set_logfile("/dev/null");
1553 /* we don't want stderr screwing us up */
1554 close(2);
1555 open("/dev/null", O_WRONLY);
1556 setup_logging("swat", DEBUG_FILE);
1558 load_case_tables();
1560 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1562 /* Parse command line options */
1564 while(poptGetNextOpt(pc) != -1) { }
1566 poptFreeContext(pc);
1568 /* This should set a more apporiate log file */
1569 load_config(True);
1570 reopen_logs();
1571 load_interfaces();
1572 iNumNonAutoPrintServices = lp_numservices();
1573 if (pcap_cache_loaded()) {
1574 load_printers(server_event_context(),
1575 server_messaging_context());
1578 cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1580 print_header();
1582 cgi_load_variables();
1584 if (!file_exist(get_dyn_CONFIGFILE())) {
1585 have_read_access = True;
1586 have_write_access = True;
1587 } else {
1588 /* check if the authenticated user has write access - if not then
1589 don't show write options */
1590 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1592 /* if the user doesn't have read access to smb.conf then
1593 don't let them view it */
1594 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1597 show_main_buttons();
1599 page = cgi_pathinfo();
1601 /* Root gets full functionality */
1602 if (have_read_access && strcmp(page, "globals")==0) {
1603 globals_page();
1604 } else if (have_read_access && strcmp(page,"shares")==0) {
1605 shares_page();
1606 } else if (have_read_access && strcmp(page,"printers")==0) {
1607 printers_page();
1608 } else if (have_read_access && strcmp(page,"status")==0) {
1609 status_page();
1610 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1611 viewconfig_page();
1612 } else if (strcmp(page,"passwd")==0) {
1613 passwd_page();
1614 } else if (have_read_access && strcmp(page,"wizard")==0) {
1615 wizard_page();
1616 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1617 wizard_params_page();
1618 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1619 rewritecfg_file();
1620 } else {
1621 welcome_page();
1624 print_footer();
1626 TALLOC_FREE(frame);
1627 return 0;
1630 /** @} **/