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