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