Importing all of DRL, including ulogd and all of its files.
[distributedratelimiting.git] / extensions / ulogd_PWSNIFF.c
1 /* ulogd_PWSNIFF.c, Version $Revision: 5372 $
2  *
3  * ulogd logging interpreter for POP3 / FTP like plaintext passwords.
4  *
5  * (C) 2000-2003 by Harald Welte <laforge@gnumonks.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 version 2 
9  *  as published by the Free Software Foundation
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * $Id: ulogd_PWSNIFF.c 5372 2005-05-04 01:22:56Z laforge $
21  *
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <netinet/ip.h>
29 #include <netinet/in.h>
30 #include <netinet/tcp.h>
31 #include "chtons.h"
32 #include <ulogd/ulogd.h>
33
34 #ifdef DEBUG_PWSNIFF
35 #define DEBUGP(x) ulogd_log(ULOGD_DEBUG, x)
36 #else
37 #define DEBUGP(format, args...)
38 #endif
39
40
41 #define PORT_POP3       110
42 #define PORT_FTP        21
43
44 static u_int16_t pwsniff_ports[] = {
45         __constant_htons(PORT_POP3),
46         __constant_htons(PORT_FTP),
47         /* feel free to include any other ports here, provided that their
48          * user/password syntax is the same */
49 };
50
51 #define PWSNIFF_MAX_PORTS 2
52
53 static char *_get_next_blank(char* begp, char *endp)
54 {
55         char *ptr;
56
57         for (ptr = begp; ptr < endp; ptr++) {
58                 if (*ptr == ' ' || *ptr == '\n' || *ptr == '\r') {
59                         return ptr-1;   
60                 }
61         }
62         return NULL;
63 }
64
65 static ulog_iret_t *_interp_pwsniff(ulog_interpreter_t *ip, ulog_packet_msg_t *pkt)
66 {
67         struct iphdr *iph = (struct iphdr *) pkt->payload;
68         void *protoh = (u_int32_t *)iph + iph->ihl;
69         struct tcphdr *tcph = protoh;
70         u_int32_t tcplen = ntohs(iph->tot_len) - iph->ihl * 4;
71         unsigned char  *ptr, *begp, *pw_begp, *endp, *pw_endp;
72         ulog_iret_t *ret = ip->result;
73         int len, pw_len, i, cont = 0;
74
75         len = pw_len = 0;
76         begp = pw_begp = NULL;
77
78         if (iph->protocol != IPPROTO_TCP)
79                 return NULL;
80         
81         for (i = 0; i < PWSNIFF_MAX_PORTS; i++)
82         {
83                 if (tcph->dest == pwsniff_ports[i]) {
84                         cont = 1; 
85                         break;
86                 }
87         }
88         if (!cont)
89                 return NULL;
90
91         DEBUGP("----> pwsniff detected, tcplen=%d, struct=%d, iphtotlen=%d, ihl=%d\n", tcplen, sizeof(struct tcphdr), ntohs(iph->tot_len), iph->ihl);
92
93         for (ptr = (unsigned char *) tcph + sizeof(struct tcphdr); 
94                         ptr < (unsigned char *) tcph + tcplen; ptr++)
95         {
96                 if (!strncasecmp((char *)ptr, "USER ", 5)) {
97                         begp = ptr+5;
98                         endp = (unsigned char *)_get_next_blank((char *)begp, (char *)tcph + tcplen);
99                         if (endp)
100                                 len = endp - begp + 1;
101                 }
102                 if (!strncasecmp((char *)ptr, "PASS ", 5)) {
103                         pw_begp = ptr+5;
104                         pw_endp = (unsigned char *)_get_next_blank((char *)pw_begp, 
105                                         (char *)tcph + tcplen);
106                         if (pw_endp)
107                                 pw_len = pw_endp - pw_begp + 1;
108                 }
109         }
110
111         if (len) {
112                 ret[0].value.ptr = (char *) malloc(len+1);
113                 ret[0].flags |= ULOGD_RETF_VALID;
114                 if (!ret[0].value.ptr) {
115                         ulogd_log(ULOGD_ERROR, "OOM (size=%u)\n", len);
116                         return NULL;
117                 }
118                 strncpy(ret[0].value.ptr, (char *)begp, len);
119                 *((char *)ret[0].value.ptr + len + 1) = '\0';
120         }
121         if (pw_len) {
122                 ret[1].value.ptr = (char *) malloc(pw_len+1);
123                 ret[1].flags |= ULOGD_RETF_VALID;
124                 if (!ret[1].value.ptr){
125                         ulogd_log(ULOGD_ERROR, "OOM (size=%u)\n", pw_len);
126                         return NULL;
127                 }
128                 strncpy(ret[1].value.ptr, (char *)pw_begp, pw_len);
129                 *((char *)ret[1].value.ptr + pw_len + 1) = '\0';
130
131         }
132         return ret;
133 }
134
135 static ulog_iret_t pwsniff_rets[] = {
136         { .type = ULOGD_RET_STRING, 
137           .flags = ULOGD_RETF_FREE, 
138           .key = "pwsniff.user", 
139         }, 
140         { .type = ULOGD_RET_STRING, 
141           .flags = ULOGD_RETF_FREE, 
142           .key = "pwsniff.pass", 
143         },
144 };
145
146 static ulog_interpreter_t base_ip[] = { 
147         { .name = "pwsniff", 
148           .interp = &_interp_pwsniff, 
149           .key_num = 2, 
150           .result = pwsniff_rets },
151         { NULL, "", 0, NULL, 0, NULL }, 
152 };
153
154 static void _base_reg_ip(void)
155 {
156         ulog_interpreter_t *ip = base_ip;
157         ulog_interpreter_t *p;
158
159         for (p = ip; p->interp; p++)
160                 register_interpreter(p);
161 }
162
163
164 void _init(void)
165 {
166         _base_reg_ip();
167 }