2
* Copyright (C) 1998-2001 Luca Deri <deri@ntop.org>
3
* Portions by Stefano Suin <stefano@ntop.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
#include "globals-report.h"
30
static void sendMenuFooter(int itm1Idx, int itm2Idx);
31
static void encodeWebFormURL(char *in, char *buf, int buflen);
32
static void decodeWebFormURL(char *buf);
33
static int readHTTPpostData(int len, char *buf, int buflen);
36
/* *******************************/
39
void showUsers(void) {
41
char buf[BUF_SIZE], ebuf[128];
42
datum key_data, return_data;
44
printHTMLheader("Registered ntop Users", HTML_FLAG_NO_REFRESH);
45
sendString("<P><HR><P>\n");
48
accessMutex(&gdbmMutex, "showUsers");
50
return_data = gdbm_firstkey(pwFile);
52
while (return_data.dptr != NULL) {
53
/* traceEvent(TRACE_INFO, "1) -> %s\n", return_data.dptr); */
54
key_data = return_data;
56
if(key_data.dptr[0] == '1') /* 1 = user */{
58
sendString("<CENTER>\n"
59
""TABLE_ON"<TABLE BORDER=1>\n");
60
sendString("<TR><TH "TH_BG">Users</TH><TH "TH_BG">Actions</TH></TR>\n");
63
if(strcmp(key_data.dptr, "1admin") == 0) {
64
if(snprintf(buf, BUF_SIZE, "<TR><TH "TH_BG" ALIGN=LEFT><IMG SRC=/user.gif>"
65
" %s</TH><TD "TD_BG"><A HREF=/modifyUser?%s>"
66
"<IMG ALT=\"Modify User\" SRC=/modifyUser.gif BORDER=0 align=absmiddle></A>"
67
" </TD></TR></TH></TR>\n", &key_data.dptr[1], key_data.dptr) < 0)
68
traceEvent(TRACE_ERROR, "Buffer overflow!");
70
encodeWebFormURL(key_data.dptr, ebuf, sizeof(ebuf));
71
if(snprintf(buf, BUF_SIZE, "<TR><TH "TH_BG" ALIGN=LEFT><IMG SRC=/user.gif>"
72
" %s</TH><TD "TD_BG"><A HREF=/modifyUser?%s>"
73
"<IMG ALT=\"Modify User\" SRC=/modifyUser.gif BORDER=0 align=absmiddle></A>"
74
" <A HREF=/deleteUser?%s><IMG ALT=\"Delete User\" SRC=/deleteUser.gif BORDER=0 align=absmiddle>"
75
"</A></TD></TR></TH></TR>\n", &key_data.dptr[1], ebuf, ebuf) < 0)
76
traceEvent(TRACE_ERROR, "Buffer overflow!");
82
return_data = gdbm_nextkey(pwFile, key_data);
87
releaseMutex(&gdbmMutex);
91
sendString("</TABLE>"TABLE_OFF"\n<P>\n");
92
sendString("</CENTER>\n");
97
/* *******************************/
99
void addUser(char* user) {
102
printHTMLheader("Manage ntop Users", HTML_FLAG_NO_REFRESH);
103
sendString("<P><HR><P>\n");
105
if((user != NULL) && ((strlen(user) < 2) || (user[0] != '1'))) {
106
printFlagedWarning("<I>The specified username is invalid.</I>");
108
sendString("<CENTER>\n");
109
sendString("<FORM METHOD=POST ACTION=/doAddUser>\n");
111
sendString("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=5>\n");
112
sendString("<TR>\n<TH ALIGN=right>User: </TH><TD ALIGN=left>");
114
decodeWebFormURL(user);
115
if(snprintf(tmpStr, sizeof(tmpStr),
116
"<INPUT TYPE=hidden NAME=user SIZE=20 VALUE=\"%s\"><B>%s</B>\n",
117
&user[1], &user[1]) < 0)
118
traceEvent(TRACE_ERROR, "Buffer overflow!");
121
sendString("<INPUT TYPE=text NAME=user SIZE=20>\n");
122
sendString("</TD>\n</TR>\n");
123
sendString("<TR>\n<TH ALIGN=right>Password: </TH>"
124
"<TD ALIGN=left><INPUT TYPE=password NAME=pw SIZE=20></TD></TR>\n");
125
sendString("</TABLE>\n");
127
if(snprintf(tmpStr, sizeof(tmpStr),
128
"<INPUT TYPE=submit VALUE=\"%s\"> <INPUT TYPE=reset>\n",
129
(user != NULL) ? "Modify User" : "Add User") < 0)
130
traceEvent(TRACE_ERROR, "Buffer overflow!");
133
sendString("</FORM>\n");
134
sendString("</CENTER>\n");
136
sendMenuFooter(0, 2);
139
/* *******************************/
141
void deleteUser(char* user) {
144
returnHTTPredirect("showUsers.html");
146
} else if((strlen(user) < 2) || (user[0] != '1')) {
147
sendHTTPHeader(HTTP_TYPE_HTML, 0);
148
printHTMLheader("Delete ntop User", HTML_FLAG_NO_REFRESH);
149
sendString("<P><HR><P>\n");
150
printFlagedWarning("<I>The specified username is invalid.</I>");
155
decodeWebFormURL(user);
156
key_data.dptr = user;
157
key_data.dsize = strlen(user)+1;
160
accessMutex(&gdbmMutex, "deleteUser");
162
rc = gdbm_delete(pwFile, key_data);
164
releaseMutex(&gdbmMutex);
168
sendHTTPHeader(HTTP_TYPE_HTML, 0);
169
printHTMLheader("Delete ntop User", HTML_FLAG_NO_REFRESH);
170
sendString("<P><HR><P>\n");
171
printFlagedWarning("<B>ERROR:</B> <I>unable to delete specified user.</I>");
173
returnHTTPredirect("showUsers.html");
178
sendMenuFooter(1, 2);
181
/* *******************************/
183
void doAddUser(int len) {
187
err = "ERROR: both user and password must be non empty fields.";
189
char postData[256], *key, *user=NULL, *pw=NULL;
190
int i, idx, badChar=0;
192
if((idx = readHTTPpostData(len, postData, sizeof(postData))) < 0)
193
return; /* FIXME (DL): an HTTP error code should be sent here */
195
for(i=0,key=postData; i<idx; i++) {
196
if(postData[i] == '&') {
198
key = &postData[i+1];
199
} else if((key != NULL) && (postData[i] == '=')) {
201
if(strcmp(key, "user") == 0)
202
user = &postData[i+1];
203
else if(strcmp(key, "pw") == 0)
209
decodeWebFormURL(user);
210
for(i=0; i<strlen(user); i++) {
211
if(!(isalpha(user[i]) || isdigit(user[i]))) {
218
decodeWebFormURL(pw);
221
printf("User='%s' - Pw='%s'\n", user?user:"(not given)", pw?pw:"(not given)");
225
if((user == NULL ) || (user[0] == '\0') || (pw == NULL) || (pw[0] == '\0')) {
226
err = "ERROR: both user and password must be non empty fields.";
228
err = "ERROR: the specified user name contains invalid characters.";
234
datum data_data, key_data;
236
if(snprintf(tmpBuf, sizeof(tmpBuf), "1%s", user) < 0)
237
traceEvent(TRACE_ERROR, "Buffer overflow!");
238
key_data.dptr = tmpBuf;
239
key_data.dsize = strlen(tmpBuf)+1;
243
strncpy(cpw, (char*)crypt(pw, (const char*)CRYPT_SALT), sizeof(cpw));
244
cpw[sizeof(cpw)-1] = '\0';
245
data_data.dptr = cpw;
247
data_data.dsize = strlen(data_data.dptr)+1;
249
traceEvent(TRACE_INFO, "User='%s' - Pw='%s [%s]'\n", user, pw, data_data.dptr);
253
accessMutex(&gdbmMutex, "doAddUser");
255
if(gdbm_store(pwFile, key_data, data_data, GDBM_REPLACE) != 0)
256
err = "FATAL ERROR: unable to add the new user.";
259
releaseMutex(&gdbmMutex);
265
sendHTTPHeader(HTTP_TYPE_HTML, 0);
266
printHTMLheader("ntop user add", HTML_FLAG_NO_REFRESH);
267
sendString("<P><HR><P>\n");
268
printFlagedWarning(err);
269
sendMenuFooter(1, 2);
272
returnHTTPredirect("showUsers.html");
276
/* ***********************************
277
*********************************** */
279
void showURLs(void) {
281
char buf[BUF_SIZE], ebuf[128];
282
datum key_data, return_data;
284
printHTMLheader("Restricted ntop URLs", HTML_FLAG_NO_REFRESH);
285
sendString("<P><HR><P>\n");
288
accessMutex(&gdbmMutex, "showURLs");
291
return_data = gdbm_firstkey(pwFile);
293
while (return_data.dptr != NULL) {
294
/* traceEvent(TRACE_INFO, "1) -> %s\n", return_data.dptr); */
295
key_data = return_data;
297
if(key_data.dptr[0] == '2') { /* 2 = URL */
299
sendString("<CENTER>\n"
300
""TABLE_ON"<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=5>\n");
301
sendString("<TR><TH "TH_BG">URLs</TH><TH "TH_BG">Actions</TH></TR>\n");
304
encodeWebFormURL(key_data.dptr, ebuf, sizeof(ebuf));
305
if(snprintf(buf, BUF_SIZE, "<TR><TH "TH_BG" ALIGN=LEFT><IMG SRC=/user.gif>"
306
" '%s*'</TH><TD "TD_BG"><A HREF=/modifyURL?%s>"
307
"<IMG ALT=\"Modify User\" SRC=/modifyUser.gif BORDER=0 align=absmiddle></A>"
308
" <A HREF=/deleteURL?%s><IMG ALT=\"Delete User\" SRC=/deleteUser.gif BORDER=0 align=absmiddle>"
309
"</A></TD></TR></TH></TR>\n", &key_data.dptr[1], ebuf, ebuf) < 0)
310
traceEvent(TRACE_ERROR, "Buffer overflow!");
315
return_data = gdbm_nextkey(pwFile, key_data);
320
releaseMutex(&gdbmMutex);
324
sendString("</TABLE>"TABLE_OFF"\n<P>\n");
325
sendString("</CENTER>\n");
327
sendMenuFooter(3, 0);
330
/* *******************************/
332
void addURL(char* url) {
334
datum key_data, return_data;
335
char *aubuf=NULL, *authorisedUser[20];
338
printHTMLheader("Manage ntop URLs", HTML_FLAG_NO_REFRESH);
339
sendString("<P><HR><P>\n");
341
if((url != NULL) && ((strlen(url) < 1) || (url[0] != '2'))) {
342
printFlagedWarning("<I>The specified URL is invalid.</I>");
345
sendString("<CENTER>\n");
346
sendString("<FORM METHOD=POST ACTION=/doAddURL>\n");
348
sendString("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3>\n");
350
sendString("<TR>\n<TH ALIGN=right VALIGN=top><B>URL</B>: </TH>");
352
sendString("<TR>\n<TH ALIGN=right VALIGN=middle><B>URL</B>: </TH>");
353
sendString("<TD ALIGN=left><TT>http://<"
354
"<I>ntop host</I>>:<<I>ntop port</I>>/</TT>");
356
decodeWebFormURL(url);
357
if(snprintf(tmpStr, sizeof(tmpStr),
358
"<INPUT TYPE=hidden NAME=url SIZE=20 VALUE=\"%s\">"
359
"<B>%s</B> <B>*</B> [Initial URL string]",
360
&url[1], &url[1]) < 0)
361
traceEvent(TRACE_ERROR, "Buffer overflow!");
364
sendString("<INPUT TYPE=text NAME=url SIZE=20> *");
366
sendString("</TD>\n</TR>\n");
367
sendString("<TR>\n<TH ALIGN=right VALIGN=top>Authorised Users: </TH>"
368
"<TD ALIGN=left><SELECT NAME=users MULTIPLE>\n");
371
accessMutex(&gdbmMutex, "addURL");
374
authorisedUser[0] = NULL;
377
key_data.dsize = strlen(url)+1;
378
return_data = gdbm_fetch(pwFile, key_data);
380
if(return_data.dptr != NULL) {
381
char *strtokState, *item;
383
aubuf = return_data.dptr; /* freed later (**) */
384
item = strtok_r(aubuf, "&", &strtokState);
385
for(i=0; (item != NULL) && (i < sizeof(authorisedUser)-1); i++) {
386
authorisedUser[i] = &item[sizeof("users=")-1];
387
item = strtok_r(NULL, "&", &strtokState);
390
traceEvent(TRACE_ERROR, "Too many users for URL='%s'\n", url);
392
authorisedUser[i] = NULL;
396
return_data = gdbm_firstkey(pwFile);
398
while (return_data.dptr != NULL) {
399
key_data = return_data;
401
if(key_data.dptr[0] == '1') { /* 1 = user */
404
for(i=0; authorisedUser[i] != NULL; i++) {
405
if(strcmp(authorisedUser[i], key_data.dptr) == 0)
408
if(snprintf(tmpStr, sizeof(tmpStr),
409
"<OPTION VALUE=%s %s>%s",
410
key_data.dptr, found ? "SELECTED" : "", &key_data.dptr[1]) < 0)
411
traceEvent(TRACE_ERROR, "Buffer overflow!");
415
return_data = gdbm_nextkey(pwFile, key_data);
420
free(aubuf); /* (**) */
423
releaseMutex(&gdbmMutex);
426
sendString("</SELECT>\n</TD></TR>\n");
427
sendString("</TABLE>\n");
430
sendString("<BLOCKQUOTE>\n<DIV ALIGN=left>\n"
431
"<B><U>NOTE</U>: if you leave the URL field empty then the "
432
"access is restricted to <I>all</I> ntop pages, otherwise, this "
433
"entry matches all the pages begining with the specified string.</B>\n"
434
"</DIV>\n</BLOCKQUOTE>\n");
436
if(snprintf(tmpStr, sizeof(tmpStr),
437
"<INPUT TYPE=submit VALUE=\"%s\"> <INPUT TYPE=reset>\n",
438
(url != NULL) ? "Modify URL" : "Add URL") < 0)
439
traceEvent(TRACE_ERROR, "Buffer overflow!");
442
sendString("</FORM>\n");
443
sendString("</CENTER>\n");
446
sendMenuFooter(0, 2);
449
/* *******************************/
451
void deleteURL(char* url) {
454
returnHTTPredirect("showURLs.html");
456
} else if((strlen(url) < 1) || (url[0] != '2')) {
457
sendHTTPHeader(HTTP_TYPE_HTML, 0);
458
printHTMLheader("Delete ntop URL", HTML_FLAG_NO_REFRESH);
459
sendString("<P><HR><P>\n");
460
printFlagedWarning("<I>The specified URL is invalid.</I>");
465
decodeWebFormURL(url);
467
key_data.dsize = strlen(url)+1;
470
accessMutex(&gdbmMutex, "deleteURL");
472
rc = gdbm_delete(pwFile, key_data);
474
releaseMutex(&gdbmMutex);
478
sendHTTPHeader(HTTP_TYPE_HTML, 0);
479
printHTMLheader("Delete ntop URL", HTML_FLAG_NO_REFRESH);
480
sendString("<P><HR><P>\n");
481
printFlagedWarning("<B>ERROR:</B> <I>unable to delete specified URL.</I>");
483
returnHTTPredirect("showURLs.html");
488
sendMenuFooter(3, 0);
492
/* *******************************/
494
void doAddURL(int len) {
496
char postData[256], *key, *url=NULL, *users=NULL, authorizedUsers[256];
497
int i, idx, alen=0, badChar=0;
501
courtesy of David Brown <david@caldera.com>
504
if((idx = readHTTPpostData(len, postData, sizeof(postData))) < 0)
505
return; /* FIXME (DL): an HTTP error code should be sent here */
507
memset(authorizedUsers, 0, sizeof(authorizedUsers));
508
for(i=0,key=postData; i<=idx; i++) {
509
if((i==idx) || (postData[i] == '&')) {
511
decodeWebFormURL(users);
512
if(snprintf(&authorizedUsers[alen], sizeof(authorizedUsers)-alen,
513
"%susers=%s", (alen>0) ? "&" : "", users) < 0)
514
traceEvent(TRACE_ERROR, "Buffer overflow!");
515
alen = strlen(authorizedUsers);
520
key = &postData[i+1];
521
} else if((key != NULL) && (postData[i] == '=')) {
523
if(strcmp(key, "url") == 0) {
524
url = &postData[i+1];
525
} else if(strcmp(key, "users") == 0) {
526
users = &postData[i+1];
532
decodeWebFormURL(url);
533
for(i=0; i<strlen(url); i++) {
534
if(!(isalpha(url[i]) || isdigit(url[i]) || (strchr("/-_?", url[i]) != NULL))) {
542
printf("URL: '%s' - users: '%s'\n", url?url:"(not given)", strlen(authorizedUsers)>0?authorizedUsers:"(not given)");
546
if(authorizedUsers[0] == '\0') {
547
err = "ERROR: user must be a non empty field.";
549
err = "ERROR: the specified URL contains invalid characters.";
552
datum data_data, key_data;
554
if(snprintf(tmpBuf, sizeof(tmpBuf), "2%s", url) < 0)
555
traceEvent(TRACE_ERROR, "Buffer overflow!");
556
key_data.dptr = tmpBuf;
557
key_data.dsize = strlen(tmpBuf)+1;
558
data_data.dptr = authorizedUsers;
559
data_data.dsize = strlen(authorizedUsers)+1;
562
accessMutex(&gdbmMutex, "doAddURL");
564
if(gdbm_store(pwFile, key_data, data_data, GDBM_REPLACE) != 0)
565
err = "FATAL ERROR: unable to add the new URL.";
567
releaseMutex(&gdbmMutex);
571
releaseMutex(&gdbmMutex);
575
sendHTTPHeader(HTTP_TYPE_HTML, 0);
576
printHTMLheader("ntop URL add", HTML_FLAG_NO_REFRESH);
577
sendString("<P><HR><P>\n");
578
printFlagedWarning(err);
579
sendMenuFooter(3, 0);
582
returnHTTPredirect("showURLs.html");
586
/* *******************************/
588
/* Courtesy of Michael Weidel <michael.weidel@gmx.de> */
590
int doChangeFilter(int len) {
592
struct bpf_program fcode;
593
char *currentFilterExpressionSav;
594
char buf[BUF_SIZE],postData[256],*key,*err=NULL;
596
currentFilterExpressionSav=strdup(currentFilterExpression); /* Backup */
598
if((idx = readHTTPpostData(len, postData, sizeof(postData))) < 0)
601
for(i=0,key=postData; i<=idx; i++) {
602
if(postData[i] == '&') {
604
key = &postData[i+1];
605
} else if((key != NULL) && (postData[i] == '=')) {
607
if(strcmp(key, "filter") == 0) {
608
currentFilterExpression = strdup(&postData[i+1]);
614
decodeWebFormURL(currentFilterExpression);
615
for(i=0; i<strlen(currentFilterExpression); i++) {
616
if(!(isalpha(currentFilterExpression[i]) ||
617
isdigit(currentFilterExpression[i]) ||
618
(strchr("/-+*_.!&|><=\\\":[]() ", currentFilterExpression[i]) != NULL))) {
619
badChar = 1; /* Perhaps we don't have to use this check? */
623
} else err = "ERROR: The HTTP Post Data was invalid.";
625
err = "ERROR: the specified filter expression contains invalid characters.";
627
traceEvent(TRACE_INFO, "Changing the kernel (libpcap) filter...");
630
accessMutex(&gdbmMutex, "changeFilter");
633
for(i=0; i<numDevices; i++) {
634
if((!device[i].virtualDevice)&&(err==NULL)) {
635
if((pcap_compile(device[i].pcapPtr, &fcode, currentFilterExpression, 1,
636
device[i].netmask.s_addr) < 0)
637
|| (pcap_setfilter(device[i].pcapPtr, &fcode) < 0)) {
638
traceEvent(TRACE_ERROR,
639
"ERROR: wrong filter '%s' (%s) on interface %s.\nUsing old filter.\n",
640
currentFilterExpression, pcap_geterr(device[i].pcapPtr), device[i].name);
641
err="The syntax of the defined filter is wrong.";
643
if(*currentFilterExpression!='\0'){
644
traceEvent(TRACE_INFO, "Set filter \"%s\" on device %s.",
645
currentFilterExpression, device[i].name);
647
traceEvent(TRACE_INFO, "Set no kernel (libpcap) filtering on device %s.",
655
releaseMutex(&gdbmMutex);
658
sendHTTPHeader(HTTP_TYPE_HTML, 0);
660
if(filterExpressionInExtraFrame) {
661
sendString("<HTML>\n<HEAD>\n");
662
sendString("<LINK REL=stylesheet HREF=/style.css type=\"text/css\">\n");
663
sendString("<SCRIPT TYPE=\"text/javascript\">\n");
664
sendString("<!--\nfunction UpdateFrame(URI,F) {\n");
665
sendString(" Frame=eval(\"parent.\"+F);\n");
666
sendString(" Frame.location.href = URI;\n");
667
sendString("}\n//-->\n</SCRIPT>");
668
sendString("</HEAD>\n");
669
sendString("<BODY ONLOAD=\"UpdateFrame('"FILTER_INFO_HTML"','filterinfo')\" ");
670
sendString("BACKGROUND=/white_bg.gif BGCOLOR=\"#FFFFFF\" LINK=blue VLINK=blue>\n");
671
printSectionTitle("Change kernel (libpcap) filter expression");
673
printHTMLheader("changing kernel (libpcap) filter expression", HTML_FLAG_NO_REFRESH);
674
sendString("<P><HR></P>\n<P><CENTER>");
677
sendString("<FONT FACE=\"Helvetica, Arial, Sans Serif\">\n");
680
if(*currentFilterExpression != '\0'){
681
if(snprintf(buf, sizeof(buf),
682
"<B>Filter changed to <I>%s</I>.</B></FONT>\n",
683
currentFilterExpression) < 0)
684
traceEvent(TRACE_ERROR, "Buffer overflow!");
686
} else sendString("<B>Kernel (libpcap) filtering disabled.</B></FONT>\n");
688
if(filterExpressionInExtraFrame) {
689
sendString("<NOSCRIPT>\n<P>You've got JavaScript disabled. Therefore ");
690
sendString("your extra frame with the filter expression isn't updated ");
691
sendString("automatically. No problem, you can update it here ");
692
sendString("<A HREF=\""FILTER_INFO_HTML"\" target=\"filterinfo\">");
693
sendString("manually</A>.</NOSCRIPT></P>");
694
sendString("</BODY>\n</HTML>\n");
696
sendString("</CENTER></P>\n");
697
/* sendString("<P><CENTER>The statistics are also reset.</CENTER></P>\n"); */
701
if(currentFilterExpressionSav!=NULL) free(currentFilterExpressionSav);
702
return 0; /* -> Statistics are reset (if uncommented) */
704
if(currentFilterExpression!=NULL) free(currentFilterExpression);
705
currentFilterExpression=currentFilterExpressionSav;
706
for(i=0; i<numDevices; i++) { /* restore old filter expression */
707
if((!device[i].virtualDevice)&&(err==NULL)) {
708
if((pcap_compile(device[i].pcapPtr, &fcode, currentFilterExpression, 1,
709
device[i].netmask.s_addr) < 0)
710
|| (pcap_setfilter(device[i].pcapPtr, &fcode) < 0)) {
711
traceEvent(TRACE_ERROR,
712
"ERROR: wrong filter '%s' (%s) on interface %s.\nUsing old filter.\n",
713
currentFilterExpression, pcap_geterr(device[i].pcapPtr), device[i].name);
718
printFlagedWarning(err);
719
if(filterExpressionInExtraFrame) sendString("</BODY>\n</HTML>\n");
720
else printHTMLtrailer();
725
/* ******************************* */
727
/* Courtesy of Michael Weidel <michael.weidel@gmx.de> */
729
void changeFilter(void) {
732
printHTMLheader("Change kernel (libpcap) filter expression", HTML_FLAG_NO_REFRESH);
733
sendString("<BR><HR><P>\n");
734
sendString("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=5>\n<TR>\n");
735
sendString("<TH "TH_BG" ALIGN=center>Old Filter Expression: </TH><TD ALIGN=left>");
736
if(snprintf(buf, sizeof(buf), "<B>%s",
737
currentFilterExpression) < 0)
738
traceEvent(TRACE_ERROR, "Buffer overflow!");
740
if(*currentFilterExpression=='\0') sendString("<No filter defined>");
741
sendString("</B><BR>\n</TD>\n</TR>\n");
743
sendString("<FORM METHOD=POST ACTION=/doChangeFilter>\n");
744
sendString("<TR>\n<TH "TH_BG" ALIGN=center>New Filter Expression: </TH>");
745
sendString("<TD ALIGN=left><INPUT TYPE=text NAME=filter SIZE=40>\n");
746
sendString("</TD>\n</TR>\n</TABLE>\n<CENTER>");
747
sendString("<INPUT TYPE=submit VALUE=\"Change Filter\"> ");
748
sendString("<INPUT TYPE=reset></FORM>");
750
sendString("</CENTER></P><P></B>\n<FONT FACE=\"Helvetica, Arial, Sans Serif\">\n");
751
sendString("You can use all filter expressions libpcap can handle, \n");
752
sendString("like the ones you pass to tcpdump.<BR>\n");
753
sendString("If \"new filter expression\" is left empty, no filtering is performed.<BR>\n");
754
sendString("If you want the statistics to be reset, you have to do that manually ");
755
sendString("with <A HREF=\"resetStats.html\">Reset Stats</A>.<BR>\n");
756
sendString("<B>Be careful</B>: That can take quite a long time!");
757
sendString("<BR><B></FONT>\n");
760
/* *******************************/
766
static struct _menuData menuItem[] = {
767
{ "Show Users", "showUsers" },
768
{ "Add User", "addUser" },
769
{ "Show URLs", "showURLs" },
770
{ "Add URL", "addURL" }
773
/* *******************************/
775
static void sendMenuFooter(int itm1Idx, int itm2Idx) {
778
sendString("<CENTER>\n");
779
sendString("<H4><FONT FACE=\"Helvetica, Arial, Sans Serif\">\n");
780
if(snprintf(buf, sizeof(buf),
781
"[<A HREF=/%s.html>%s</A>] [<A HREF=/%s.html>%s</A>]\n",
782
menuItem[itm1Idx].anchor, menuItem[itm1Idx].text,
783
menuItem[itm2Idx].anchor, menuItem[itm2Idx].text) < 0)
784
traceEvent(TRACE_ERROR, "Buffer overflow!");
786
sendString("</FONT></H4>\n");
787
sendString("</CENTER>\n");
791
/* *******************************/
793
static void encodeWebFormURL(char *in, char *buf, int buflen) {
796
for(i=j=0; (in[i]!='\0') && (j<(buflen-4)); i++) {
797
c = (unsigned int)in[i];
798
if(isalpha(c) || isdigit(c)) {
800
} else if(c == ' ') {
805
buf[j++] = (d < 10) ? '0'+d : 'A'+(d-10);
807
buf[j++] = (d < 10) ? '0'+d : 'A'+(d-10);
813
/* *******************************/
815
static void decodeWebFormURL(char *buf) {
818
for(i=j=0; buf[i]!='\0'; i++,j++) {
822
} else if(buf[j] == '%') {
823
buf[j] = ((buf[i+1] >= 'A' ? ((buf[i+1] & 0xdf) - 'A')+10 : (buf[i+1] - '0')) & 0x0f) << 4 |
824
((buf[i+2] >= 'A' ? ((buf[i+2] & 0xdf) - 'A')+10 : (buf[i+2] - '0')) & 0x0f);
831
/* *******************************/
833
static int readHTTPpostData(int len, char *buf, int buflen) {
837
SSL* ssl = getSSLsocket(-newSock);
840
memset(buf, 0, buflen);
842
if(len > (buflen-8)) {
843
traceEvent(TRACE_ERROR, "Too much HTTP POST data");
850
rc = SSL_read(ssl, &buf[idx], len);
852
rc = recv(newSock, &buf[idx], len, 0);
854
rc = recv(newSock, &buf[idx], len, 0);
867
struct timeval wait_time;
870
FD_SET((unsigned int)abs(newSock), &mask);
872
/* select returns immediately */
873
wait_time.tv_sec = 0, wait_time.tv_usec = 0;
874
if(select(newSock+1, &mask, 0, 0, &wait_time) == 1) {
875
char aChar[8]; /* just in case */
879
rc = SSL_read(ssl, aChar, 1);
881
rc = recv(newSock, aChar, 1, 0);
883
rc = recv(newSock, aChar, 1, 0);
892
printf("HTTP POST data: '%s' (%d)\n", buf, idx);
897
traceEvent(TRACE_INFO, "Data: '%s' (%d)\n", buf, idx);
903
#endif /* HAVE_GDBM_H */
904
#endif /* MICRO_NTOP */
906
/* *******************************/
908
static void addKeyIfMissing(char* key, char* value, int encryptValue) {
909
datum key_data, return_data, data_data;
914
/* Check existence of user 'admin' */
916
key_data.dsize = strlen(key_data.dptr)+1;
919
accessMutex(&gdbmMutex, "addKeyIfMissing");
921
return_data = gdbm_fetch(pwFile, key_data);
923
releaseMutex(&gdbmMutex);
926
if(return_data.dptr == NULL) {
927
/* If not existing, the add user 'admin', pw 'admin' */
930
data_data.dptr = value;
932
strncpy(cpw, (char*)crypt(value, (const char*)CRYPT_SALT), sizeof(cpw));
933
cpw[sizeof(cpw)-1] = '\0';
934
data_data.dptr = cpw;
937
data_data.dptr = value;
940
traceEvent(TRACE_INFO, "'%s' <-> '%s'\n", key, data_data.dptr);
943
data_data.dsize = strlen(data_data.dptr)+1;
945
accessMutex(&gdbmMutex, "showUsers");
947
gdbm_store(pwFile, key_data, data_data, GDBM_REPLACE);
949
releaseMutex(&gdbmMutex);
952
free(return_data.dptr);
955
/* *******************************/
957
void addDefaultAdminUser(void) {
958
/* Add user 'admin/admin' if not existing */
959
addKeyIfMissing("1admin", "admin", 1);
961
/* Add user 'admin' for URL 'show...' if not existing */
962
addKeyIfMissing("2showU", "users=1admin", 0);
963
addKeyIfMissing("2modifyU", "users=1admin", 0);
964
addKeyIfMissing("2deleteU", "users=1admin", 0);
965
addKeyIfMissing("2shut", "users=1admin", 0);
966
addKeyIfMissing("2resetStats", "users=1admin", 0);
967
addKeyIfMissing("2chang", "users=1admin", 0);