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