~ubuntu-branches/ubuntu/wily/ntop/wily-proposed

« back to all changes in this revision

Viewing changes to ntop/admin.c

  • Committer: Bazaar Package Importer
  • Author(s): Dennis Schoen
  • Date: 2002-04-12 11:38:47 UTC
  • Revision ID: james.westby@ubuntu.com-20020412113847-4k4yydw0pzybc6g8
Tags: upstream-2.0.0
ImportĀ upstreamĀ versionĀ 2.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 1998-2001 Luca Deri <deri@ntop.org>
 
3
 *                          Portions by Stefano Suin <stefano@ntop.org>
 
4
 *                      
 
5
 *                          http://www.ntop.org/
 
6
 *                                      
 
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.
 
11
 *
 
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.
 
16
 *
 
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.
 
20
 */
 
21
 
 
22
#include "ntop.h"
 
23
#include "globals-report.h"
 
24
 
 
25
 
 
26
#ifndef MICRO_NTOP
 
27
 
 
28
/* Forward */
 
29
#ifdef HAVE_GDBM_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);
 
34
#endif
 
35
 
 
36
/* *******************************/
 
37
 
 
38
#ifdef HAVE_GDBM_H
 
39
void showUsers(void) {
 
40
  u_int numUsers=0;
 
41
  char buf[BUF_SIZE], ebuf[128];
 
42
  datum key_data, return_data;
 
43
 
 
44
  printHTMLheader("Registered ntop Users", HTML_FLAG_NO_REFRESH);
 
45
  sendString("<P><HR><P>\n");
 
46
 
 
47
#ifdef MULTITHREADED
 
48
    accessMutex(&gdbmMutex, "showUsers");
 
49
#endif 
 
50
  return_data = gdbm_firstkey(pwFile);
 
51
 
 
52
  while (return_data.dptr != NULL) {
 
53
    /* traceEvent(TRACE_INFO, "1) -> %s\n", return_data.dptr); */
 
54
    key_data = return_data;
 
55
 
 
56
    if(key_data.dptr[0] == '1') /* 1 = user */{
 
57
      if(numUsers == 0) {
 
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");
 
61
      }
 
62
 
 
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
                "&nbsp;%s</TH><TD "TD_BG"><A HREF=/modifyUser?%s>"
 
66
                "<IMG ALT=\"Modify User\" SRC=/modifyUser.gif BORDER=0 align=absmiddle></A>"
 
67
                "&nbsp;</TD></TR></TH></TR>\n", &key_data.dptr[1], key_data.dptr) < 0) 
 
68
          traceEvent(TRACE_ERROR, "Buffer overflow!");
 
69
      } else{
 
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
                "&nbsp;%s</TH><TD "TD_BG"><A HREF=/modifyUser?%s>"
 
73
                "<IMG ALT=\"Modify User\" SRC=/modifyUser.gif BORDER=0 align=absmiddle></A>"
 
74
                "&nbsp;<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!");
 
77
      }
 
78
      sendString(buf);
 
79
      numUsers++;
 
80
    }
 
81
 
 
82
    return_data = gdbm_nextkey(pwFile, key_data);
 
83
    free(key_data.dptr);
 
84
  }
 
85
    
 
86
#ifdef MULTITHREADED
 
87
  releaseMutex(&gdbmMutex);
 
88
#endif 
 
89
 
 
90
  if(numUsers > 0) {
 
91
    sendString("</TABLE>"TABLE_OFF"\n<P>\n");
 
92
    sendString("</CENTER>\n");
 
93
  }
 
94
  sendMenuFooter(1, 2);
 
95
}
 
96
 
 
97
/* *******************************/
 
98
 
 
99
void addUser(char* user) {
 
100
  char tmpStr[128];
 
101
    
 
102
  printHTMLheader("Manage ntop Users", HTML_FLAG_NO_REFRESH);
 
103
  sendString("<P><HR><P>\n");
 
104
 
 
105
  if((user != NULL) && ((strlen(user) < 2) || (user[0] != '1'))) {
 
106
    printFlagedWarning("<I>The specified username is invalid.</I>");
 
107
  } else {
 
108
    sendString("<CENTER>\n");
 
109
    sendString("<FORM METHOD=POST ACTION=/doAddUser>\n");
 
110
 
 
111
    sendString("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=5>\n");
 
112
    sendString("<TR>\n<TH ALIGN=right>User:&nbsp;</TH><TD ALIGN=left>");
 
113
    if(user != NULL) {
 
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!");
 
119
      sendString(tmpStr);
 
120
    } else
 
121
      sendString("<INPUT TYPE=text NAME=user SIZE=20>\n");
 
122
    sendString("</TD>\n</TR>\n");
 
123
    sendString("<TR>\n<TH ALIGN=right>Password:&nbsp;</TH>"
 
124
               "<TD ALIGN=left><INPUT TYPE=password NAME=pw SIZE=20></TD></TR>\n");
 
125
    sendString("</TABLE>\n");
 
126
 
 
127
    if(snprintf(tmpStr, sizeof(tmpStr),
 
128
           "<INPUT TYPE=submit VALUE=\"%s\">&nbsp;&nbsp;&nbsp;<INPUT TYPE=reset>\n",
 
129
           (user != NULL) ? "Modify User" : "Add User") < 0) 
 
130
          traceEvent(TRACE_ERROR, "Buffer overflow!");
 
131
    sendString(tmpStr);
 
132
 
 
133
    sendString("</FORM>\n");
 
134
    sendString("</CENTER>\n");
 
135
  }
 
136
  sendMenuFooter(0, 2);
 
137
}
 
138
 
 
139
/* *******************************/
 
140
 
 
141
void deleteUser(char* user) {
 
142
 
 
143
  if(user == NULL) {
 
144
    returnHTTPredirect("showUsers.html");
 
145
    return;
 
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>");
 
151
  } else {
 
152
    int rc;
 
153
    datum key_data;
 
154
 
 
155
    decodeWebFormURL(user);
 
156
    key_data.dptr = user;
 
157
    key_data.dsize = strlen(user)+1;
 
158
      
 
159
#ifdef MULTITHREADED
 
160
    accessMutex(&gdbmMutex, "deleteUser");
 
161
#endif 
 
162
    rc = gdbm_delete(pwFile, key_data);
 
163
#ifdef MULTITHREADED
 
164
    releaseMutex(&gdbmMutex);
 
165
#endif 
 
166
 
 
167
    if(rc != 0) {
 
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>");
 
172
    } else {
 
173
      returnHTTPredirect("showUsers.html");
 
174
      return;
 
175
    }
 
176
 
 
177
  }
 
178
  sendMenuFooter(1, 2);
 
179
  printHTMLtrailer();
 
180
}
 
181
/* *******************************/
 
182
 
 
183
void doAddUser(int len) {
 
184
  char *err=NULL;
 
185
 
 
186
  if(len <= 0) {
 
187
    err = "ERROR: both user and password must be non empty fields.";
 
188
  } else {
 
189
    char postData[256], *key, *user=NULL, *pw=NULL;
 
190
    int i, idx, badChar=0;
 
191
 
 
192
    if((idx = readHTTPpostData(len, postData, sizeof(postData))) < 0)
 
193
      return; /* FIXME (DL): an HTTP error code should be sent here */
 
194
 
 
195
    for(i=0,key=postData; i<idx; i++) {
 
196
      if(postData[i] == '&') {
 
197
        postData[i] = '\0';
 
198
        key = &postData[i+1];
 
199
      } else if((key != NULL) && (postData[i] == '=')) {
 
200
        postData[i] = '\0';
 
201
        if(strcmp(key, "user") == 0)
 
202
          user = &postData[i+1];
 
203
        else if(strcmp(key, "pw") == 0)
 
204
          pw = &postData[i+1];
 
205
        key = NULL;
 
206
      }
 
207
    }
 
208
    if(user != NULL) {
 
209
      decodeWebFormURL(user);
 
210
      for(i=0; i<strlen(user); i++) {
 
211
        if(!(isalpha(user[i]) || isdigit(user[i]))) {
 
212
          badChar = 1;
 
213
          break;
 
214
        }
 
215
      }
 
216
    }
 
217
    if(pw != NULL)
 
218
      decodeWebFormURL(pw);
 
219
 
 
220
#if 0
 
221
    printf("User='%s' - Pw='%s'\n", user?user:"(not given)", pw?pw:"(not given)");
 
222
    fflush(stdout);
 
223
#endif
 
224
 
 
225
    if((user == NULL ) || (user[0] == '\0') || (pw == NULL) || (pw[0] == '\0')) {
 
226
      err = "ERROR: both user and password must be non empty fields.";
 
227
    } else if(badChar) {
 
228
      err = "ERROR: the specified user name contains invalid characters.";
 
229
    } else {
 
230
      char tmpBuf[64];
 
231
#ifndef WIN32
 
232
      char cpw[14];
 
233
#endif
 
234
      datum data_data, key_data;
 
235
 
 
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;
 
240
#ifdef WIN32
 
241
      data_data.dptr = pw;
 
242
#else
 
243
      strncpy(cpw, (char*)crypt(pw, (const char*)CRYPT_SALT), sizeof(cpw));
 
244
      cpw[sizeof(cpw)-1] = '\0';
 
245
      data_data.dptr = cpw;
 
246
#endif
 
247
      data_data.dsize = strlen(data_data.dptr)+1;
 
248
#ifdef DEBUG
 
249
      traceEvent(TRACE_INFO, "User='%s' - Pw='%s [%s]'\n", user, pw, data_data.dptr);
 
250
#endif
 
251
 
 
252
#ifdef MULTITHREADED
 
253
      accessMutex(&gdbmMutex, "doAddUser");
 
254
#endif 
 
255
      if(gdbm_store(pwFile, key_data, data_data, GDBM_REPLACE) != 0)
 
256
        err = "FATAL ERROR: unable to add the new user.";
 
257
 
 
258
#ifdef MULTITHREADED
 
259
      releaseMutex(&gdbmMutex);
 
260
#endif 
 
261
    }
 
262
  }
 
263
 
 
264
  if(err != NULL) {
 
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);
 
270
    printHTMLtrailer();
 
271
  } else {
 
272
    returnHTTPredirect("showUsers.html");
 
273
  }
 
274
}
 
275
 
 
276
/* ***********************************
 
277
   *********************************** */
 
278
 
 
279
void showURLs(void) {
 
280
  u_int numUsers=0;
 
281
  char buf[BUF_SIZE], ebuf[128];
 
282
  datum key_data, return_data;
 
283
 
 
284
  printHTMLheader("Restricted ntop URLs", HTML_FLAG_NO_REFRESH);
 
285
  sendString("<P><HR><P>\n");
 
286
 
 
287
#ifdef MULTITHREADED
 
288
  accessMutex(&gdbmMutex, "showURLs");
 
289
#endif 
 
290
 
 
291
  return_data = gdbm_firstkey(pwFile);
 
292
 
 
293
  while (return_data.dptr != NULL) {
 
294
    /* traceEvent(TRACE_INFO, "1) -> %s\n", return_data.dptr); */
 
295
    key_data = return_data;
 
296
 
 
297
    if(key_data.dptr[0] == '2') { /* 2 = URL */
 
298
      if(numUsers == 0) {
 
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");
 
302
      }
 
303
 
 
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
              "&nbsp;'%s*'</TH><TD "TD_BG"><A HREF=/modifyURL?%s>"
 
307
              "<IMG ALT=\"Modify User\" SRC=/modifyUser.gif BORDER=0 align=absmiddle></A>"
 
308
              "&nbsp;<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!");
 
311
      sendString(buf);
 
312
      numUsers++;      
 
313
    }
 
314
 
 
315
    return_data = gdbm_nextkey(pwFile, key_data);
 
316
    free(key_data.dptr);
 
317
  }
 
318
 
 
319
#ifdef MULTITHREADED
 
320
  releaseMutex(&gdbmMutex);
 
321
#endif 
 
322
    
 
323
  if(numUsers > 0) {
 
324
    sendString("</TABLE>"TABLE_OFF"\n<P>\n");
 
325
    sendString("</CENTER>\n");
 
326
  } 
 
327
  sendMenuFooter(3, 0);
 
328
}
 
329
 
 
330
/* *******************************/
 
331
 
 
332
void addURL(char* url) {
 
333
  int i;
 
334
  datum key_data, return_data;
 
335
  char *aubuf=NULL, *authorisedUser[20];
 
336
  char tmpStr[128];
 
337
 
 
338
  printHTMLheader("Manage ntop URLs", HTML_FLAG_NO_REFRESH);
 
339
  sendString("<P><HR><P>\n");
 
340
 
 
341
  if((url != NULL) && ((strlen(url) < 1) || (url[0] != '2'))) {
 
342
    printFlagedWarning("<I>The specified URL is invalid.</I>");
 
343
 
 
344
  } else {
 
345
    sendString("<CENTER>\n");
 
346
    sendString("<FORM METHOD=POST ACTION=/doAddURL>\n");
 
347
 
 
348
    sendString("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3>\n");
 
349
    if(url != NULL)
 
350
      sendString("<TR>\n<TH ALIGN=right VALIGN=top><B>URL</B>:&nbsp;</TH>");
 
351
    else
 
352
      sendString("<TR>\n<TH ALIGN=right VALIGN=middle><B>URL</B>:&nbsp;</TH>");
 
353
    sendString("<TD ALIGN=left><TT>http://&lt;"
 
354
               "<I>ntop host</I>&gt;:&lt;<I>ntop port</I>&gt;/</TT>");
 
355
    if(url != NULL) {
 
356
      decodeWebFormURL(url);
 
357
      if(snprintf(tmpStr, sizeof(tmpStr),
 
358
               "<INPUT TYPE=hidden NAME=url SIZE=20 VALUE=\"%s\">"
 
359
               "<B>%s</B>&nbsp;<B>*</B>  [Initial URL string]",
 
360
               &url[1], &url[1]) < 0) 
 
361
          traceEvent(TRACE_ERROR, "Buffer overflow!");
 
362
      sendString(tmpStr);
 
363
    } else {
 
364
      sendString("<INPUT TYPE=text NAME=url SIZE=20>&nbsp;*");
 
365
    }
 
366
    sendString("</TD>\n</TR>\n");
 
367
    sendString("<TR>\n<TH ALIGN=right VALIGN=top>Authorised Users:&nbsp;</TH>"
 
368
               "<TD ALIGN=left><SELECT NAME=users MULTIPLE>\n");
 
369
 
 
370
#ifdef MULTITHREADED
 
371
    accessMutex(&gdbmMutex, "addURL");
 
372
#endif 
 
373
  
 
374
    authorisedUser[0] = NULL;
 
375
    if(url != NULL) {
 
376
      key_data.dptr = url;
 
377
      key_data.dsize = strlen(url)+1;
 
378
      return_data = gdbm_fetch(pwFile, key_data);
 
379
 
 
380
      if(return_data.dptr != NULL) {
 
381
        char *strtokState, *item;
 
382
 
 
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);
 
388
        }
 
389
        if(item != NULL) {
 
390
          traceEvent(TRACE_ERROR, "Too many users for URL='%s'\n", url);
 
391
        } 
 
392
        authorisedUser[i] = NULL;
 
393
      }
 
394
    }
 
395
 
 
396
    return_data = gdbm_firstkey(pwFile);
 
397
 
 
398
    while (return_data.dptr != NULL) {
 
399
      key_data = return_data;
 
400
 
 
401
      if(key_data.dptr[0] == '1') { /* 1 = user */
 
402
        int found = 0;
 
403
 
 
404
        for(i=0; authorisedUser[i] != NULL; i++) {
 
405
          if(strcmp(authorisedUser[i], key_data.dptr) == 0)
 
406
            found = 1;
 
407
        }
 
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!");
 
412
        sendString(tmpStr);
 
413
      }
 
414
 
 
415
      return_data = gdbm_nextkey(pwFile, key_data);
 
416
      free(key_data.dptr);
 
417
    }
 
418
 
 
419
    if(aubuf != NULL)
 
420
      free(aubuf); /* (**) */
 
421
 
 
422
#ifdef MULTITHREADED
 
423
    releaseMutex(&gdbmMutex);
 
424
#endif 
 
425
 
 
426
    sendString("</SELECT>\n</TD></TR>\n");
 
427
    sendString("</TABLE>\n");
 
428
 
 
429
    if(url == NULL)
 
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");
 
435
 
 
436
    if(snprintf(tmpStr, sizeof(tmpStr),
 
437
             "<INPUT TYPE=submit VALUE=\"%s\">&nbsp;&nbsp;&nbsp;<INPUT TYPE=reset>\n",
 
438
             (url != NULL) ? "Modify URL" : "Add URL") < 0) 
 
439
          traceEvent(TRACE_ERROR, "Buffer overflow!");
 
440
    sendString(tmpStr);
 
441
 
 
442
    sendString("</FORM>\n");
 
443
    sendString("</CENTER>\n");
 
444
 
 
445
  }
 
446
  sendMenuFooter(0, 2);
 
447
}
 
448
 
 
449
/* *******************************/
 
450
 
 
451
void deleteURL(char* url) {
 
452
 
 
453
  if(url == NULL) {
 
454
    returnHTTPredirect("showURLs.html");
 
455
    return;
 
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>");
 
461
  } else {
 
462
    int rc;
 
463
    datum key_data;
 
464
 
 
465
    decodeWebFormURL(url);
 
466
    key_data.dptr = url;
 
467
    key_data.dsize = strlen(url)+1;
 
468
 
 
469
#ifdef MULTITHREADED
 
470
    accessMutex(&gdbmMutex, "deleteURL");
 
471
#endif 
 
472
    rc = gdbm_delete(pwFile, key_data);
 
473
#ifdef MULTITHREADED
 
474
    releaseMutex(&gdbmMutex);
 
475
#endif 
 
476
 
 
477
    if(rc != 0) {
 
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>");
 
482
    } else {
 
483
      returnHTTPredirect("showURLs.html");
 
484
      return;
 
485
    }
 
486
 
 
487
  }
 
488
  sendMenuFooter(3, 0);
 
489
  printHTMLtrailer();
 
490
}
 
491
 
 
492
/* *******************************/
 
493
 
 
494
void doAddURL(int len) {
 
495
  char *err=NULL;
 
496
  char postData[256], *key, *url=NULL, *users=NULL, authorizedUsers[256];
 
497
  int i, idx, alen=0, badChar=0;
 
498
 
 
499
  /*
 
500
    Authorization fix
 
501
    courtesy of David Brown <david@caldera.com>
 
502
  */
 
503
 
 
504
  if((idx = readHTTPpostData(len, postData, sizeof(postData))) < 0)
 
505
    return; /* FIXME (DL): an HTTP error code should be sent here */
 
506
 
 
507
  memset(authorizedUsers, 0, sizeof(authorizedUsers));
 
508
  for(i=0,key=postData; i<=idx; i++) {
 
509
    if((i==idx) || (postData[i] == '&')) {
 
510
      if(users != NULL) {
 
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);
 
516
        users = NULL;
 
517
      }
 
518
      if(i==idx) break;
 
519
      postData[i] = '\0';
 
520
      key = &postData[i+1];
 
521
    } else if((key != NULL) && (postData[i] == '=')) {
 
522
      postData[i] = '\0';
 
523
      if(strcmp(key, "url") == 0) {
 
524
        url = &postData[i+1];
 
525
      } else if(strcmp(key, "users") == 0) {
 
526
        users = &postData[i+1];
 
527
      }
 
528
      key = NULL;
 
529
    }
 
530
  }
 
531
  if(url != NULL) {
 
532
    decodeWebFormURL(url);
 
533
    for(i=0; i<strlen(url); i++) {
 
534
      if(!(isalpha(url[i]) || isdigit(url[i]) || (strchr("/-_?", url[i]) != NULL))) {
 
535
        badChar = 1;
 
536
        break;
 
537
      }
 
538
    }
 
539
  }
 
540
 
 
541
#if 0
 
542
  printf("URL: '%s' - users: '%s'\n", url?url:"(not given)", strlen(authorizedUsers)>0?authorizedUsers:"(not given)"); 
 
543
  fflush(stdout);
 
544
#endif
 
545
 
 
546
  if(authorizedUsers[0] == '\0') {
 
547
    err = "ERROR: user must be a non empty field.";
 
548
  } else if(badChar) {
 
549
    err = "ERROR: the specified URL contains invalid characters.";
 
550
  } else {
 
551
    char tmpBuf[64];
 
552
    datum data_data, key_data;
 
553
 
 
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;
 
560
    
 
561
#ifdef MULTITHREADED
 
562
    accessMutex(&gdbmMutex, "doAddURL");
 
563
#endif 
 
564
    if(gdbm_store(pwFile, key_data, data_data, GDBM_REPLACE) != 0)
 
565
      err = "FATAL ERROR: unable to add the new URL.";
 
566
#ifdef MULTITHREADED
 
567
    releaseMutex(&gdbmMutex);
 
568
#endif 
 
569
  }
 
570
#ifdef MULTITHREADED
 
571
  releaseMutex(&gdbmMutex);
 
572
#endif 
 
573
 
 
574
  if(err != NULL) {
 
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);
 
580
    printHTMLtrailer();
 
581
  } else {
 
582
    returnHTTPredirect("showURLs.html");
 
583
  }
 
584
}
 
585
 
 
586
/* *******************************/
 
587
 
 
588
/* Courtesy of Michael Weidel <michael.weidel@gmx.de> */
 
589
 
 
590
int doChangeFilter(int len) {
 
591
  int i,idx,badChar=0;
 
592
  struct bpf_program fcode;
 
593
  char *currentFilterExpressionSav;
 
594
  char buf[BUF_SIZE],postData[256],*key,*err=NULL;
 
595
 
 
596
  currentFilterExpressionSav=strdup(currentFilterExpression);  /* Backup */
 
597
 
 
598
  if((idx = readHTTPpostData(len, postData, sizeof(postData))) < 0)
 
599
    return 1;
 
600
 
 
601
  for(i=0,key=postData; i<=idx; i++) {
 
602
    if(postData[i] == '&') {
 
603
      postData[i] = '\0';
 
604
      key = &postData[i+1];
 
605
    } else if((key != NULL) && (postData[i] == '=')) {
 
606
      postData[i] = '\0';
 
607
      if(strcmp(key, "filter") == 0) {
 
608
       currentFilterExpression = strdup(&postData[i+1]);
 
609
      }
 
610
      key = NULL;
 
611
    }
 
612
  }
 
613
  if(key == NULL) {
 
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? */
 
620
       break;
 
621
      }
 
622
    }
 
623
  } else err = "ERROR: The HTTP Post Data was invalid.";
 
624
  if(badChar)
 
625
    err = "ERROR: the specified filter expression contains invalid characters.";
 
626
  if(err==NULL) {
 
627
    traceEvent(TRACE_INFO, "Changing the kernel (libpcap) filter...");
 
628
    
 
629
#ifdef MULTITHREADED
 
630
    accessMutex(&gdbmMutex, "changeFilter");
 
631
#endif
 
632
 
 
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.";
 
642
        } else{
 
643
         if(*currentFilterExpression!='\0'){
 
644
           traceEvent(TRACE_INFO, "Set filter \"%s\" on device %s.", 
 
645
                      currentFilterExpression, device[i].name);
 
646
         }else{
 
647
           traceEvent(TRACE_INFO, "Set no kernel (libpcap) filtering on device %s.",
 
648
                      device[i].name);
 
649
         }
 
650
        }
 
651
      }
 
652
    }
 
653
 
 
654
#ifdef MULTITHREADED
 
655
    releaseMutex(&gdbmMutex);
 
656
#endif
 
657
  }
 
658
  sendHTTPHeader(HTTP_TYPE_HTML, 0);
 
659
 
 
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");
 
672
  } else {
 
673
    printHTMLheader("changing kernel (libpcap) filter expression", HTML_FLAG_NO_REFRESH);
 
674
    sendString("<P><HR></P>\n<P><CENTER>");
 
675
  }
 
676
 
 
677
  sendString("<FONT FACE=\"Helvetica, Arial, Sans Serif\">\n");
 
678
 
 
679
  if(err == NULL) {
 
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!");
 
685
      sendString(buf);
 
686
    } else sendString("<B>Kernel (libpcap) filtering disabled.</B></FONT>\n");
 
687
 
 
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");
 
695
    } else {
 
696
      sendString("</CENTER></P>\n");
 
697
      /* sendString("<P><CENTER>The statistics are also reset.</CENTER></P>\n"); */
 
698
      printHTMLtrailer();
 
699
    }
 
700
 
 
701
    if(currentFilterExpressionSav!=NULL) free(currentFilterExpressionSav);
 
702
    return 0; /* -> Statistics are reset (if uncommented) */
 
703
  } else {
 
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);
 
714
        }
 
715
      }
 
716
    }
 
717
 
 
718
    printFlagedWarning(err);
 
719
    if(filterExpressionInExtraFrame) sendString("</BODY>\n</HTML>\n");
 
720
    else printHTMLtrailer();
 
721
    return 2;
 
722
  }
 
723
}
 
724
 
 
725
/* ******************************* */
 
726
 
 
727
/* Courtesy of Michael Weidel <michael.weidel@gmx.de> */
 
728
 
 
729
void changeFilter(void) {
 
730
  char buf[BUF_SIZE];
 
731
  
 
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:&nbsp;</TH><TD ALIGN=left>");
 
736
  if(snprintf(buf, sizeof(buf), "<B>%s",
 
737
             currentFilterExpression) < 0)
 
738
    traceEvent(TRACE_ERROR, "Buffer overflow!");
 
739
  sendString(buf);
 
740
  if(*currentFilterExpression=='\0') sendString("&lt;No filter defined&gt;");
 
741
  sendString("</B><BR>\n</TD>\n</TR>\n");
 
742
  
 
743
  sendString("<FORM METHOD=POST ACTION=/doChangeFilter>\n");
 
744
  sendString("<TR>\n<TH "TH_BG" ALIGN=center>New Filter Expression:&nbsp;</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\">&nbsp;&nbsp;&nbsp;");
 
748
  sendString("<INPUT TYPE=reset></FORM>");
 
749
  
 
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");
 
758
}
 
759
 
 
760
/* *******************************/
 
761
 
 
762
struct _menuData {
 
763
  char  *text, *anchor;
 
764
};
 
765
 
 
766
static struct _menuData menuItem[] = {
 
767
  { "Show Users", "showUsers" },
 
768
  { "Add User",   "addUser" },
 
769
  { "Show URLs",  "showURLs" },
 
770
  { "Add URL",    "addURL" }
 
771
};
 
772
 
 
773
/* *******************************/
 
774
 
 
775
static void sendMenuFooter(int itm1Idx, int itm2Idx) {
 
776
  char  buf[128];
 
777
 
 
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>]&nbsp;[<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!");
 
785
  sendString(buf);
 
786
  sendString("</FONT></H4>\n");
 
787
  sendString("</CENTER>\n");
 
788
 
 
789
}
 
790
 
 
791
/* *******************************/
 
792
 
 
793
static void encodeWebFormURL(char *in, char *buf, int buflen) {
 
794
  int i, j, c, d;
 
795
 
 
796
  for(i=j=0; (in[i]!='\0') && (j<(buflen-4)); i++) {
 
797
    c = (unsigned int)in[i];
 
798
    if(isalpha(c) || isdigit(c)) {
 
799
      buf[j++] = (char)c;
 
800
    } else if(c == ' ') {
 
801
      buf[j++] = '+';
 
802
    } else {
 
803
      buf[j++] = '%';
 
804
      d = (c>>4) & 0x0f;
 
805
      buf[j++] = (d < 10) ? '0'+d : 'A'+(d-10);
 
806
      d = c & 0x0f;
 
807
      buf[j++] = (d < 10) ? '0'+d : 'A'+(d-10);
 
808
    }
 
809
  }
 
810
  buf[j] = '\0';
 
811
}
 
812
 
 
813
/* *******************************/
 
814
 
 
815
static void decodeWebFormURL(char *buf) {
 
816
  int i, j;
 
817
 
 
818
  for(i=j=0; buf[i]!='\0'; i++,j++) {
 
819
    buf[j] = buf[i];
 
820
    if(buf[j] == '+') {
 
821
      buf[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);
 
825
      i += 2;
 
826
    }
 
827
  }
 
828
  buf[j] = '\0';
 
829
}
 
830
 
 
831
/* *******************************/
 
832
 
 
833
static int readHTTPpostData(int len, char *buf, int buflen) {
 
834
  int rc, idx=0;
 
835
 
 
836
#ifdef HAVE_OPENSSL
 
837
  SSL* ssl = getSSLsocket(-newSock);
 
838
#endif
 
839
 
 
840
  memset(buf, 0, buflen);
 
841
 
 
842
  if(len > (buflen-8)) {
 
843
    traceEvent(TRACE_ERROR, "Too much HTTP POST data");
 
844
    return (-1);
 
845
  }
 
846
 
 
847
  while(len > 0) {
 
848
#ifdef HAVE_OPENSSL
 
849
    if(newSock < 0) 
 
850
      rc = SSL_read(ssl, &buf[idx], len);
 
851
    else
 
852
      rc = recv(newSock, &buf[idx], len, 0);
 
853
#else
 
854
    rc = recv(newSock, &buf[idx], len, 0);
 
855
#endif
 
856
    if(rc < 0)
 
857
      return (-1);
 
858
 
 
859
    idx += rc;
 
860
    len -= rc;
 
861
  }
 
862
 
 
863
  buf[idx] = '\0';
 
864
  
 
865
  while(1) {
 
866
    fd_set mask;
 
867
    struct timeval wait_time;
 
868
 
 
869
    FD_ZERO(&mask);
 
870
    FD_SET((unsigned int)abs(newSock), &mask);    
 
871
  
 
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 */
 
876
 
 
877
#ifdef HAVE_OPENSSL
 
878
      if(newSock < 0) 
 
879
        rc = SSL_read(ssl, aChar, 1);
 
880
      else
 
881
        rc = recv(newSock, aChar, 1, 0);
 
882
#else
 
883
      rc = recv(newSock, aChar, 1, 0);
 
884
#endif
 
885
      if(rc <= 0)
 
886
        break;
 
887
    } else
 
888
      break;
 
889
  }
 
890
 
 
891
#if 0
 
892
  printf("HTTP POST data: '%s' (%d)\n", buf, idx); 
 
893
  fflush(stdout);
 
894
#endif
 
895
 
 
896
#ifdef DEBUG
 
897
  traceEvent(TRACE_INFO, "Data: '%s' (%d)\n", buf, idx); 
 
898
#endif
 
899
 
 
900
  return (idx);
 
901
}
 
902
 
 
903
#endif /* HAVE_GDBM_H */
 
904
#endif /* MICRO_NTOP */
 
905
 
 
906
/* *******************************/
 
907
 
 
908
static void addKeyIfMissing(char* key, char* value, int encryptValue) {
 
909
  datum key_data, return_data, data_data;
 
910
#ifndef WIN32
 
911
  char cpw[14];
 
912
#endif
 
913
 
 
914
  /* Check existence of user 'admin' */
 
915
  key_data.dptr = key;
 
916
  key_data.dsize = strlen(key_data.dptr)+1;
 
917
 
 
918
#ifdef MULTITHREADED
 
919
  accessMutex(&gdbmMutex, "addKeyIfMissing");
 
920
#endif 
 
921
  return_data = gdbm_fetch(pwFile, key_data);
 
922
#ifdef MULTITHREADED
 
923
  releaseMutex(&gdbmMutex);
 
924
#endif
 
925
 
 
926
  if(return_data.dptr == NULL) {
 
927
    /* If not existing, the add user 'admin', pw 'admin' */
 
928
    if(encryptValue) {
 
929
#ifdef WIN32
 
930
      data_data.dptr = value;
 
931
#else
 
932
      strncpy(cpw, (char*)crypt(value, (const char*)CRYPT_SALT), sizeof(cpw));
 
933
      cpw[sizeof(cpw)-1] = '\0';
 
934
      data_data.dptr = cpw;
 
935
#endif
 
936
    } else
 
937
      data_data.dptr = value;    
 
938
    
 
939
#ifdef DEBUG
 
940
    traceEvent(TRACE_INFO, "'%s' <-> '%s'\n", key, data_data.dptr);
 
941
#endif
 
942
    
 
943
    data_data.dsize = strlen(data_data.dptr)+1;
 
944
#ifdef MULTITHREADED
 
945
    accessMutex(&gdbmMutex, "showUsers");
 
946
#endif 
 
947
    gdbm_store(pwFile, key_data, data_data, GDBM_REPLACE);
 
948
#ifdef MULTITHREADED
 
949
    releaseMutex(&gdbmMutex);
 
950
#endif
 
951
  } else
 
952
    free(return_data.dptr);
 
953
}
 
954
 
 
955
/* *******************************/
 
956
 
 
957
void addDefaultAdminUser(void) {
 
958
  /* Add user 'admin/admin' if not existing */
 
959
  addKeyIfMissing("1admin", "admin", 1);
 
960
 
 
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);
 
968
}
 
969