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