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