param: handle P_BYTES in more places
[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         case P_BYTES:
413                 printf("<input type=text size=8 name=\"parm_%s\" value=\"%d\">", make_parm_name(parm->label), *(int *)ptr);
414                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%d\'\">",
415                         _("Set Default"), make_parm_name(parm->label),(int)(parm->def.ivalue));
416                 break;
417
418         case P_OCTAL: {
419                 char *o;
420                 o = octal_string(*(int *)ptr);
421                 printf("<input type=text size=8 name=\"parm_%s\" value=%s>",
422                        make_parm_name(parm->label), o);
423                 TALLOC_FREE(o);
424                 o = octal_string((int)(parm->def.ivalue));
425                 printf("<input type=button value=\"%s\" "
426                        "onClick=\"swatform.parm_%s.value=\'%s\'\">",
427                        _("Set Default"), make_parm_name(parm->label), o);
428                 TALLOC_FREE(o);
429                 break;
430         }
431
432         case P_ENUM:
433                 printf("<select name=\"parm_%s\">",make_parm_name(parm->label)); 
434                 for (i=0;parm->enum_list[i].name;i++) {
435                         if (i == 0 || parm->enum_list[i].value != parm->enum_list[i-1].value) {
436                                 printf("<option %s>%s",(*(int *)ptr)==parm->enum_list[i].value?"selected":"",parm->enum_list[i].name);
437                         }
438                 }
439                 printf("</select>");
440                 printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.selectedIndex=\'%d\'\">",
441                         _("Set Default"), make_parm_name(parm->label),enum_index((int)(parm->def.ivalue),parm->enum_list));
442                 break;
443         case P_SEP:
444                 break;
445         }
446         printf("</td></tr>\n");
447         TALLOC_FREE(ctx);
448 }
449
450 /****************************************************************************
451   display a set of parameters for a service 
452 ****************************************************************************/
453 static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
454 {
455         int i = 0;
456         struct parm_struct *parm;
457         const char *heading = NULL;
458         const char *last_heading = NULL;
459
460         while ((parm = lp_next_parameter(snum, &i, allparameters))) {
461                 if (snum < 0 && parm->p_class == P_LOCAL && !(parm->flags & FLAG_GLOBAL))
462                         continue;
463                 if (parm->p_class == P_SEPARATOR) {
464                         heading = parm->label;
465                         continue;
466                 }
467                 if (parm->flags & FLAG_HIDE) continue;
468                 if (snum >= 0) {
469                         if (printers & !(parm->flags & FLAG_PRINT)) continue;
470                         if (!printers & !(parm->flags & FLAG_SHARE)) continue;
471                 }
472
473                 if (!( parm_filter & FLAG_ADVANCED )) {
474                         if (!(parm->flags & FLAG_BASIC)) {
475                                 void *ptr;
476                                 if (parm->p_class == P_LOCAL && snum >= 0) {
477                                         ptr = lp_local_ptr_by_snum(snum, parm);
478                                 } else {
479                                         ptr = lp_parm_ptr(NULL, parm);
480                                 }
481
482                                 switch (parm->type) {
483                                 case P_CHAR:
484                                         if (*(char *)ptr == (char)(parm->def.cvalue)) continue;
485                                         break;
486
487                                 case P_LIST:
488                                         if (!str_list_equal(*(const char ***)ptr, 
489                                                             (const char **)(parm->def.lvalue))) continue;
490                                         break;
491
492                                 case P_STRING:
493                                 case P_USTRING:
494                                         if (!strcmp(*(char **)ptr,(char *)(parm->def.svalue))) continue;
495                                         break;
496
497                                 case P_BOOL:
498                                 case P_BOOLREV:
499                                         if (*(bool *)ptr == (bool)(parm->def.bvalue)) continue;
500                                         break;
501
502                                 case P_INTEGER:
503                                 case P_BYTES:
504                                 case P_OCTAL:
505                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
506                                         break;
507
508
509                                 case P_ENUM:
510                                         if (*(int *)ptr == (int)(parm->def.ivalue)) continue;
511                                         break;
512                                 case P_SEP:
513                                         continue;
514                                         }
515                         }
516                         if (printers && !(parm->flags & FLAG_PRINT)) continue;
517                 }
518
519                 if ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue;
520
521                 if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue;
522
523                 if (heading && heading != last_heading) {
524                         printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
525                         last_heading = heading;
526                 }
527                 show_parameter(snum, parm);
528         }
529 }
530
531 /****************************************************************************
532   load the smb.conf file into loadparm.
533 ****************************************************************************/
534 static bool load_config(bool save_def)
535 {
536         return lp_load(get_dyn_CONFIGFILE(),False,save_def,False,True);
537 }
538
539 /****************************************************************************
540   write a config file 
541 ****************************************************************************/
542 static void write_config(FILE *f, bool show_defaults)
543 {
544         TALLOC_CTX *ctx = talloc_stackframe();
545
546         fprintf(f, "# Samba config file created using SWAT\n");
547         fprintf(f, "# from %s (%s)\n", cgi_remote_host(), cgi_remote_addr());
548         fprintf(f, "# Date: %s\n\n", current_timestring(ctx, False));
549
550         lp_dump(f, show_defaults, iNumNonAutoPrintServices);
551
552         TALLOC_FREE(ctx);
553 }
554
555 /****************************************************************************
556   save and reload the smb.conf config file 
557 ****************************************************************************/
558 static int save_reload(int snum)
559 {
560         FILE *f;
561         struct stat st;
562
563         f = sys_fopen(get_dyn_CONFIGFILE(),"w");
564         if (!f) {
565                 printf(_("failed to open %s for writing"), get_dyn_CONFIGFILE());
566                 printf("\n");
567                 return 0;
568         }
569
570         /* just in case they have used the buggy xinetd to create the file */
571         if (fstat(fileno(f), &st) == 0 &&
572             (st.st_mode & S_IWOTH)) {
573 #if defined HAVE_FCHMOD
574                 fchmod(fileno(f), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
575 #else
576                 chmod(get_dyn_CONFIGFILE(), S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
577 #endif
578         }
579
580         write_config(f, False);
581         if (snum >= 0)
582                 lp_dump_one(f, False, snum);
583         fclose(f);
584
585         lp_kill_all_services();
586
587         if (!load_config(False)) {
588                 printf(_("Can't reload %s"), get_dyn_CONFIGFILE());
589                 printf("\n");
590                 return 0;
591         }
592         iNumNonAutoPrintServices = lp_numservices();
593         if (pcap_cache_loaded()) {
594                 struct tevent_context *ev_ctx;
595                 struct messaging_context *msg_ctx;
596
597                 ev_ctx = s3_tevent_context_init(NULL);
598                 if (ev_ctx == NULL) {
599                         printf("s3_tevent_context_init() failed\n");
600                         return 0;
601                 }
602                 msg_ctx = messaging_init(ev_ctx, ev_ctx);
603                 if (msg_ctx == NULL) {
604                         printf("messaging_init() failed\n");
605                         return 0;
606                 }
607
608                 load_printers(ev_ctx, msg_ctx);
609
610                 talloc_free(ev_ctx);
611         }
612
613         return 1;
614 }
615
616 /****************************************************************************
617   commit one parameter 
618 ****************************************************************************/
619 static void commit_parameter(int snum, struct parm_struct *parm, const char *v)
620 {
621         int i;
622         char *s;
623
624         if (snum < 0 && parm->p_class == P_LOCAL) {
625                 /* this handles the case where we are changing a local
626                    variable globally. We need to change the parameter in 
627                    all shares where it is currently set to the default */
628                 for (i=0;i<lp_numservices();i++) {
629                         s = lp_servicename(i);
630                         if (s && (*s) && lp_is_default(i, parm)) {
631                                 lp_do_parameter(i, parm->label, v);
632                         }
633                 }
634         }
635
636         lp_do_parameter(snum, parm->label, v);
637 }
638
639 /****************************************************************************
640   commit a set of parameters for a service 
641 ****************************************************************************/
642 static void commit_parameters(int snum)
643 {
644         int i = 0;
645         struct parm_struct *parm;
646         char *label;
647         const char *v;
648
649         while ((parm = lp_next_parameter(snum, &i, 1))) {
650                 if (asprintf(&label, "parm_%s", make_parm_name(parm->label)) > 0) {
651                         if ((v = cgi_variable(label)) != NULL) {
652                                 if (parm->flags & FLAG_HIDE)
653                                         continue;
654                                 commit_parameter(snum, parm, v);
655                         }
656                         SAFE_FREE(label);
657                 }
658         }
659 }
660
661 /****************************************************************************
662   spit out the html for a link with an image 
663 ****************************************************************************/
664 static void image_link(const char *name, const char *hlink, const char *src)
665 {
666         printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n", 
667                cgi_baseurl(), hlink, src, name);
668 }
669
670 /****************************************************************************
671   display the main navigation controls at the top of each page along
672   with a title 
673 ****************************************************************************/
674 static void show_main_buttons(void)
675 {
676         char *p;
677
678         if ((p = cgi_user_name()) && strcmp(p, "root")) {
679                 printf(_("Logged in as <b>%s</b>"), p);
680                 printf("<p>\n");
681         }
682
683         image_link(_("Home"), "", "images/home.gif");
684         if (have_write_access) {
685                 image_link(_("Globals"), "globals", "images/globals.gif");
686                 image_link(_("Shares"), "shares", "images/shares.gif");
687                 image_link(_("Printers"), "printers", "images/printers.gif");
688                 image_link(_("Wizard"), "wizard", "images/wizard.gif");
689         }
690    /* root always gets all buttons, otherwise look for -P */
691         if ( have_write_access || (!passwd_only && have_read_access) ) {
692                 image_link(_("Status"), "status", "images/status.gif");
693                 image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
694         }
695         image_link(_("Password Management"), "passwd", "images/passwd.gif");
696
697         printf("<HR>\n");
698 }
699
700 /****************************************************************************
701  * Handle Display/Edit Mode CGI
702  ****************************************************************************/
703 static void ViewModeBoxes(int mode)
704 {
705         printf("<p>%s:&nbsp;\n", _("Current View Is"));
706         printf("<input type=radio name=\"ViewMode\" value=0 %s>%s\n", ((mode == 0) ? "checked" : ""), _("Basic"));
707         printf("<input type=radio name=\"ViewMode\" value=1 %s>%s\n", ((mode == 1) ? "checked" : ""), _("Advanced"));
708         printf("<br>%s:&nbsp;\n", _("Change View To"));
709         printf("<input type=submit name=\"BasicMode\" value=\"%s\">\n", _("Basic"));
710         printf("<input type=submit name=\"AdvMode\" value=\"%s\">\n", _("Advanced"));
711         printf("</p><br>\n");
712 }
713
714 /****************************************************************************
715   display a welcome page  
716 ****************************************************************************/
717 static void welcome_page(void)
718 {
719         if (file_exist("help/welcome.html")) {
720                 include_html("help/welcome.html");
721         } else {
722                 include_html("help/welcome-no-samba-doc.html");
723         }
724 }
725
726 /****************************************************************************
727   display the current smb.conf  
728 ****************************************************************************/
729 static void viewconfig_page(void)
730 {
731         int full_view=0;
732         const char form_name[] = "viewconfig";
733
734         if (!verify_xsrf_token(form_name)) {
735                 goto output_page;
736         }
737
738         if (cgi_variable("full_view")) {
739                 full_view = 1;
740         }
741
742 output_page:
743         printf("<H2>%s</H2>\n", _("Current Config"));
744         printf("<form method=post>\n");
745         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
746
747         if (full_view) {
748                 printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View"));
749         } else {
750                 printf("<input type=submit name=\"full_view\" value=\"%s\">\n", _("Full View"));
751         }
752
753         printf("<p><pre>");
754         write_config(stdout, full_view);
755         printf("</pre>");
756         printf("</form>\n");
757 }
758
759 /****************************************************************************
760   second screen of the wizard ... Fetch Configuration Parameters
761 ****************************************************************************/
762 static void wizard_params_page(void)
763 {
764         unsigned int parm_filter = FLAG_WIZARD;
765         const char form_name[] = "wizard_params";
766
767         /* Here we first set and commit all the parameters that were selected
768            in the previous screen. */
769
770         printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
771
772         if (!verify_xsrf_token(form_name)) {
773                 goto output_page;
774         }
775
776         if (cgi_variable("Commit")) {
777                 commit_parameters(GLOBAL_SECTION_SNUM);
778                 save_reload(-1);
779         }
780
781 output_page:
782         printf("<form name=\"swatform\" method=post action=wizard_params>\n");
783         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
784
785         if (have_write_access) {
786                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
787         }
788
789         printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
790         printf("<p>\n");
791
792         printf("<table>\n");
793         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
794         printf("</table>\n");
795         printf("</form>\n");
796 }
797
798 /****************************************************************************
799   Utility to just rewrite the smb.conf file - effectively just cleans it up
800 ****************************************************************************/
801 static void rewritecfg_file(void)
802 {
803         commit_parameters(GLOBAL_SECTION_SNUM);
804         save_reload(-1);
805         printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
806 }
807
808 /****************************************************************************
809   wizard to create/modify the smb.conf file
810 ****************************************************************************/
811 static void wizard_page(void)
812 {
813         /* Set some variables to collect data from smb.conf */
814         int role = 0;
815         int winstype = 0;
816         int have_home = -1;
817         int HomeExpo = 0;
818         int SerType = 0;
819         const char form_name[] = "wizard";
820
821         if (!verify_xsrf_token(form_name)) {
822                 goto output_page;
823         }
824
825         if (cgi_variable("Rewrite")) {
826                 (void) rewritecfg_file();
827                 return;
828         }
829
830         if (cgi_variable("GetWizardParams")){
831                 (void) wizard_params_page();
832                 return;
833         }
834
835         if (cgi_variable("Commit")){
836                 SerType = atoi(cgi_variable_nonull("ServerType"));
837                 winstype = atoi(cgi_variable_nonull("WINSType"));
838                 have_home = lp_servicenumber(HOMES_NAME);
839                 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
840
841                 /* Plain text passwords are too badly broken - use encrypted passwords only */
842                 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
843
844                 switch ( SerType ){
845                         case 0:
846                                 /* Stand-alone Server */
847                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
848                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
849                                 break;
850                         case 1:
851                                 /* Domain Member */
852                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
853                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
854                                 break;
855                         case 2:
856                                 /* Domain Controller */
857                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
858                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
859                                 break;
860                 }
861                 switch ( winstype ) {
862                         case 0:
863                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
864                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
865                                 break;
866                         case 1:
867                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
868                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
869                                 break;
870                         case 2:
871                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
872                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
873                                 break;
874                 }
875
876                 /* Have to create Homes share? */
877                 if ((HomeExpo == 1) && (have_home == -1)) {
878                         const char *unix_share = HOMES_NAME;
879
880                         load_config(False);
881                         lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
882                         have_home = lp_servicenumber(HOMES_NAME);
883                         lp_do_parameter( have_home, "read only", "No");
884                         lp_do_parameter( have_home, "valid users", "%S");
885                         lp_do_parameter( have_home, "browseable", "No");
886                         commit_parameters(have_home);
887                         save_reload(have_home);
888                 }
889
890                 /* Need to Delete Homes share? */
891                 if ((HomeExpo == 0) && (have_home != -1)) {
892                         lp_remove_service(have_home);
893                         have_home = -1;
894                 }
895
896                 commit_parameters(GLOBAL_SECTION_SNUM);
897                 save_reload(-1);
898         }
899         else
900         {
901                 /* Now determine smb.conf WINS settings */
902                 if (lp_we_are_a_wins_server())
903                         winstype = 1;
904                 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
905                         winstype = 2;
906
907                 /* Do we have a homes share? */
908                 have_home = lp_servicenumber(HOMES_NAME);
909         }
910         if ((winstype == 2) && lp_we_are_a_wins_server())
911                 winstype = 3;
912
913         role = lp_server_role();
914
915 output_page:
916         /* Here we go ... */
917         printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
918         printf("<form method=post action=wizard>\n");
919         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
920
921         if (have_write_access) {
922                 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
923                 printf("%s", _("The same will happen if you press the commit button."));
924                 printf("<br><br>\n");
925                 printf("<center>");
926                 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
927                 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
928                 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
929                 printf("</center>\n");
930         }
931
932         printf("<hr>");
933         printf("<center><table border=0>");
934         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
935         printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
936         printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member")); 
937         printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
938         printf("</tr>\n");
939         if (role == ROLE_DOMAIN_BDC) {
940                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
941         }
942         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
943         printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
944         printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
945         printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
946         printf("</tr>\n");
947         printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
948
949         /* Print out the list of wins servers */
950         if(lp_wins_server_list()) {
951                 int i;
952                 const char **wins_servers = lp_wins_server_list();
953                 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
954         }
955
956         printf("\"></td></tr>\n");
957         if (winstype == 3) {
958                 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"));
959                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
960         }
961         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
962         printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
963         printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
964         printf("<td></td></tr>\n");
965
966         /* Enable this when we are ready ....
967          * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
968          * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
969          * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
970          * printf("<td></td></tr>\n");
971          */
972
973         printf("</table></center>");
974         printf("<hr>");
975
976         printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
977         printf("</form>\n");
978 }
979
980
981 /****************************************************************************
982   display a globals editing page  
983 ****************************************************************************/
984 static void globals_page(void)
985 {
986         unsigned int parm_filter = FLAG_BASIC;
987         int mode = 0;
988         const char form_name[] = "globals";
989
990         printf("<H2>%s</H2>\n", _("Global Parameters"));
991
992         if (!verify_xsrf_token(form_name)) {
993                 goto output_page;
994         }
995
996         if (cgi_variable("Commit")) {
997                 commit_parameters(GLOBAL_SECTION_SNUM);
998                 save_reload(-1);
999         }
1000
1001         if ( cgi_variable("ViewMode") )
1002                 mode = atoi(cgi_variable_nonull("ViewMode"));
1003         if ( cgi_variable("BasicMode"))
1004                 mode = 0;
1005         if ( cgi_variable("AdvMode"))
1006                 mode = 1;
1007
1008 output_page:
1009         printf("<form name=\"swatform\" method=post action=globals>\n");
1010         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1011
1012         ViewModeBoxes( mode );
1013         switch ( mode ) {
1014                 case 0:
1015                         parm_filter = FLAG_BASIC;
1016                         break;
1017                 case 1:
1018                         parm_filter = FLAG_ADVANCED;
1019                         break;
1020         }
1021         printf("<br>\n");
1022         if (have_write_access) {
1023                 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
1024                         _("Commit Changes"));
1025         }
1026
1027         printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", 
1028                  _("Reset Values"));
1029
1030         printf("<p>\n");
1031         printf("<table>\n");
1032         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
1033         printf("</table>\n");
1034         printf("</form>\n");
1035 }
1036
1037 /****************************************************************************
1038   display a shares editing page. share is in unix codepage, 
1039 ****************************************************************************/
1040 static void shares_page(void)
1041 {
1042         const char *share = cgi_variable("share");
1043         char *s;
1044         char *utf8_s;
1045         int snum = -1;
1046         int i;
1047         int mode = 0;
1048         unsigned int parm_filter = FLAG_BASIC;
1049         size_t converted_size;
1050         const char form_name[] = "shares";
1051
1052         printf("<H2>%s</H2>\n", _("Share Parameters"));
1053
1054         if (!verify_xsrf_token(form_name)) {
1055                 goto output_page;
1056         }
1057
1058         if (share)
1059                 snum = lp_servicenumber(share);
1060
1061
1062         if (cgi_variable("Commit") && snum >= 0) {
1063                 commit_parameters(snum);
1064                 save_reload(-1);
1065                 snum = lp_servicenumber(share);
1066         }
1067
1068         if (cgi_variable("Delete") && snum >= 0) {
1069                 lp_remove_service(snum);
1070                 save_reload(-1);
1071                 share = NULL;
1072                 snum = -1;
1073         }
1074
1075         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1076                 snum = lp_servicenumber(share);
1077                 if (snum < 0) {
1078                         load_config(False);
1079                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1080                         snum = lp_servicenumber(share);
1081                         save_reload(snum);
1082                         snum = lp_servicenumber(share);
1083                 }
1084         }
1085
1086         if ( cgi_variable("ViewMode") )
1087                 mode = atoi(cgi_variable_nonull("ViewMode"));
1088         if ( cgi_variable("BasicMode"))
1089                 mode = 0;
1090         if ( cgi_variable("AdvMode"))
1091                 mode = 1;
1092
1093 output_page:
1094         printf("<FORM name=\"swatform\" method=post>\n");
1095         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1096
1097         printf("<table>\n");
1098
1099         ViewModeBoxes( mode );
1100         switch ( mode ) {
1101                 case 0:
1102                         parm_filter = FLAG_BASIC;
1103                         break;
1104                 case 1:
1105                         parm_filter = FLAG_ADVANCED;
1106                         break;
1107         }
1108         printf("<br><tr>\n");
1109         printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1110         printf("<td><select name=share>\n");
1111         if (snum < 0)
1112                 printf("<option value=\" \"> \n");
1113         for (i=0;i<lp_numservices();i++) {
1114                 s = lp_servicename(i);
1115                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1116                         push_utf8_talloc(talloc_tos(), &utf8_s, s, &converted_size);
1117                         printf("<option %s value=\"%s\">%s\n", 
1118                                (share && strcmp(share,s)==0)?"SELECTED":"",
1119                                utf8_s, utf8_s);
1120                         TALLOC_FREE(utf8_s);
1121                 }
1122         }
1123         printf("</select></td>\n");
1124         if (have_write_access) {
1125                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1126         }
1127         printf("</tr>\n");
1128         printf("</table>");
1129         printf("<table>");
1130         if (have_write_access) {
1131                 printf("<tr>\n");
1132                 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1133                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1134         }
1135         printf("</table>");
1136
1137
1138         if (snum >= 0) {
1139                 if (have_write_access) {
1140                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1141                 }
1142
1143                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1144                 printf("<p>\n");
1145         }
1146
1147         if (snum >= 0) {
1148                 printf("<table>\n");
1149                 show_parameters(snum, 1, parm_filter, 0);
1150                 printf("</table>\n");
1151         }
1152
1153         printf("</FORM>\n");
1154 }
1155
1156 /*************************************************************
1157 change a password either locally or remotely
1158 *************************************************************/
1159 static bool change_password(const char *remote_machine, const char *user_name, 
1160                             const char *old_passwd, const char *new_passwd, 
1161                                 int local_flags)
1162 {
1163         NTSTATUS ret;
1164         char *err_str = NULL;
1165         char *msg_str = NULL;
1166
1167         if (demo_mode) {
1168                 printf("%s\n<p>", _("password change in demo mode rejected"));
1169                 return False;
1170         }
1171
1172         if (remote_machine != NULL) {
1173                 ret = remote_password_change(remote_machine, user_name,
1174                                              old_passwd, new_passwd, &err_str);
1175                 if (err_str != NULL)
1176                         printf("%s\n<p>", err_str);
1177                 SAFE_FREE(err_str);
1178                 return NT_STATUS_IS_OK(ret);
1179         }
1180
1181         if(!initialize_password_db(True, NULL)) {
1182                 printf("%s\n<p>", _("Can't setup password database vectors."));
1183                 return False;
1184         }
1185
1186         ret = local_password_change(user_name, local_flags, new_passwd,
1187                                         &err_str, &msg_str);
1188
1189         if(msg_str)
1190                 printf("%s\n<p>", msg_str);
1191         if(err_str)
1192                 printf("%s\n<p>", err_str);
1193
1194         SAFE_FREE(msg_str);
1195         SAFE_FREE(err_str);
1196         return NT_STATUS_IS_OK(ret);
1197 }
1198
1199 /****************************************************************************
1200   do the stuff required to add or change a password 
1201 ****************************************************************************/
1202 static void chg_passwd(void)
1203 {
1204         const char *host;
1205         bool rslt;
1206         int local_flags = 0;
1207
1208         /* Make sure users name has been specified */
1209         if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1210                 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1211                 return;
1212         }
1213
1214         /*
1215          * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1216          * so if that's what we're doing, skip the rest of the checks
1217          */
1218         if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1219
1220                 /*
1221                  * If current user is not root, make sure old password has been specified 
1222                  * If REMOTE change, even root must provide old password 
1223                  */
1224                 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1225                     ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1226                         printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1227                         return;
1228                 }
1229
1230                 /* If changing a users password on a remote hosts we have to know what host */
1231                 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1232                         printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1233                         return;
1234                 }
1235
1236                 /* Make sure new passwords have been specified */
1237                 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1238                     (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1239                         printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1240                         return;
1241                 }
1242
1243                 /* Make sure new passwords was typed correctly twice */
1244                 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1245                         printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1246                         return;
1247                 }
1248         }
1249
1250         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1251                 host = cgi_variable(RHOST);
1252         } else if (am_root()) {
1253                 host = NULL;
1254         } else {
1255                 host = "127.0.0.1";
1256         }
1257
1258         /*
1259          * Set up the local flags.
1260          */
1261
1262         local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1263         local_flags |= (cgi_variable(ADD_USER_FLAG) ?  LOCAL_SET_PASSWORD : 0);
1264         local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1265         local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1266         local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1267         local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1268
1269         rslt = change_password(host,
1270                                cgi_variable_nonull(SWAT_USER),
1271                                cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1272                                    local_flags);
1273
1274         if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1275                 printf("<p>");
1276                 if (rslt == True) {
1277                         printf("%s\n", _(" The passwd has been changed."));
1278                 } else {
1279                         printf("%s\n", _(" The passwd has NOT been changed."));
1280                 }
1281         }
1282
1283         return;
1284 }
1285
1286 /****************************************************************************
1287   display a password editing page  
1288 ****************************************************************************/
1289 static void passwd_page(void)
1290 {
1291         const char *new_name = cgi_user_name();
1292         const char passwd_form[] = "passwd";
1293         const char rpasswd_form[] = "rpasswd";
1294
1295         if (!new_name) new_name = "";
1296
1297         printf("<H2>%s</H2>\n", _("Server Password Management"));
1298
1299         printf("<FORM name=\"swatform\" method=post>\n");
1300         print_xsrf_token(cgi_user_name(), cgi_user_pass(), passwd_form);
1301
1302         printf("<table>\n");
1303
1304         /* 
1305          * Create all the dialog boxes for data collection
1306          */
1307         printf("<tr><td> %s : </td>\n", _("User Name"));
1308         printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1309         if (!am_root()) {
1310                 printf("<tr><td> %s : </td>\n", _("Old Password"));
1311                 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1312         }
1313         printf("<tr><td> %s : </td>\n", _("New Password"));
1314         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1315         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1316         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1317         printf("</table>\n");
1318
1319         /*
1320          * Create all the control buttons for requesting action
1321          */
1322         printf("<input type=submit name=%s value=\"%s\">\n", 
1323                CHG_S_PASSWD_FLAG, _("Change Password"));
1324         if (demo_mode || am_root()) {
1325                 printf("<input type=submit name=%s value=\"%s\">\n",
1326                        ADD_USER_FLAG, _("Add New User"));
1327                 printf("<input type=submit name=%s value=\"%s\">\n",
1328                        DELETE_USER_FLAG, _("Delete User"));
1329                 printf("<input type=submit name=%s value=\"%s\">\n", 
1330                        DISABLE_USER_FLAG, _("Disable User"));
1331                 printf("<input type=submit name=%s value=\"%s\">\n", 
1332                        ENABLE_USER_FLAG, _("Enable User"));
1333         }
1334         printf("<p></FORM>\n");
1335
1336         /*
1337          * Do some work if change, add, disable or enable was
1338          * requested. It could be this is the first time through this
1339          * code, so there isn't anything to do.  */
1340         if (verify_xsrf_token(passwd_form) &&
1341            ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1342             (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG)))) {
1343                 chg_passwd();           
1344         }
1345
1346         printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1347
1348         printf("<FORM name=\"swatform\" method=post>\n");
1349         print_xsrf_token(cgi_user_name(), cgi_user_pass(), rpasswd_form);
1350
1351         printf("<table>\n");
1352
1353         /* 
1354          * Create all the dialog boxes for data collection
1355          */
1356         printf("<tr><td> %s : </td>\n", _("User Name"));
1357         printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1358         printf("<tr><td> %s : </td>\n", _("Old Password"));
1359         printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1360         printf("<tr><td> %s : </td>\n", _("New Password"));
1361         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1362         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1363         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1364         printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1365         printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1366
1367         printf("</table>");
1368
1369         /*
1370          * Create all the control buttons for requesting action
1371          */
1372         printf("<input type=submit name=%s value=\"%s\">", 
1373                CHG_R_PASSWD_FLAG, _("Change Password"));
1374
1375         printf("<p></FORM>\n");
1376
1377         /*
1378          * Do some work if a request has been made to change the
1379          * password somewhere other than the server. It could be this
1380          * is the first time through this code, so there isn't
1381          * anything to do.  */
1382         if (verify_xsrf_token(passwd_form) && cgi_variable(CHG_R_PASSWD_FLAG)) {
1383                 chg_passwd();           
1384         }
1385
1386 }
1387
1388 /****************************************************************************
1389   display a printers editing page  
1390 ****************************************************************************/
1391 static void printers_page(void)
1392 {
1393         const char *share = cgi_variable("share");
1394         char *s;
1395         int snum=-1;
1396         int i;
1397         int mode = 0;
1398         unsigned int parm_filter = FLAG_BASIC;
1399         const char form_name[] = "printers";
1400
1401         if (!verify_xsrf_token(form_name)) {
1402                 goto output_page;
1403         }
1404
1405         if (share)
1406                 snum = lp_servicenumber(share);
1407
1408         if (cgi_variable("Commit") && snum >= 0) {
1409                 commit_parameters(snum);
1410                 if (snum >= iNumNonAutoPrintServices)
1411                     save_reload(snum);
1412                 else
1413                     save_reload(-1);
1414                 snum = lp_servicenumber(share);
1415         }
1416
1417         if (cgi_variable("Delete") && snum >= 0) {
1418                 lp_remove_service(snum);
1419                 save_reload(-1);
1420                 share = NULL;
1421                 snum = -1;
1422         }
1423
1424         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1425                 snum = lp_servicenumber(share);
1426                 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1427                         load_config(False);
1428                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1429                         snum = lp_servicenumber(share);
1430                         lp_do_parameter(snum, "print ok", "Yes");
1431                         save_reload(snum);
1432                         snum = lp_servicenumber(share);
1433                 }
1434         }
1435
1436         if ( cgi_variable("ViewMode") )
1437                 mode = atoi(cgi_variable_nonull("ViewMode"));
1438         if ( cgi_variable("BasicMode"))
1439                 mode = 0;
1440         if ( cgi_variable("AdvMode"))
1441                 mode = 1;
1442
1443 output_page:
1444         printf("<H2>%s</H2>\n", _("Printer Parameters"));
1445
1446         printf("<H3>%s</H3>\n", _("Important Note:"));
1447         printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1448         printf("%s",_("are autoloaded printers from "));
1449         printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1450         printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1451
1452
1453         printf("<FORM name=\"swatform\" method=post>\n");
1454         print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
1455
1456         ViewModeBoxes( mode );
1457         switch ( mode ) {
1458                 case 0:
1459                         parm_filter = FLAG_BASIC;
1460                         break;
1461                 case 1:
1462                         parm_filter = FLAG_ADVANCED;
1463                         break;
1464         }
1465         printf("<table>\n");
1466         printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1467         printf("<td><select name=\"share\">\n");
1468         if (snum < 0 || !lp_print_ok(snum))
1469                 printf("<option value=\" \"> \n");
1470         for (i=0;i<lp_numservices();i++) {
1471                 s = lp_servicename(i);
1472                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1473                     if (i >= iNumNonAutoPrintServices)
1474                         printf("<option %s value=\"%s\">[*]%s\n",
1475                                (share && strcmp(share,s)==0)?"SELECTED":"",
1476                                s, s);
1477                     else
1478                         printf("<option %s value=\"%s\">%s\n", 
1479                                (share && strcmp(share,s)==0)?"SELECTED":"",
1480                                s, s);
1481                 }
1482         }
1483         printf("</select></td>");
1484         if (have_write_access) {
1485                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1486         }
1487         printf("</tr>");
1488         printf("</table>\n");
1489
1490         if (have_write_access) {
1491                 printf("<table>\n");
1492                 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1493                 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1494                 printf("</table>");
1495         }
1496
1497
1498         if (snum >= 0) {
1499                 if (have_write_access) {
1500                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1501                 }
1502                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1503                 printf("<p>\n");
1504         }
1505
1506         if (snum >= 0) {
1507                 printf("<table>\n");
1508                 show_parameters(snum, 1, parm_filter, 1);
1509                 printf("</table>\n");
1510         }
1511         printf("</FORM>\n");
1512 }
1513
1514 /*
1515   when the _() translation macro is used there is no obvious place to free
1516   the resulting string and there is no easy way to give a static pointer.
1517   All we can do is rotate between some static buffers and hope a single d_printf()
1518   doesn't have more calls to _() than the number of buffers
1519 */
1520
1521 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1522 {
1523         const char *msgstr;
1524         const char *ret;
1525
1526         msgstr = lang_msg(msgid);
1527         if (!msgstr) {
1528                 return msgid;
1529         }
1530
1531         ret = talloc_strdup(ctx, msgstr);
1532
1533         lang_msg_free(msgstr);
1534         if (!ret) {
1535                 return msgid;
1536         }
1537
1538         return ret;
1539 }
1540
1541 /**
1542  * main function for SWAT.
1543  **/
1544  int main(int argc, char *argv[])
1545 {
1546         const char *page;
1547         poptContext pc;
1548         struct poptOption long_options[] = {
1549                 POPT_AUTOHELP
1550                 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1551                 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" }, 
1552                 POPT_COMMON_SAMBA
1553                 POPT_TABLEEND
1554         };
1555         TALLOC_CTX *frame = talloc_stackframe();
1556
1557         fault_setup();
1558         umask(S_IWGRP | S_IWOTH);
1559
1560 #if defined(HAVE_SET_AUTH_PARAMETERS)
1561         set_auth_parameters(argc, argv);
1562 #endif /* HAVE_SET_AUTH_PARAMETERS */
1563
1564         /* just in case it goes wild ... */
1565         alarm(300);
1566
1567         setlinebuf(stdout);
1568
1569         /* we don't want any SIGPIPE messages */
1570         BlockSignals(True,SIGPIPE);
1571
1572         debug_set_logfile("/dev/null");
1573
1574         /* we don't want stderr screwing us up */
1575         close(2);
1576         open("/dev/null", O_WRONLY);
1577         setup_logging("swat", DEBUG_FILE);
1578
1579         load_case_tables();
1580         
1581         pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1582
1583         /* Parse command line options */
1584
1585         while(poptGetNextOpt(pc) != -1) { }
1586
1587         poptFreeContext(pc);
1588
1589         /* This should set a more apporiate log file */
1590         load_config(True);
1591         reopen_logs();
1592         load_interfaces();
1593         iNumNonAutoPrintServices = lp_numservices();
1594         if (pcap_cache_loaded()) {
1595                 struct tevent_context *ev_ctx;
1596                 struct messaging_context *msg_ctx;
1597
1598                 ev_ctx = s3_tevent_context_init(NULL);
1599                 if (ev_ctx == NULL) {
1600                         printf("s3_tevent_context_init() failed\n");
1601                         return 0;
1602                 }
1603                 msg_ctx = messaging_init(ev_ctx, ev_ctx);
1604                 if (msg_ctx == NULL) {
1605                         printf("messaging_init() failed\n");
1606                         return 0;
1607                 }
1608
1609                 load_printers(ev_ctx, msg_ctx);
1610
1611                 talloc_free(ev_ctx);
1612         }
1613
1614         cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1615
1616         print_header();
1617
1618         cgi_load_variables();
1619
1620         if (!file_exist(get_dyn_CONFIGFILE())) {
1621                 have_read_access = True;
1622                 have_write_access = True;
1623         } else {
1624                 /* check if the authenticated user has write access - if not then
1625                    don't show write options */
1626                 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1627
1628                 /* if the user doesn't have read access to smb.conf then
1629                    don't let them view it */
1630                 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1631         }
1632
1633         show_main_buttons();
1634
1635         page = cgi_pathinfo();
1636
1637         /* Root gets full functionality */
1638         if (have_read_access && strcmp(page, "globals")==0) {
1639                 globals_page();
1640         } else if (have_read_access && strcmp(page,"shares")==0) {
1641                 shares_page();
1642         } else if (have_read_access && strcmp(page,"printers")==0) {
1643                 printers_page();
1644         } else if (have_read_access && strcmp(page,"status")==0) {
1645                 status_page();
1646         } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1647                 viewconfig_page();
1648         } else if (strcmp(page,"passwd")==0) {
1649                 passwd_page();
1650         } else if (have_read_access && strcmp(page,"wizard")==0) {
1651                 wizard_page();
1652         } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1653                 wizard_params_page();
1654         } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1655                 rewritecfg_file();
1656         } else {
1657                 welcome_page();
1658         }
1659
1660         print_footer();
1661
1662         TALLOC_FREE(frame);
1663         return 0;
1664 }
1665
1666 /** @} **/