430c76ed6ad0b1ac51f393d2f1aa40e16b13cfc2
[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
702         /* Here we first set and commit all the parameters that were selected
703            in the previous screen. */
704
705         printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
706
707         if (cgi_variable("Commit")) {
708                 commit_parameters(GLOBAL_SECTION_SNUM);
709                 save_reload(0);
710         }
711
712         printf("<form name=\"swatform\" method=post action=wizard_params>\n");
713
714         if (have_write_access) {
715                 printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
716         }
717
718         printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
719         printf("<p>\n");
720         
721         printf("<table>\n");
722         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
723         printf("</table>\n");
724         printf("</form>\n");
725 }
726
727 /****************************************************************************
728   Utility to just rewrite the smb.conf file - effectively just cleans it up
729 ****************************************************************************/
730 static void rewritecfg_file(void)
731 {
732         commit_parameters(GLOBAL_SECTION_SNUM);
733         save_reload(0);
734         printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
735 }
736
737 /****************************************************************************
738   wizard to create/modify the smb.conf file
739 ****************************************************************************/
740 static void wizard_page(void)
741 {
742         /* Set some variables to collect data from smb.conf */
743         int role = 0;
744         int winstype = 0;
745         int have_home = -1;
746         int HomeExpo = 0;
747         int SerType = 0;
748
749         if (cgi_variable("Rewrite")) {
750                 (void) rewritecfg_file();
751                 return;
752         }
753
754         if (cgi_variable("GetWizardParams")){
755                 (void) wizard_params_page();
756                 return;
757         }
758
759         if (cgi_variable("Commit")){
760                 SerType = atoi(cgi_variable_nonull("ServerType"));
761                 winstype = atoi(cgi_variable_nonull("WINSType"));
762                 have_home = lp_servicenumber(HOMES_NAME);
763                 HomeExpo = atoi(cgi_variable_nonull("HomeExpo"));
764
765                 /* Plain text passwords are too badly broken - use encrypted passwords only */
766                 lp_do_parameter( GLOBAL_SECTION_SNUM, "encrypt passwords", "Yes");
767                 
768                 switch ( SerType ){
769                         case 0:
770                                 /* Stand-alone Server */
771                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
772                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
773                                 break;
774                         case 1:
775                                 /* Domain Member */
776                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" );
777                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" );
778                                 break;
779                         case 2:
780                                 /* Domain Controller */
781                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" );
782                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" );
783                                 break;
784                 }
785                 switch ( winstype ) {
786                         case 0:
787                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
788                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
789                                 break;
790                         case 1:
791                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" );
792                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" );
793                                 break;
794                         case 2:
795                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" );
796                                 lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable_nonull("WINSAddr"));
797                                 break;
798                 }
799
800                 /* Have to create Homes share? */
801                 if ((HomeExpo == 1) && (have_home == -1)) {
802                         const char *unix_share = HOMES_NAME;
803
804                         load_config(False);
805                         lp_copy_service(GLOBAL_SECTION_SNUM, unix_share);
806                         have_home = lp_servicenumber(HOMES_NAME);
807                         lp_do_parameter( have_home, "read only", "No");
808                         lp_do_parameter( have_home, "valid users", "%S");
809                         lp_do_parameter( have_home, "browseable", "No");
810                         commit_parameters(have_home);
811                         save_reload(have_home);
812                 }
813
814                 /* Need to Delete Homes share? */
815                 if ((HomeExpo == 0) && (have_home != -1)) {
816                         lp_remove_service(have_home);
817                         have_home = -1;
818                 }
819
820                 commit_parameters(GLOBAL_SECTION_SNUM);
821                 save_reload(0);
822         }
823         else
824         {
825                 /* Now determine smb.conf WINS settings */
826                 if (lp_wins_support())
827                         winstype = 1;
828                 if (lp_wins_server_list() && strlen(*lp_wins_server_list()))
829                         winstype = 2;
830
831                 /* Do we have a homes share? */
832                 have_home = lp_servicenumber(HOMES_NAME);
833         }
834         if ((winstype == 2) && lp_wins_support())
835                 winstype = 3;
836
837         role = lp_server_role();
838         
839         /* Here we go ... */
840         printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
841         printf("<form method=post action=wizard>\n");
842
843         if (have_write_access) {
844                 printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
845                 printf("%s", _("The same will happen if you press the commit button."));
846                 printf("<br><br>\n");
847                 printf("<center>");
848                 printf("<input type=submit name=\"Rewrite\" value=\"%s\"> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
849                 printf("<input type=submit name=\"Commit\" value=\"%s\"> &nbsp;&nbsp;",_("Commit"));
850                 printf("<input type=submit name=\"GetWizardParams\" value=\"%s\">", _("Edit Parameter Values"));
851                 printf("</center>\n");
852         }
853
854         printf("<hr>");
855         printf("<center><table border=0>");
856         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Server Type"));
857         printf("<td><input type=radio name=\"ServerType\" value=\"0\" %s> %s&nbsp;</td>", ((role == ROLE_STANDALONE) ? "checked" : ""), _("Stand Alone"));
858         printf("<td><input type=radio name=\"ServerType\" value=\"1\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_MEMBER) ? "checked" : ""), _("Domain Member")); 
859         printf("<td><input type=radio name=\"ServerType\" value=\"2\" %s> %s&nbsp;</td>", ((role == ROLE_DOMAIN_PDC) ? "checked" : ""), _("Domain Controller"));
860         printf("</tr>\n");
861         if (role == ROLE_DOMAIN_BDC) {
862                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Unusual Type in smb.conf - Please Select New Mode"));
863         }
864         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Configure WINS As"));
865         printf("<td><input type=radio name=\"WINSType\" value=\"0\" %s> %s&nbsp;</td>", ((winstype == 0) ? "checked" : ""), _("Not Used"));
866         printf("<td><input type=radio name=\"WINSType\" value=\"1\" %s> %s&nbsp;</td>", ((winstype == 1) ? "checked" : ""), _("Server for client use"));
867         printf("<td><input type=radio name=\"WINSType\" value=\"2\" %s> %s&nbsp;</td>", ((winstype == 2) ? "checked" : ""), _("Client of another WINS server"));
868         printf("</tr>\n");
869         printf("<tr><td></td><td></td><td></td><td>%s&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"", _("Remote WINS Server"));
870
871         /* Print out the list of wins servers */
872         if(lp_wins_server_list()) {
873                 int i;
874                 const char **wins_servers = lp_wins_server_list();
875                 for(i = 0; wins_servers[i]; i++) printf("%s ", wins_servers[i]);
876         }
877         
878         printf("\"></td></tr>\n");
879         if (winstype == 3) {
880                 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"));
881                 printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">%s</font></td></tr>\n", _("Please Select desired WINS mode above."));
882         }
883         printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Expose Home Directories"));
884         printf("<td><input type=radio name=\"HomeExpo\" value=\"1\" %s> Yes</td>", (have_home == -1) ? "" : "checked ");
885         printf("<td><input type=radio name=\"HomeExpo\" value=\"0\" %s> No</td>", (have_home == -1 ) ? "checked" : "");
886         printf("<td></td></tr>\n");
887         
888         /* Enable this when we are ready ....
889          * printf("<tr><td><b>%s:&nbsp;</b></td>\n", _("Is Print Server"));
890          * printf("<td><input type=radio name=\"PtrSvr\" value=\"1\" %s> Yes</td>");
891          * printf("<td><input type=radio name=\"PtrSvr\" value=\"0\" %s> No</td>");
892          * printf("<td></td></tr>\n");
893          */
894         
895         printf("</table></center>");
896         printf("<hr>");
897
898         printf("%s\n", _("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment."));
899         printf("</form>\n");
900 }
901
902
903 /****************************************************************************
904   display a globals editing page  
905 ****************************************************************************/
906 static void globals_page(void)
907 {
908         unsigned int parm_filter = FLAG_BASIC;
909         int mode = 0;
910
911         printf("<H2>%s</H2>\n", _("Global Parameters"));
912
913         if (cgi_variable("Commit")) {
914                 commit_parameters(GLOBAL_SECTION_SNUM);
915                 save_reload(0);
916         }
917
918         if ( cgi_variable("ViewMode") )
919                 mode = atoi(cgi_variable_nonull("ViewMode"));
920         if ( cgi_variable("BasicMode"))
921                 mode = 0;
922         if ( cgi_variable("AdvMode"))
923                 mode = 1;
924
925         printf("<form name=\"swatform\" method=post action=globals>\n");
926
927         ViewModeBoxes( mode );
928         switch ( mode ) {
929                 case 0:
930                         parm_filter = FLAG_BASIC;
931                         break;
932                 case 1:
933                         parm_filter = FLAG_ADVANCED;
934                         break;
935         }
936         printf("<br>\n");
937         if (have_write_access) {
938                 printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
939                         _("Commit Changes"));
940         }
941
942         printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", 
943                  _("Reset Values"));
944
945         printf("<p>\n");
946         printf("<table>\n");
947         show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0);
948         printf("</table>\n");
949         printf("</form>\n");
950 }
951
952 /****************************************************************************
953   display a shares editing page. share is in unix codepage, 
954 ****************************************************************************/
955 static void shares_page(void)
956 {
957         const char *share = cgi_variable("share");
958         char *s;
959         char *utf8_s;
960         int snum = -1;
961         int i;
962         int mode = 0;
963         unsigned int parm_filter = FLAG_BASIC;
964         size_t converted_size;
965
966         if (share)
967                 snum = lp_servicenumber(share);
968
969         printf("<H2>%s</H2>\n", _("Share Parameters"));
970
971         if (cgi_variable("Commit") && snum >= 0) {
972                 commit_parameters(snum);
973                 save_reload(0);
974                 snum = lp_servicenumber(share);
975         }
976
977         if (cgi_variable("Delete") && snum >= 0) {
978                 lp_remove_service(snum);
979                 save_reload(0);
980                 share = NULL;
981                 snum = -1;
982         }
983
984         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
985                 snum = lp_servicenumber(share);
986                 if (snum < 0) {
987                         load_config(False);
988                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
989                         snum = lp_servicenumber(share);
990                         save_reload(snum);
991                         snum = lp_servicenumber(share);
992                 }
993         }
994
995         printf("<FORM name=\"swatform\" method=post>\n");
996
997         printf("<table>\n");
998
999         if ( cgi_variable("ViewMode") )
1000                 mode = atoi(cgi_variable_nonull("ViewMode"));
1001         if ( cgi_variable("BasicMode"))
1002                 mode = 0;
1003         if ( cgi_variable("AdvMode"))
1004                 mode = 1;
1005
1006         ViewModeBoxes( mode );
1007         switch ( mode ) {
1008                 case 0:
1009                         parm_filter = FLAG_BASIC;
1010                         break;
1011                 case 1:
1012                         parm_filter = FLAG_ADVANCED;
1013                         break;
1014         }
1015         printf("<br><tr>\n");
1016         printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
1017         printf("<td><select name=share>\n");
1018         if (snum < 0)
1019                 printf("<option value=\" \"> \n");
1020         for (i=0;i<lp_numservices();i++) {
1021                 s = lp_servicename(i);
1022                 if (s && (*s) && strcmp(s,"IPC$") && !lp_print_ok(i)) {
1023                         push_utf8_allocate(&utf8_s, s, &converted_size);
1024                         printf("<option %s value=\"%s\">%s\n", 
1025                                (share && strcmp(share,s)==0)?"SELECTED":"",
1026                                utf8_s, utf8_s);
1027                         SAFE_FREE(utf8_s);
1028                 }
1029         }
1030         printf("</select></td>\n");
1031         if (have_write_access) {
1032                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Share"));
1033         }
1034         printf("</tr>\n");
1035         printf("</table>");
1036         printf("<table>");
1037         if (have_write_access) {
1038                 printf("<tr>\n");
1039                 printf("<td><input type=submit name=createshare value=\"%s\"></td>\n", _("Create Share"));
1040                 printf("<td><input type=text size=30 name=newshare></td></tr>\n");
1041         }
1042         printf("</table>");
1043
1044
1045         if (snum >= 0) {
1046                 if (have_write_access) {
1047                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1048                 }
1049
1050                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1051                 printf("<p>\n");
1052         }
1053
1054         if (snum >= 0) {
1055                 printf("<table>\n");
1056                 show_parameters(snum, 1, parm_filter, 0);
1057                 printf("</table>\n");
1058         }
1059
1060         printf("</FORM>\n");
1061 }
1062
1063 /*************************************************************
1064 change a password either locally or remotely
1065 *************************************************************/
1066 static bool change_password(const char *remote_machine, const char *user_name, 
1067                             const char *old_passwd, const char *new_passwd, 
1068                                 int local_flags)
1069 {
1070         NTSTATUS ret;
1071         char *err_str = NULL;
1072         char *msg_str = NULL;
1073
1074         if (demo_mode) {
1075                 printf("%s\n<p>", _("password change in demo mode rejected"));
1076                 return False;
1077         }
1078         
1079         if (remote_machine != NULL) {
1080                 ret = remote_password_change(remote_machine, user_name,
1081                                              old_passwd, new_passwd, &err_str);
1082                 if (err_str != NULL)
1083                         printf("%s\n<p>", err_str);
1084                 SAFE_FREE(err_str);
1085                 return NT_STATUS_IS_OK(ret);
1086         }
1087
1088         if(!initialize_password_db(True, NULL)) {
1089                 printf("%s\n<p>", _("Can't setup password database vectors."));
1090                 return False;
1091         }
1092         
1093         ret = local_password_change(user_name, local_flags, new_passwd,
1094                                         &err_str, &msg_str);
1095
1096         if(msg_str)
1097                 printf("%s\n<p>", msg_str);
1098         if(err_str)
1099                 printf("%s\n<p>", err_str);
1100
1101         SAFE_FREE(msg_str);
1102         SAFE_FREE(err_str);
1103         return NT_STATUS_IS_OK(ret);
1104 }
1105
1106 /****************************************************************************
1107   do the stuff required to add or change a password 
1108 ****************************************************************************/
1109 static void chg_passwd(void)
1110 {
1111         const char *host;
1112         bool rslt;
1113         int local_flags = 0;
1114
1115         /* Make sure users name has been specified */
1116         if (strlen(cgi_variable_nonull(SWAT_USER)) == 0) {
1117                 printf("<p>%s\n", _(" Must specify \"User Name\" "));
1118                 return;
1119         }
1120
1121         /*
1122          * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
1123          * so if that's what we're doing, skip the rest of the checks
1124          */
1125         if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
1126
1127                 /*
1128                  * If current user is not root, make sure old password has been specified 
1129                  * If REMOTE change, even root must provide old password 
1130                  */
1131                 if (((!am_root()) && (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0)) ||
1132                     ((cgi_variable(CHG_R_PASSWD_FLAG)) &&  (strlen( cgi_variable_nonull(OLD_PSWD)) <= 0))) {
1133                         printf("<p>%s\n", _(" Must specify \"Old Password\" "));
1134                         return;
1135                 }
1136
1137                 /* If changing a users password on a remote hosts we have to know what host */
1138                 if ((cgi_variable(CHG_R_PASSWD_FLAG)) && (strlen( cgi_variable_nonull(RHOST)) <= 0)) {
1139                         printf("<p>%s\n", _(" Must specify \"Remote Machine\" "));
1140                         return;
1141                 }
1142
1143                 /* Make sure new passwords have been specified */
1144                 if ((strlen( cgi_variable_nonull(NEW_PSWD)) <= 0) ||
1145                     (strlen( cgi_variable_nonull(NEW2_PSWD)) <= 0)) {
1146                         printf("<p>%s\n", _(" Must specify \"New, and Re-typed Passwords\" "));
1147                         return;
1148                 }
1149
1150                 /* Make sure new passwords was typed correctly twice */
1151                 if (strcmp(cgi_variable_nonull(NEW_PSWD), cgi_variable_nonull(NEW2_PSWD)) != 0) {
1152                         printf("<p>%s\n", _(" Re-typed password didn't match new password "));
1153                         return;
1154                 }
1155         }
1156
1157         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1158                 host = cgi_variable(RHOST);
1159         } else if (am_root()) {
1160                 host = NULL;
1161         } else {
1162                 host = "127.0.0.1";
1163         }
1164
1165         /*
1166          * Set up the local flags.
1167          */
1168
1169         local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
1170         local_flags |= (cgi_variable(ADD_USER_FLAG) ?  LOCAL_SET_PASSWORD : 0);
1171         local_flags |= (cgi_variable(CHG_S_PASSWD_FLAG) ? LOCAL_SET_PASSWORD : 0);
1172         local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
1173         local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
1174         local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
1175         
1176
1177         rslt = change_password(host,
1178                                cgi_variable_nonull(SWAT_USER),
1179                                cgi_variable_nonull(OLD_PSWD), cgi_variable_nonull(NEW_PSWD),
1180                                    local_flags);
1181
1182         if(cgi_variable(CHG_S_PASSWD_FLAG)) {
1183                 printf("<p>");
1184                 if (rslt == True) {
1185                         printf("%s\n", _(" The passwd has been changed."));
1186                 } else {
1187                         printf("%s\n", _(" The passwd for has NOT been changed."));
1188                 }
1189         }
1190         
1191         return;
1192 }
1193
1194 /****************************************************************************
1195   display a password editing page  
1196 ****************************************************************************/
1197 static void passwd_page(void)
1198 {
1199         const char *new_name = cgi_user_name();
1200
1201         if (!new_name) new_name = "";
1202
1203         printf("<H2>%s</H2>\n", _("Server Password Management"));
1204
1205         printf("<FORM name=\"swatform\" method=post>\n");
1206
1207         printf("<table>\n");
1208
1209         /* 
1210          * Create all the dialog boxes for data collection
1211          */
1212         printf("<tr><td> %s : </td>\n", _("User Name"));
1213         printf("<td><input type=text size=30 name=%s value=%s></td></tr> \n", SWAT_USER, new_name);
1214         if (!am_root()) {
1215                 printf("<tr><td> %s : </td>\n", _("Old Password"));
1216                 printf("<td><input type=password size=30 name=%s></td></tr> \n",OLD_PSWD);
1217         }
1218         printf("<tr><td> %s : </td>\n", _("New Password"));
1219         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1220         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1221         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1222         printf("</table>\n");
1223
1224         /*
1225          * Create all the control buttons for requesting action
1226          */
1227         printf("<input type=submit name=%s value=\"%s\">\n", 
1228                CHG_S_PASSWD_FLAG, _("Change Password"));
1229         if (demo_mode || am_root()) {
1230                 printf("<input type=submit name=%s value=\"%s\">\n",
1231                        ADD_USER_FLAG, _("Add New User"));
1232                 printf("<input type=submit name=%s value=\"%s\">\n",
1233                        DELETE_USER_FLAG, _("Delete User"));
1234                 printf("<input type=submit name=%s value=\"%s\">\n", 
1235                        DISABLE_USER_FLAG, _("Disable User"));
1236                 printf("<input type=submit name=%s value=\"%s\">\n", 
1237                        ENABLE_USER_FLAG, _("Enable User"));
1238         }
1239         printf("<p></FORM>\n");
1240
1241         /*
1242          * Do some work if change, add, disable or enable was
1243          * requested. It could be this is the first time through this
1244          * code, so there isn't anything to do.  */
1245         if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
1246             (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
1247                 chg_passwd();           
1248         }
1249
1250         printf("<H2>%s</H2>\n", _("Client/Server Password Management"));
1251
1252         printf("<FORM name=\"swatform\" method=post>\n");
1253
1254         printf("<table>\n");
1255
1256         /* 
1257          * Create all the dialog boxes for data collection
1258          */
1259         printf("<tr><td> %s : </td>\n", _("User Name"));
1260         printf("<td><input type=text size=30 name=%s value=%s></td></tr>\n",SWAT_USER, new_name);
1261         printf("<tr><td> %s : </td>\n", _("Old Password"));
1262         printf("<td><input type=password size=30 name=%s></td></tr>\n",OLD_PSWD);
1263         printf("<tr><td> %s : </td>\n", _("New Password"));
1264         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW_PSWD);
1265         printf("<tr><td> %s : </td>\n", _("Re-type New Password"));
1266         printf("<td><input type=password size=30 name=%s></td></tr>\n",NEW2_PSWD);
1267         printf("<tr><td> %s : </td>\n", _("Remote Machine"));
1268         printf("<td><input type=text size=30 name=%s></td></tr>\n",RHOST);
1269
1270         printf("</table>");
1271
1272         /*
1273          * Create all the control buttons for requesting action
1274          */
1275         printf("<input type=submit name=%s value=\"%s\">", 
1276                CHG_R_PASSWD_FLAG, _("Change Password"));
1277
1278         printf("<p></FORM>\n");
1279
1280         /*
1281          * Do some work if a request has been made to change the
1282          * password somewhere other than the server. It could be this
1283          * is the first time through this code, so there isn't
1284          * anything to do.  */
1285         if (cgi_variable(CHG_R_PASSWD_FLAG)) {
1286                 chg_passwd();           
1287         }
1288
1289 }
1290
1291 /****************************************************************************
1292   display a printers editing page  
1293 ****************************************************************************/
1294 static void printers_page(void)
1295 {
1296         const char *share = cgi_variable("share");
1297         char *s;
1298         int snum=-1;
1299         int i;
1300         int mode = 0;
1301         unsigned int parm_filter = FLAG_BASIC;
1302
1303         if (share)
1304                 snum = lp_servicenumber(share);
1305
1306         printf("<H2>%s</H2>\n", _("Printer Parameters"));
1307  
1308         printf("<H3>%s</H3>\n", _("Important Note:"));
1309         printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
1310         printf("%s",_("are autoloaded printers from "));
1311         printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
1312         printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
1313
1314         if (cgi_variable("Commit") && snum >= 0) {
1315                 commit_parameters(snum);
1316                 if (snum >= iNumNonAutoPrintServices)
1317                     save_reload(snum);
1318                 else
1319                     save_reload(0);
1320                 snum = lp_servicenumber(share);
1321         }
1322
1323         if (cgi_variable("Delete") && snum >= 0) {
1324                 lp_remove_service(snum);
1325                 save_reload(0);
1326                 share = NULL;
1327                 snum = -1;
1328         }
1329
1330         if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) {
1331                 snum = lp_servicenumber(share);
1332                 if (snum < 0 || snum >= iNumNonAutoPrintServices) {
1333                         load_config(False);
1334                         lp_copy_service(GLOBAL_SECTION_SNUM, share);
1335                         snum = lp_servicenumber(share);
1336                         lp_do_parameter(snum, "print ok", "Yes");
1337                         save_reload(snum);
1338                         snum = lp_servicenumber(share);
1339                 }
1340         }
1341
1342         printf("<FORM name=\"swatform\" method=post>\n");
1343
1344         if ( cgi_variable("ViewMode") )
1345                 mode = atoi(cgi_variable_nonull("ViewMode"));
1346         if ( cgi_variable("BasicMode"))
1347                 mode = 0;
1348         if ( cgi_variable("AdvMode"))
1349                 mode = 1;
1350
1351         ViewModeBoxes( mode );
1352         switch ( mode ) {
1353                 case 0:
1354                         parm_filter = FLAG_BASIC;
1355                         break;
1356                 case 1:
1357                         parm_filter = FLAG_ADVANCED;
1358                         break;
1359         }
1360         printf("<table>\n");
1361         printf("<tr><td><input type=submit name=\"selectshare\" value=\"%s\"></td>\n", _("Choose Printer"));
1362         printf("<td><select name=\"share\">\n");
1363         if (snum < 0 || !lp_print_ok(snum))
1364                 printf("<option value=\" \"> \n");
1365         for (i=0;i<lp_numservices();i++) {
1366                 s = lp_servicename(i);
1367                 if (s && (*s) && strcmp(s,"IPC$") && lp_print_ok(i)) {
1368                     if (i >= iNumNonAutoPrintServices)
1369                         printf("<option %s value=\"%s\">[*]%s\n",
1370                                (share && strcmp(share,s)==0)?"SELECTED":"",
1371                                s, s);
1372                     else
1373                         printf("<option %s value=\"%s\">%s\n", 
1374                                (share && strcmp(share,s)==0)?"SELECTED":"",
1375                                s, s);
1376                 }
1377         }
1378         printf("</select></td>");
1379         if (have_write_access) {
1380                 printf("<td><input type=submit name=\"Delete\" value=\"%s\"></td>\n", _("Delete Printer"));
1381         }
1382         printf("</tr>");
1383         printf("</table>\n");
1384
1385         if (have_write_access) {
1386                 printf("<table>\n");
1387                 printf("<tr><td><input type=submit name=\"createshare\" value=\"%s\"></td>\n", _("Create Printer"));
1388                 printf("<td><input type=text size=30 name=\"newshare\"></td></tr>\n");
1389                 printf("</table>");
1390         }
1391
1392
1393         if (snum >= 0) {
1394                 if (have_write_access) {
1395                         printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
1396                 }
1397                 printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
1398                 printf("<p>\n");
1399         }
1400
1401         if (snum >= 0) {
1402                 printf("<table>\n");
1403                 show_parameters(snum, 1, parm_filter, 1);
1404                 printf("</table>\n");
1405         }
1406         printf("</FORM>\n");
1407 }
1408
1409 /*
1410   when the _() translation macro is used there is no obvious place to free
1411   the resulting string and there is no easy way to give a static pointer.
1412   All we can do is rotate between some static buffers and hope a single d_printf()
1413   doesn't have more calls to _() than the number of buffers
1414 */
1415
1416 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid)
1417 {
1418         const char *msgstr;
1419         const char *ret;
1420
1421         msgstr = lang_msg(msgid);
1422         if (!msgstr) {
1423                 return msgid;
1424         }
1425
1426         ret = talloc_strdup(ctx, msgstr);
1427
1428         lang_msg_free(msgstr);
1429         if (!ret) {
1430                 return msgid;
1431         }
1432
1433         return ret;
1434 }
1435
1436 /**
1437  * main function for SWAT.
1438  **/
1439  int main(int argc, char *argv[])
1440 {
1441         const char *page;
1442         poptContext pc;
1443         struct poptOption long_options[] = {
1444                 POPT_AUTOHELP
1445                 { "disable-authentication", 'a', POPT_ARG_VAL, &demo_mode, True, "Disable authentication (demo mode)" },
1446                 { "password-menu-only", 'P', POPT_ARG_VAL, &passwd_only, True, "Show only change password menu" }, 
1447                 POPT_COMMON_SAMBA
1448                 POPT_TABLEEND
1449         };
1450         TALLOC_CTX *frame = talloc_stackframe();
1451
1452         fault_setup(NULL);
1453         umask(S_IWGRP | S_IWOTH);
1454
1455 #if defined(HAVE_SET_AUTH_PARAMETERS)
1456         set_auth_parameters(argc, argv);
1457 #endif /* HAVE_SET_AUTH_PARAMETERS */
1458
1459         /* just in case it goes wild ... */
1460         alarm(300);
1461
1462         setlinebuf(stdout);
1463
1464         /* we don't want any SIGPIPE messages */
1465         BlockSignals(True,SIGPIPE);
1466
1467         dbf = x_fopen("/dev/null", O_WRONLY, 0);
1468         if (!dbf) dbf = x_stderr;
1469
1470         /* we don't want stderr screwing us up */
1471         close(2);
1472         open("/dev/null", O_WRONLY);
1473
1474         pc = poptGetContext("swat", argc, (const char **) argv, long_options, 0);
1475
1476         /* Parse command line options */
1477
1478         while(poptGetNextOpt(pc) != -1) { }
1479
1480         poptFreeContext(pc);
1481
1482         load_case_tables();
1483
1484         setup_logging(argv[0],False);
1485         load_config(True);
1486         load_interfaces();
1487         iNumNonAutoPrintServices = lp_numservices();
1488         load_printers();
1489
1490         cgi_setup(get_dyn_SWATDIR(), !demo_mode);
1491
1492         print_header();
1493
1494         cgi_load_variables();
1495
1496         if (!file_exist(get_dyn_CONFIGFILE())) {
1497                 have_read_access = True;
1498                 have_write_access = True;
1499         } else {
1500                 /* check if the authenticated user has write access - if not then
1501                    don't show write options */
1502                 have_write_access = (access(get_dyn_CONFIGFILE(),W_OK) == 0);
1503
1504                 /* if the user doesn't have read access to smb.conf then
1505                    don't let them view it */
1506                 have_read_access = (access(get_dyn_CONFIGFILE(),R_OK) == 0);
1507         }
1508
1509         show_main_buttons();
1510
1511         page = cgi_pathinfo();
1512
1513         /* Root gets full functionality */
1514         if (have_read_access && strcmp(page, "globals")==0) {
1515                 globals_page();
1516         } else if (have_read_access && strcmp(page,"shares")==0) {
1517                 shares_page();
1518         } else if (have_read_access && strcmp(page,"printers")==0) {
1519                 printers_page();
1520         } else if (have_read_access && strcmp(page,"status")==0) {
1521                 status_page();
1522         } else if (have_read_access && strcmp(page,"viewconfig")==0) {
1523                 viewconfig_page();
1524         } else if (strcmp(page,"passwd")==0) {
1525                 passwd_page();
1526         } else if (have_read_access && strcmp(page,"wizard")==0) {
1527                 wizard_page();
1528         } else if (have_read_access && strcmp(page,"wizard_params")==0) {
1529                 wizard_params_page();
1530         } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
1531                 rewritecfg_file();
1532         } else {
1533                 welcome_page();
1534         }
1535
1536         print_footer();
1537
1538         TALLOC_FREE(frame);
1539         return 0;
1540 }
1541
1542 /** @} **/