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