~ubuntu-branches/ubuntu/natty/ntop/natty

« back to all changes in this revision

Viewing changes to ntop/admin.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2005-01-30 21:59:13 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050130215913-xc3ke963bw49b3k4
Tags: 2:3.0-5
* Updated README.Debian file so users will understand what to do at
  install, closes: #291794, #287802.
* Updated ntop init script to give better output.
* Also changed log directory from /var/lib/ntop to /var/log/ntop,
  closes: #252352.
* Quoted the interface list to allow whitespace, closes: #267248.
* Added a couple of logcheck ignores, closes: #269321, #269319.

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