swat: Use additional nonce on XSRF protection
[Samba.git] / source3 / web / swat.c
blobf8933d21c84fe7bb1d5eb3ab9e70c474755baf46
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;
157 char *nonce = cgi_nonce();
159 token_str[0] = '\0';
160 ZERO_STRUCT(md5_ctx);
161 MD5Init(&md5_ctx);
163 MD5Update(&md5_ctx, (uint8_t *)formname, strlen(formname));
164 MD5Update(&md5_ctx, (uint8_t *)&xsrf_time, sizeof(time_t));
165 if (username != NULL) {
166 MD5Update(&md5_ctx, (uint8_t *)username, strlen(username));
168 if (pass != NULL) {
169 MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
171 MD5Update(&md5_ctx, (uint8_t *)nonce, strlen(nonce));
173 MD5Final(token, &md5_ctx);
175 for(i = 0; i < sizeof(token); i++) {
176 char tmp[3];
178 snprintf(tmp, sizeof(tmp), "%02x", token[i]);
179 strlcat(token_str, tmp, sizeof(tmp));
183 void print_xsrf_token(const char *username, const char *pass,
184 const char *formname)
186 char token[33];
187 time_t xsrf_time = time(NULL);
189 get_xsrf_token(username, pass, formname, xsrf_time, token);
190 printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
191 XSRF_TOKEN, token);
192 printf("<input type=\"hidden\" name=\"%s\" value=\"%lld\">\n",
193 XSRF_TIME, (long long int)xsrf_time);
196 bool verify_xsrf_token(const char *formname)
198 char expected[33];
199 const char *username = cgi_user_name();
200 const char *pass = cgi_user_pass();
201 const char *token = cgi_variable_nonull(XSRF_TOKEN);
202 const char *time_str = cgi_variable_nonull(XSRF_TIME);
203 char *p = NULL;
204 long long xsrf_time_ll = 0;
205 time_t xsrf_time = 0;
206 time_t now = time(NULL);
208 errno = 0;
209 xsrf_time_ll = strtoll(time_str, &p, 10);
210 if (errno != 0) {
211 return false;
213 if (p == NULL) {
214 return false;
216 if (PTR_DIFF(p, time_str) > strlen(time_str)) {
217 return false;
219 if (xsrf_time_ll > _TYPE_MAXIMUM(time_t)) {
220 return false;
222 if (xsrf_time_ll < _TYPE_MINIMUM(time_t)) {
223 return false;
225 xsrf_time = xsrf_time_ll;
227 if (abs(now - xsrf_time) > XSRF_TIMEOUT) {
228 return false;
231 get_xsrf_token(username, pass, formname, xsrf_time, expected);
232 return (strncmp(expected, token, sizeof(expected)) == 0);
236 /****************************************************************************
237 include a lump of html in a page
238 ****************************************************************************/
239 static int include_html(const char *fname)
241 int fd;
242 char buf[1024];
243 int ret;
245 fd = web_open(fname, O_RDONLY, 0);
247 if (fd == -1) {
248 printf(_("ERROR: Can't open %s"), fname);
249 printf("\n");
250 return 0;
253 while ((ret = read(fd, buf, sizeof(buf))) > 0) {
254 if (write(1, buf, ret) == -1) {
255 break;
259 close(fd);
260 return 1;
263 /****************************************************************************
264 start the page with standard stuff
265 ****************************************************************************/
266 static void print_header(void)
268 if (!cgi_waspost()) {
269 printf("Expires: 0\r\n");
271 printf("Content-type: text/html\r\n");
272 printf("X-Frame-Options: DENY\r\n\r\n");
274 if (!include_html("include/header.html")) {
275 printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
276 printf("<HTML>\n<HEAD>\n<TITLE>Samba Web Administration Tool</TITLE>\n</HEAD>\n<BODY background=\"/swat/images/background.jpg\">\n\n");
280 /* *******************************************************************
281 show parameter label with translated name in the following form
282 because showing original and translated label in one line looks
283 too long, and showing translated label only is unusable for
284 heavy users.
285 -------------------------------
286 HELP security [combo box][button]
287 SECURITY
288 -------------------------------
289 (capital words are translated by gettext.)
290 if no translation is available, then same form as original is
291 used.
292 "i18n_translated_parm" class is used to change the color of the
293 translated parameter with CSS.
294 **************************************************************** */
295 static const char *get_parm_translated(TALLOC_CTX *ctx,
296 const char* pAnchor, const char* pHelp, const char* pLabel)
298 const char *pTranslated = _(pLabel);
299 char *output;
300 if(strcmp(pLabel, pTranslated) != 0) {
301 output = talloc_asprintf(ctx,
302 "<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>",
303 pAnchor, pHelp, pLabel, pTranslated);
304 return output;
306 output = talloc_asprintf(ctx,
307 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
308 pAnchor, pHelp, pLabel);
309 return output;
311 /****************************************************************************
312 finish off the page
313 ****************************************************************************/
314 static void print_footer(void)
316 if (!include_html("include/footer.html")) {
317 printf("\n</BODY>\n</HTML>\n");
321 /****************************************************************************
322 display one editable parameter in a form
323 ****************************************************************************/
324 static void show_parameter(int snum, struct parm_struct *parm)
326 int i;
327 void *ptr = parm->ptr;
328 char *utf8_s1, *utf8_s2;
329 size_t converted_size;
330 TALLOC_CTX *ctx = talloc_stackframe();
332 if (parm->p_class == P_LOCAL && snum >= 0) {
333 ptr = lp_local_ptr_by_snum(snum, ptr);
336 printf("<tr><td>%s</td><td>", get_parm_translated(ctx,
337 stripspaceupper(parm->label), _("Help"), parm->label));
338 switch (parm->type) {
339 case P_CHAR:
340 printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
341 make_parm_name(parm->label), *(char *)ptr);
342 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%c\'\">",
343 _("Set Default"), make_parm_name(parm->label),(char)(parm->def.cvalue));
344 break;
346 case P_LIST:
347 printf("<input type=text size=40 name=\"parm_%s\" value=\"",
348 make_parm_name(parm->label));
349 if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
350 char **list = *(char ***)ptr;
351 for (;*list;list++) {
352 /* enclose in HTML encoded quotes if the string contains a space */
353 if ( strchr_m(*list, ' ') ) {
354 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
355 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
356 printf("&quot;%s&quot;%s", utf8_s1, utf8_s2);
357 } else {
358 push_utf8_talloc(talloc_tos(), &utf8_s1, *list, &converted_size);
359 push_utf8_talloc(talloc_tos(), &utf8_s2, ((*(list+1))?", ":""), &converted_size);
360 printf("%s%s", utf8_s1, utf8_s2);
362 TALLOC_FREE(utf8_s1);
363 TALLOC_FREE(utf8_s2);
366 printf("\">");
367 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'",
368 _("Set Default"), make_parm_name(parm->label));
369 if (parm->def.lvalue) {
370 char **list = (char **)(parm->def.lvalue);
371 for (; *list; list++) {
372 /* enclose in HTML encoded quotes if the string contains a space */
373 if ( strchr_m(*list, ' ') )
374 printf("&quot;%s&quot;%s", *list, ((*(list+1))?", ":""));
375 else
376 printf("%s%s", *list, ((*(list+1))?", ":""));
379 printf("\'\">");
380 break;
382 case P_STRING:
383 case P_USTRING:
384 push_utf8_talloc(talloc_tos(), &utf8_s1, *(char **)ptr, &converted_size);
385 printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
386 make_parm_name(parm->label), fix_quotes(ctx, utf8_s1));
387 TALLOC_FREE(utf8_s1);
388 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
389 _("Set Default"), make_parm_name(parm->label),fix_backslash((char *)(parm->def.svalue)));
390 break;
392 case P_BOOL:
393 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
394 printf("<option %s>Yes", (*(bool *)ptr)?"selected":"");
395 printf("<option %s>No", (*(bool *)ptr)?"":"selected");
396 printf("</select>");
397 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
398 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?0:1);
399 break;
401 case P_BOOLREV:
402 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
403 printf("<option %s>Yes", (*(bool *)ptr)?"":"selected");
404 printf("<option %s>No", (*(bool *)ptr)?"selected":"");
405 printf("</select>");
406 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
407 _("Set Default"), make_parm_name(parm->label),(bool)(parm->def.bvalue)?1:0);
408 break;
410 case P_INTEGER:
411 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
412 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
413 _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
414 break;
416 case P_OCTAL: {
417 char *o;
418 o = octal_string(*(int *)ptr);
419 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
420 make_parm_name(parm->label), o);
421 TALLOC_FREE(o);
422 o = octal_string((int)(parm->def.ivalue));
423 printf("<input type=button value=\"%s\" "
424 "onClick=\"swatform.parm_%s.value=\'%s\'\">",
425 _("Set Default"), make_parm_name(parm->label), o);
426 TALLOC_FREE(o);
427 break;
430 case P_ENUM:
431 printf("<select name=\"parm_%s\">",make_parm_name(parm->label));
432 for (i=0;parm->enum_list[i].name;i++) {
433 if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
434 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
437 printf("</select>");
438 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
439 _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
440 break;
441 case P_SEP:
442 break;
444 printf("</td></tr>\n");
445 TALLOC_FREE(ctx);
448 /****************************************************************************
449 display a set of parameters for a service
450 ****************************************************************************/
451 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
453 int i = 0;
454 struct parm_struct *parm;
455 const char *heading = NULL;
456 const char *last_heading = NULL;
458 while ((parm = lp_next_parameter(snum, &i, allparameters))) {
459 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
460 continue;
461 if (parm->p_class == P_SEPARATOR) {
462 heading = parm->label;
463 continue;
465 if (parm->flags & FLAG_HIDE) continue;
466 if (snum >= 0) {
467 if (printers & !(parm->flags & FLAG_PRINT)) continue;
468 if (!printers & !(parm->flags & FLAG_SHARE)) continue;
471 if (!( parm_filter & FLAG_ADVANCED )) {
472 if (!(parm->flags & FLAG_BASIC)) {
473 void *ptr = parm->ptr;
475 if (parm->p_class == P_LOCAL && snum >= 0) {
476 ptr = lp_local_ptr_by_snum(snum, ptr);
479 switch (parm->type) {
480 case P_CHAR:
481 if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
482 break;
484 case P_LIST:
485 if (!str_list_equal(*(const char ***)ptr,
486 (const char **)(parm->def.lvalue))) continue;
487 break;
489 case P_STRING:
490 case P_USTRING:
491 if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
492 break;
494 case P_BOOL:
495 case P_BOOLREV:
496 if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
497 break;
499 case P_INTEGER:
500 case P_OCTAL:
501 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
502 break;
505 case P_ENUM:
506 if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
507 break;
508 case P_SEP:
509 continue;
512 if (printers && !(parm->flags & FLAG_PRINT)) continue;
515 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
517 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
519 if (heading && heading != last_heading) {
520 printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
521 last_heading = heading;
523 show_parameter(snum, parm);
527 /****************************************************************************
528 load the smb.conf file into loadparm.
529 ****************************************************************************/
530 static bool load_config(bool save_def)
532 return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
535 /****************************************************************************
536 write a config file
537 ****************************************************************************/
538 static void write_config(FILE *f, bool show_defaults)
540 TALLOC_CTX *ctx = talloc_stackframe();
542 fprintf(f, "# Samba config file created using SWAT\n");
543 fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
544 fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
546 lp_dump(f, show_defaults, iNumNonAutoPrintServices);
548 TALLOC_FREE(ctx);
551 /****************************************************************************
552 save and reload the smb.conf config file
553 ****************************************************************************/
554 static int save_reload(int snum)
556 FILE *f;
557 struct stat st;
559 f = sys_fopen(get_dyn_CONFIGFILE(),"w");
560 if (!f) {
561 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
562 printf("\n");
563 return 0;
566 /* just in case they have used the buggy xinetd to create the file */
567 if (fstat(fileno(f), &st) == 0 &&
568 (st.st_mode & S_IWOTH)) {
569 #if defined HAVE_FCHMOD
570 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
571 #else
572 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
573 #endif
576 write_config(f, False);
577 if (snum >= 0)
578 lp_dump_one(f, False, snum);
579 fclose(f);
581 lp_kill_all_services();
583 if (!load_config(False)) {
584 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
585 printf("\n");
586 return 0;
588 iNumNonAutoPrintServices = lp_numservices();
589 if (pcap_cache_loaded()) {
590 load_printers(server_event_context(),
591 server_messaging_context());
594 return 1;
597 /****************************************************************************
598 commit one parameter
599 ****************************************************************************/
600 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
602 int i;
603 char *s;
605 if (snum < 0 && parm->p_class == P_LOCAL) {
606 /* this handles the case where we are changing a local
607 variable globally. We need to change the parameter in
608 all shares where it is currently set to the default */
609 for (i=0;i<lp_numservices();i++) {
610 s = lp_servicename(i);
611 if (s && (*s) && lp_is_default(i, parm)) {
612 lp_do_parameter(i, parm->label, v);
617 lp_do_parameter(snum, parm->label, v);
620 /****************************************************************************
621 commit a set of parameters for a service
622 ****************************************************************************/
623 static void commit_parameters(int snum)
625 int i = 0;
626 struct parm_struct *parm;
627 char *label;
628 const char *v;
630 while ((parm = lp_next_parameter(snum, &i, 1))) {
631 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
632 if ((v = cgi_variable(label)) != NULL) {
633 if (parm->flags & FLAG_HIDE)
634 continue;
635 commit_parameter(snum, parm, v);
637 SAFE_FREE(label);
642 /****************************************************************************
643 spit out the html for a link with an image
644 ****************************************************************************/
645 static void image_link(const char *name, const char *hlink, const char *src)
647 printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n",
648 cgi_baseurl(), hlink, src, name);
651 /****************************************************************************
652 display the main navigation controls at the top of each page along
653 with a title
654 ****************************************************************************/
655 static void show_main_buttons(void)
657 char *p;
659 if ((p = cgi_user_name()) && strcmp(p, "root")) {
660 printf(_("Logged in as <b>%s</b>"), p);
661 printf("<p>\n");
664 image_link(_("Home"), "", "images/home.gif");
665 if (have_write_access) {
666 image_link(_("Globals"), "globals", "images/globals.gif");
667 image_link(_("Shares"), "shares", "images/shares.gif");
668 image_link(_("Printers"), "printers", "images/printers.gif");
669 image_link(_("Wizard"), "wizard", "images/wizard.gif");
671 /* root always gets all buttons, otherwise look for -P */
672 if ( have_write_access || (!passwd_only && have_read_access) ) {
673 image_link(_("Status"), "status", "images/status.gif");
674 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
676 image_link(_("Password Management"), "passwd", "images/passwd.gif");
678 printf("<HR>\n");
681 /****************************************************************************
682 * Handle Display/Edit Mode CGI
683 ****************************************************************************/
684 static void ViewModeBoxes(int mode)
686 printf("<p>%s:&nbsp;\n", _("Current View Is"));
687 printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
688 printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
689 printf("<br>%s:&nbsp;\n", _("Change View To"));
690 printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
691 printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
692 printf("</p><br>\n");
695 /****************************************************************************
696 display a welcome page
697 ****************************************************************************/
698 static void welcome_page(void)
700 if (file_exist("help/welcome.html")) {
701 include_html("help/welcome.html");
702 } else {
703 include_html("help/welcome-no-samba-doc.html");
707 /****************************************************************************
708 display the current smb.conf
709 ****************************************************************************/
710 static void viewconfig_page(void)
712 int full_view=0;
713 const char form_name[] = "viewconfig";
715 if (!verify_xsrf_token(form_name)) {
716 goto output_page;
719 if (cgi_variable("full_view")) {
720 full_view = 1;
723 output_page:
724 printf("<H2>%s</H2>\n", _("Current Config"));
725 printf("<form method=post>\n");
726 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
728 if (full_view) {
729 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
730 } else {
731 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
734 printf("<p><pre>");
735 write_config(stdout, full_view);
736 printf("</pre>");
737 printf("</form>\n");
740 /****************************************************************************
741 second screen of the wizard ... Fetch Configuration Parameters
742 ****************************************************************************/
743 static void wizard_params_page(void)
745 unsigned int parm_filter = FLAG_WIZARD;
746 const char form_name[] = "wizard_params";
748 /* Here we first set and commit all the parameters that were selected
749 in the previous screen. */
751 printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
753 if (!verify_xsrf_token(form_name)) {
754 goto output_page;
757 if (cgi_variable("Commit")) {
758 commit_parameters(GLOBAL_SECTION_SNUM);
759 save_reload(-1);
762 output_page:
763 printf("<form name=\"swatform\" method=post action=wizard_params>\n");
764 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
766 if (have_write_access) {
767 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
770 printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
771 printf("<p>\n");
773 printf("<table>\n");
774 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
775 printf("</table>\n");
776 printf("</form>\n");
779 /****************************************************************************
780 Utility to just rewrite the smb.conf file - effectively just cleans it up
781 ****************************************************************************/
782 static void rewritecfg_file(void)
784 commit_parameters(GLOBAL_SECTION_SNUM);
785 save_reload(-1);
786 printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
789 /****************************************************************************
790 wizard to create/modify the smb.conf file
791 ****************************************************************************/
792 static void wizard_page(void)
794 /* Set some variables to collect data from smb.conf */
795 int role = 0;
796 int winstype = 0;
797 int have_home = -1;
798 int HomeExpo = 0;
799 int SerType = 0;
800 const char form_name[] = "wizard";
802 if (!verify_xsrf_token(form_name)) {
803 goto output_page;
806 if (cgi_variable("Rewrite")) {
807 (void) rewritecfg_file();
808 return;
811 if (cgi_variable("GetWizardParams")){
812 (void) wizard_params_page();
813 return;
816 if (cgi_variable("Commit")){
817 SerType = atoi(cgi_variable_nonull("ServerType"));
818 winstype = atoi(cgi_variable_nonull("WINSType"));
819 have_home = lp_servicenumber(HOMES_NAME);
820 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
822 /* Plain text passwords are too badly broken - use encrypted passwords only */
823 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
825 switch ( SerType ){
826 case 0:
827 /* Stand-alone Server */
828 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
829 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
830 break;
831 case 1:
832 /* Domain Member */
833 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
834 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
835 break;
836 case 2:
837 /* Domain Controller */
838 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
839 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
840 break;
842 switch ( winstype ) {
843 case 0:
844 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
845 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
846 break;
847 case 1:
848 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
849 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
850 break;
851 case 2:
852 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
853 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
854 break;
857 /* Have to create Homes share? */
858 if ((HomeExpo == 1) && (have_home == -1)) {
859 const char *unix_share = HOMES_NAME;
861 load_config(False);
862 lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
863 have_home = lp_servicenumber(HOMES_NAME);
864 lp_do_parameter( have_home, "read only", "No");
865 lp_do_parameter( have_home, "valid users", "%S");
866 lp_do_parameter( have_home, "browseable", "No");
867 commit_parameters(have_home);
868 save_reload(have_home);
871 /* Need to Delete Homes share? */
872 if ((HomeExpo == 0) && (have_home != -1)) {
873 lp_remove_service(have_home);
874 have_home = -1;
877 commit_parameters(GLOBAL_SECTION_SNUM);
878 save_reload(-1);
880 else
882 /* Now determine smb.conf WINS settings */
883 if (lp_wins_support())
884 winstype = 1;
885 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
886 winstype = 2;
888 /* Do we have a homes share? */
889 have_home = lp_servicenumber(HOMES_NAME);
891 if ((winstype == 2) && lp_wins_support())
892 winstype = 3;
894 role = lp_server_role();
896 output_page:
897 /* Here we go ... */
898 printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
899 printf("<form method=post action=wizard>\n");
900 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
902 if (have_write_access) {
903 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
904 printf("%s", _("The same will happen if you press the commit button."));
905 printf("<br><br>\n");
906 printf("<center>");
907 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
908 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
909 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
910 printf("</center>\n");
913 printf("<hr>");
914 printf("<center><table border=0>");
915 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
916 printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
917 printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member"));
918 printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
919 printf("</tr>\n");
920 if (role == ROLE_DOMAIN_BDC) {
921 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
923 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
924 printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
925 printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
926 printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
927 printf("</tr>\n");
928 printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
930 /* Print out the list of wins servers */
931 if(lp_wins_server_list()) {
932 int i;
933 const char **wins_servers = lp_wins_server_list();
934 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
937 printf("\"></td></tr>\n");
938 if (winstype == 3) {
939 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"));
940 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
942 printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
943 printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
944 printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
945 printf("<td></td></tr>\n");
947 /* Enable this when we are ready ....
948 * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
949 * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
950 * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
951 * printf("<td></td></tr>\n");
954 printf("</table></center>");
955 printf("<hr>");
957 printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
958 printf("</form>\n");
962 /****************************************************************************
963 display a globals editing page
964 ****************************************************************************/
965 static void globals_page(void)
967 unsigned int parm_filter = FLAG_BASIC;
968 int mode = 0;
969 const char form_name[] = "globals";
971 printf("<H2>%s</H2>\n", _("Global Parameters"));
973 if (!verify_xsrf_token(form_name)) {
974 goto output_page;
977 if (cgi_variable("Commit")) {
978 commit_parameters(GLOBAL_SECTION_SNUM);
979 save_reload(-1);
982 if ( cgi_variable("ViewMode") )
983 mode = atoi(cgi_variable_nonull("ViewMode"));
984 if ( cgi_variable("BasicMode"))
985 mode = 0;
986 if ( cgi_variable("AdvMode"))
987 mode = 1;
989 output_page:
990 printf("<form name=\"swatform\" method=post action=globals>\n");
991 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
993 ViewModeBoxes( mode );
994 switch ( mode ) {
995 case 0:
996 parm_filter = FLAG_BASIC;
997 break;
998 case 1:
999 parm_filter = FLAG_ADVANCED;
1000 break;
1002 printf("<br>\n");
1003 if (have_write_access) {
1004 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
1005 _("Commit Changes"));
1008 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n",
1009 _("Reset Values"));
1011 printf("<p>\n");
1012 printf("<table>\n");
1013 show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
1014 printf("</table>\n");
1015 printf("</form>\n");
1018 /****************************************************************************
1019 display a shares editing page. share is in unix codepage,
1020 ****************************************************************************/
1021 static void shares_page(void)
1023 const char *share = cgi_variable("share");
1024 char *s;
1025 char *utf8_s;
1026 int snum = -1;
1027 int i;
1028 int mode = 0;
1029 unsigned int parm_filter = FLAG_BASIC;
1030 size_t converted_size;
1031 const char form_name[] = "shares";
1033 printf("<H2>%s</H2>\n", _("Share Parameters"));
1035 if (!verify_xsrf_token(form_name)) {
1036 goto output_page;
1039 if (share)
1040 snum = lp_servicenumber(share);
1043 if (cgi_variable("Commit") && snum >= 0) {
1044 commit_parameters(snum);
1045 save_reload(-1);
1046 snum = lp_servicenumber(share);
1049 if (cgi_variable("Delete") && snum >= 0) {
1050 lp_remove_service(snum);
1051 save_reload(-1);
1052 share = NULL;
1053 snum = -1;
1056 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1057 snum = lp_servicenumber(share);
1058 if (snum < 0) {
1059 load_config(False);
1060 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1061 snum = lp_servicenumber(share);
1062 save_reload(snum);
1063 snum = lp_servicenumber(share);
1067 if ( cgi_variable("ViewMode") )
1068 mode = atoi(cgi_variable_nonull("ViewMode"));
1069 if ( cgi_variable("BasicMode"))
1070 mode = 0;
1071 if ( cgi_variable("AdvMode"))
1072 mode = 1;
1074 output_page:
1075 printf("<FORM name=\"swatform\" method=post>\n");
1076 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1078 printf("<table>\n");
1080 ViewModeBoxes( mode );
1081 switch ( mode ) {
1082 case 0:
1083 parm_filter = FLAG_BASIC;
1084 break;
1085 case 1:
1086 parm_filter = FLAG_ADVANCED;
1087 break;
1089 printf("<br><tr>\n");
1090 printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1091 printf("<td><select name=share>\n");
1092 if (snum < 0)
1093 printf("<option value=\" \"> \n");
1094 for (i=0;i<lp_numservices();i++) {
1095 s = lp_servicename(i);
1096 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1097 push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1098 printf("<option %s value=\"%s\">%s\n",
1099 (share && strcmp(share,s)==0)?"SELECTED":"",
1100 utf8_s, utf8_s);
1101 TALLOC_FREE(utf8_s);
1104 printf("</select></td>\n");
1105 if (have_write_access) {
1106 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1108 printf("</tr>\n");
1109 printf("</table>");
1110 printf("<table>");
1111 if (have_write_access) {
1112 printf("<tr>\n");
1113 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1114 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1116 printf("</table>");
1119 if (snum >= 0) {
1120 if (have_write_access) {
1121 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1124 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1125 printf("<p>\n");
1128 if (snum >= 0) {
1129 printf("<table>\n");
1130 show_parameters(snum, 1, parm_filter, 0);
1131 printf("</table>\n");
1134 printf("</FORM>\n");
1137 /*************************************************************
1138 change a password either locally or remotely
1139 *************************************************************/
1140 static bool change_password(const char *remote_machine, const char *user_name,
1141 const char *old_passwd, const char *new_passwd,
1142 int local_flags)
1144 NTSTATUS ret;
1145 char *err_str = NULL;
1146 char *msg_str = NULL;
1148 if (demo_mode) {
1149 printf("%s\n<p>", _("password change in demo mode rejected"));
1150 return False;
1153 if (remote_machine != NULL) {
1154 ret = remote_password_change(remote_machine, user_name,
1155 old_passwd, new_passwd, &err_str);
1156 if (err_str != NULL)
1157 printf("%s\n<p>", err_str);
1158 SAFE_FREE(err_str);
1159 return NT_STATUS_IS_OK(ret);
1162 if(!initialize_password_db(True, NULL)) {
1163 printf("%s\n<p>", _("Can't setup password database vectors."));
1164 return False;
1167 ret = local_password_change(user_name, local_flags, new_passwd,
1168 &err_str, &msg_str);
1170 if(msg_str)
1171 printf("%s\n<p>", msg_str);
1172 if(err_str)
1173 printf("%s\n<p>", err_str);
1175 SAFE_FREE(msg_str);
1176 SAFE_FREE(err_str);
1177 return NT_STATUS_IS_OK(ret);
1180 /****************************************************************************
1181 do the stuff required to add or change a password
1182 ****************************************************************************/
1183 static void chg_passwd(void)
1185 const char *host;
1186 bool rslt;
1187 int local_flags = 0;
1189 /* Make sure users name has been specified */
1190 if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1191 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1192 return;
1196 * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1197 * so if that's what we're doing, skip the rest of the checks
1199 if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1202 * If current user is not root, make sure old password has been specified
1203 * If REMOTE change, even root must provide old password
1205 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1206 ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1207 printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1208 return;
1211 /* If changing a users password on a remote hosts we have to know what host */
1212 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1213 printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1214 return;
1217 /* Make sure new passwords have been specified */
1218 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1219 (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1220 printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1221 return;
1224 /* Make sure new passwords was typed correctly twice */
1225 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1226 printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1227 return;
1231 if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1232 host = cgi_variable(RHOST);
1233 } else if (am_root()) {
1234 host = NULL;
1235 } else {
1236 host = "127.0.0.1";
1240 * Set up the local flags.
1243 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1244 local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_SET_PASSWORD : 0);
1245 local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1246 local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1247 local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1248 local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1250 rslt = change_password(host,
1251 cgi_variable_nonull(SWAT_USER),
1252 cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1253 local_flags);
1255 if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1256 printf("<p>");
1257 if (rslt == True) {
1258 printf("%s\n", _(" The passwd has been changed."));
1259 } else {
1260 printf("%s\n", _(" The passwd has NOT been changed."));
1264 return;
1267 /****************************************************************************
1268 display a password editing page
1269 ****************************************************************************/
1270 static void passwd_page(void)
1272 const char *new_name = cgi_user_name();
1273 const char passwd_form[] = "passwd";
1274 const char rpasswd_form[] = "rpasswd";
1276 if (!new_name) new_name = "";
1278 printf("<H2>%s</H2>\n", _("Server Password Management"));
1280 printf("<FORM name=\"swatform\" method=post>\n");
1281 print_xsrf_token(cgi_user_name(), cgi_user_pass(), passwd_form);
1283 printf("<table>\n");
1286 * Create all the dialog boxes for data collection
1288 printf("<tr><td> %s : </td>\n", _("User Name"));
1289 printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1290 if (!am_root()) {
1291 printf("<tr><td> %s : </td>\n", _("Old Password"));
1292 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1294 printf("<tr><td> %s : </td>\n", _("New Password"));
1295 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1296 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1297 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1298 printf("</table>\n");
1301 * Create all the control buttons for requesting action
1303 printf("<input type=submit name=%s value=\"%s\">\n",
1304 CHG_S_PASSWD_FLAG, _("Change Password"));
1305 if (demo_mode || am_root()) {
1306 printf("<input type=submit name=%s value=\"%s\">\n",
1307 ADD_USER_FLAG, _("Add New User"));
1308 printf("<input type=submit name=%s value=\"%s\">\n",
1309 DELETE_USER_FLAG, _("Delete User"));
1310 printf("<input type=submit name=%s value=\"%s\">\n",
1311 DISABLE_USER_FLAG, _("Disable User"));
1312 printf("<input type=submit name=%s value=\"%s\">\n",
1313 ENABLE_USER_FLAG, _("Enable User"));
1315 printf("<p></FORM>\n");
1318 * Do some work if change, add, disable or enable was
1319 * requested. It could be this is the first time through this
1320 * code, so there isn't anything to do. */
1321 if (verify_xsrf_token(passwd_form) &&
1322 ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1323 (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG)))) {
1324 chg_passwd();
1327 printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1329 printf("<FORM name=\"swatform\" method=post>\n");
1330 print_xsrf_token(cgi_user_name(), cgi_user_pass(), rpasswd_form);
1332 printf("<table>\n");
1335 * Create all the dialog boxes for data collection
1337 printf("<tr><td> %s : </td>\n", _("User Name"));
1338 printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1339 printf("<tr><td> %s : </td>\n", _("Old Password"));
1340 printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1341 printf("<tr><td> %s : </td>\n", _("New Password"));
1342 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1343 printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1344 printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1345 printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1346 printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1348 printf("</table>");
1351 * Create all the control buttons for requesting action
1353 printf("<input type=submit name=%s value=\"%s\">",
1354 CHG_R_PASSWD_FLAG, _("Change Password"));
1356 printf("<p></FORM>\n");
1359 * Do some work if a request has been made to change the
1360 * password somewhere other than the server. It could be this
1361 * is the first time through this code, so there isn't
1362 * anything to do. */
1363 if (verify_xsrf_token(passwd_form) && cgi_variable(CHG_R_PASSWD_FLAG)) {
1364 chg_passwd();
1369 /****************************************************************************
1370 display a printers editing page
1371 ****************************************************************************/
1372 static void printers_page(void)
1374 const char *share = cgi_variable("share");
1375 char *s;
1376 int snum=-1;
1377 int i;
1378 int mode = 0;
1379 unsigned int parm_filter = FLAG_BASIC;
1380 const char form_name[] = "printers";
1382 if (!verify_xsrf_token(form_name)) {
1383 goto output_page;
1386 if (share)
1387 snum = lp_servicenumber(share);
1389 if (cgi_variable("Commit") && snum >= 0) {
1390 commit_parameters(snum);
1391 if (snum >= iNumNonAutoPrintServices)
1392 save_reload(snum);
1393 else
1394 save_reload(-1);
1395 snum = lp_servicenumber(share);
1398 if (cgi_variable("Delete") && snum >= 0) {
1399 lp_remove_service(snum);
1400 save_reload(-1);
1401 share = NULL;
1402 snum = -1;
1405 if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1406 snum = lp_servicenumber(share);
1407 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1408 load_config(False);
1409 lp_copy_service(GLOBAL_SECTION_SNUM, share);
1410 snum = lp_servicenumber(share);
1411 lp_do_parameter(snum, "print ok", "Yes");
1412 save_reload(snum);
1413 snum = lp_servicenumber(share);
1417 if ( cgi_variable("ViewMode") )
1418 mode = atoi(cgi_variable_nonull("ViewMode"));
1419 if ( cgi_variable("BasicMode"))
1420 mode = 0;
1421 if ( cgi_variable("AdvMode"))
1422 mode = 1;
1424 output_page:
1425 printf("<H2>%s</H2>\n", _("Printer Parameters"));
1427 printf("<H3>%s</H3>\n", _("Important Note:"));
1428 printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1429 printf("%s",_("are autoloaded printers from "));
1430 printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1431 printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1434 printf("<FORM name=\"swatform\" method=post>\n");
1435 print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1437 ViewModeBoxes( mode );
1438 switch ( mode ) {
1439 case 0:
1440 parm_filter = FLAG_BASIC;
1441 break;
1442 case 1:
1443 parm_filter = FLAG_ADVANCED;
1444 break;
1446 printf("<table>\n");
1447 printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1448 printf("<td><select name=\"share\">\n");
1449 if (snum < 0 || !lp_print_ok(snum))
1450 printf("<option value=\" \"> \n");
1451 for (i=0;i<lp_numservices();i++) {
1452 s = lp_servicename(i);
1453 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1454 if (i >= iNumNonAutoPrintServices)
1455 printf("<option %s value=\"%s\">[*]%s\n",
1456 (share && strcmp(share,s)==0)?"SELECTED":"",
1457 s, s);
1458 else
1459 printf("<option %s value=\"%s\">%s\n",
1460 (share && strcmp(share,s)==0)?"SELECTED":"",
1461 s, s);
1464 printf("</select></td>");
1465 if (have_write_access) {
1466 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1468 printf("</tr>");
1469 printf("</table>\n");
1471 if (have_write_access) {
1472 printf("<table>\n");
1473 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1474 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1475 printf("</table>");
1479 if (snum >= 0) {
1480 if (have_write_access) {
1481 printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1483 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1484 printf("<p>\n");
1487 if (snum >= 0) {
1488 printf("<table>\n");
1489 show_parameters(snum, 1, parm_filter, 1);
1490 printf("</table>\n");
1492 printf("</FORM>\n");
1496 when the _() translation macro is used there is no obvious place to free
1497 the resulting string and there is no easy way to give a static pointer.
1498 All we can do is rotate between some static buffers and hope a single d_printf()
1499 doesn't have more calls to _() than the number of buffers
1502 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1504 const char *msgstr;
1505 const char *ret;
1507 msgstr = lang_msg(msgid);
1508 if (!msgstr) {
1509 return msgid;
1512 ret = talloc_strdup(ctx, msgstr);
1514 lang_msg_free(msgstr);
1515 if (!ret) {
1516 return msgid;
1519 return ret;
1523 * main function for SWAT.
1525 int main(int argc, char *argv[])
1527 const char *page;
1528 poptContext pc;
1529 struct poptOption long_options[] = {
1530 POPT_AUTOHELP
1531 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1532 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" },
1533 POPT_COMMON_SAMBA
1534 POPT_TABLEEND
1536 TALLOC_CTX *frame = talloc_stackframe();
1538 fault_setup(NULL);
1539 umask(S_IWGRP | S_IWOTH);
1541 #if defined(HAVE_SET_AUTH_PARAMETERS)
1542 set_auth_parameters(argc, argv);
1543 #endif /* HAVE_SET_AUTH_PARAMETERS */
1545 /* just in case it goes wild ... */
1546 alarm(300);
1548 setlinebuf(stdout);
1550 /* we don't want any SIGPIPE messages */
1551 BlockSignals(True,SIGPIPE);
1553 debug_set_logfile("/dev/null");
1555 /* we don't want stderr screwing us up */
1556 close(2);
1557 open("/dev/null", O_WRONLY);
1558 setup_logging("swat", DEBUG_FILE);
1560 load_case_tables();
1562 pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1564 /* Parse command line options */
1566 while(poptGetNextOpt(pc) != -1) { }
1568 poptFreeContext(pc);
1570 /* This should set a more apporiate log file */
1571 load_config(True);
1572 reopen_logs();
1573 load_interfaces();
1574 iNumNonAutoPrintServices = lp_numservices();
1575 if (pcap_cache_loaded()) {
1576 load_printers(server_event_context(),
1577 server_messaging_context());
1580 cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1582 print_header();
1584 cgi_load_variables();
1586 if (!file_exist(get_dyn_CONFIGFILE())) {
1587 have_read_access = True;
1588 have_write_access = True;
1589 } else {
1590 /* check if the authenticated user has write access - if not then
1591 don't show write options */
1592 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1594 /* if the user doesn't have read access to smb.conf then
1595 don't let them view it */
1596 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1599 show_main_buttons();
1601 page = cgi_pathinfo();
1603 /* Root gets full functionality */
1604 if (have_read_access && strcmp(page, "globals")==0) {
1605 globals_page();
1606 } else if (have_read_access && strcmp(page,"shares")==0) {
1607 shares_page();
1608 } else if (have_read_access && strcmp(page,"printers")==0) {
1609 printers_page();
1610 } else if (have_read_access && strcmp(page,"status")==0) {
1611 status_page();
1612 } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1613 viewconfig_page();
1614 } else if (strcmp(page,"passwd")==0) {
1615 passwd_page();
1616 } else if (have_read_access && strcmp(page,"wizard")==0) {
1617 wizard_page();
1618 } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1619 wizard_params_page();
1620 } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1621 rewritecfg_file();
1622 } else {
1623 welcome_page();
1626 print_footer();
1628 TALLOC_FREE(frame);
1629 return 0;
1632 /** @} **/