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