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