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