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