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