1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2023 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2005-2013 Sourcefire, Inc.
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation. You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 //--------------------------------------------------------------------------
20 // client_app_tns.cc author Sourcefire Inc.
26 #include "client_app_tns.h"
28 #include "app_info_table.h"
29 #include "application_ids.h"
31 static const char TNS_BANNER
[] = "\000\000";
32 #define TNS_BANNER_LEN (sizeof(TNS_BANNER)-1)
34 #define TNS_TYPE_CONNECT 1
35 #define TNS_TYPE_ACCEPT 2
36 #define TNS_TYPE_ACK 3
37 #define TNS_TYPE_REFUSE 4
38 #define TNS_TYPE_REDIRECT 5
39 #define TNS_TYPE_DATA 6
40 #define TNS_TYPE_NULL 7
41 #define TNS_TYPE_ABORT 9
42 #define TNS_TYPE_RESEND 11
43 #define TNS_TYPE_MARKER 12
44 #define TNS_TYPE_ATTENTION 13
45 #define TNS_TYPE_CONTROL 14
46 #define TNS_TYPE_MAX 19
48 #define CONNECT_VERSION_OFFSET 8
49 #define CONNECT_DATA_OFFSET 26
51 #define USER_STRING "user="
52 #define MAX_USER_POS ((int)sizeof(USER_STRING) - 2)
56 TNS_STATE_MESSAGE_LEN
= 0,
57 TNS_STATE_MESSAGE_CHECKSUM
,
59 TNS_STATE_MESSAGE_RES
,
60 TNS_STATE_MESSAGE_HD_CHECKSUM
,
61 TNS_STATE_MESSAGE_DATA
,
62 TNS_STATE_MESSAGE_CONNECT
,
63 TNS_STATE_MESSAGE_CONNECT_OFFSET_DC
,
64 TNS_STATE_MESSAGE_CONNECT_OFFSET
,
65 TNS_STATE_MESSAGE_CONNECT_PREDATA
,
66 TNS_STATE_MESSAGE_CONNECT_DATA
,
67 TNS_STATE_COLLECT_USER
98 TnsClientDetector::TnsClientDetector(ClientDiscovery
* cdm
)
102 proto
= IpProtocol::TCP
;
104 provides_user
= true;
108 { (const uint8_t*)TNS_BANNER
, TNS_BANNER_LEN
, 2, 0, APP_ID_ORACLE_DATABASE
},
113 { APP_ID_ORACLE_DATABASE
, APPINFO_FLAG_CLIENT_ADDITIONAL
| APPINFO_FLAG_CLIENT_USER
}
116 handler
->register_detector(name
, this, proto
);
120 static int reset_flow_data(ClientTNSData
* fd
)
122 memset(fd
, '\0', sizeof(ClientTNSData
));
123 fd
->state
= TNS_STATE_MESSAGE_LEN
;
124 return APPID_EINVALID
;
127 #define TNS_MAX_INFO_SIZE 63
128 int TnsClientDetector::validate(AppIdDiscoveryArgs
& args
)
130 char username
[TNS_MAX_INFO_SIZE
+ 1];
135 uint16_t user_start
= 0;
136 uint16_t user_end
= 0;
138 if (args
.dir
!= APP_ID_FROM_INITIATOR
)
139 return APPID_INPROCESS
;
141 fd
= (ClientTNSData
*)data_get(args
.asd
);
144 fd
= (ClientTNSData
*)snort_calloc(sizeof(ClientTNSData
));
145 data_add(args
.asd
, fd
, &snort_free
);
146 fd
->state
= TNS_STATE_MESSAGE_LEN
;
150 while (offset
< args
.size
)
154 case TNS_STATE_MESSAGE_LEN
:
155 fd
->l
.raw_len
[fd
->pos
++] = args
.data
[offset
];
156 if (fd
->pos
>= offsetof(ClientTNSMsg
, checksum
))
158 fd
->stringlen
= ntohs(fd
->l
.len
);
159 if (fd
->stringlen
== 2)
161 if (offset
== args
.size
- 1)
163 return reset_flow_data(fd
);
165 else if (fd
->stringlen
< 2)
166 return reset_flow_data(fd
);
167 else if (fd
->stringlen
> args
.size
)
168 return reset_flow_data(fd
);
170 fd
->state
= TNS_STATE_MESSAGE_CHECKSUM
;
174 case TNS_STATE_MESSAGE_CHECKSUM
:
175 if (args
.data
[offset
] != 0)
176 return reset_flow_data(fd
);
178 if (fd
->pos
>= offsetof(ClientTNSMsg
, msg
))
179 fd
->state
= TNS_STATE_MESSAGE
;
182 case TNS_STATE_MESSAGE
:
183 fd
->message
= args
.data
[offset
];
184 if (fd
->message
< TNS_TYPE_CONNECT
|| fd
->message
> TNS_TYPE_MAX
)
185 return reset_flow_data(fd
);
187 fd
->state
= TNS_STATE_MESSAGE_RES
;
189 case TNS_STATE_MESSAGE_RES
:
190 fd
->state
= TNS_STATE_MESSAGE_HD_CHECKSUM
;
193 case TNS_STATE_MESSAGE_HD_CHECKSUM
:
195 if (fd
->pos
>= offsetof(ClientTNSMsg
, data
))
199 case TNS_TYPE_CONNECT
:
200 fd
->state
= TNS_STATE_MESSAGE_CONNECT
;
203 case TNS_TYPE_REFUSE
:
207 case TNS_TYPE_RESEND
:
208 case TNS_TYPE_MARKER
:
209 case TNS_TYPE_ATTENTION
:
210 case TNS_TYPE_CONTROL
:
211 if (fd
->pos
>= fd
->stringlen
)
213 if (offset
== (args
.size
- 1))
215 return reset_flow_data(fd
);
217 fd
->state
= TNS_STATE_MESSAGE_DATA
;
219 case TNS_TYPE_ACCEPT
:
220 case TNS_TYPE_REDIRECT
:
222 return reset_flow_data(fd
);
226 case TNS_STATE_MESSAGE_CONNECT
:
227 if (fd
->pos
>= (CONNECT_VERSION_OFFSET
+ 2))
229 fd
->l
.raw_len
[fd
->pos
- CONNECT_VERSION_OFFSET
] = args
.data
[offset
];
231 if (fd
->pos
== (CONNECT_VERSION_OFFSET
+ 2))
234 switch (ntohs(fd
->l
.len
))
240 fd
->version
= "9i R1";
243 fd
->version
= "9i R2";
246 fd
->version
= "10g R1/R2";
249 fd
->version
= "11g R1";
256 fd
->state
= TNS_STATE_MESSAGE_CONNECT_OFFSET_DC
;
259 case TNS_STATE_MESSAGE_CONNECT_OFFSET_DC
:
261 if (fd
->pos
>= CONNECT_DATA_OFFSET
)
262 fd
->state
= TNS_STATE_MESSAGE_CONNECT_OFFSET
;
264 case TNS_STATE_MESSAGE_CONNECT_OFFSET
:
265 fd
->l
.raw_len
[fd
->pos
- CONNECT_DATA_OFFSET
] = args
.data
[offset
];
267 if (fd
->pos
>= (CONNECT_DATA_OFFSET
+ 2))
269 fd
->offsetlen
= ntohs(fd
->l
.len
);
270 if (fd
->offsetlen
> args
.size
)
272 return reset_flow_data(fd
);
274 fd
->state
= TNS_STATE_MESSAGE_CONNECT_PREDATA
;
277 case TNS_STATE_MESSAGE_CONNECT_PREDATA
:
279 if (fd
->pos
>= fd
->offsetlen
)
281 fd
->state
= TNS_STATE_MESSAGE_CONNECT_DATA
;
284 case TNS_STATE_MESSAGE_CONNECT_DATA
:
285 if (tolower(args
.data
[offset
]) != USER_STRING
[user_pos
])
288 if (tolower(args
.data
[offset
]) == USER_STRING
[user_pos
])
291 else if (++user_pos
> MAX_USER_POS
)
293 user_start
= offset
+1;
294 fd
->state
= TNS_STATE_COLLECT_USER
;
298 if (fd
->pos
>= fd
->stringlen
)
300 if (offset
== (args
.size
- 1))
302 return reset_flow_data(fd
);
305 case TNS_STATE_COLLECT_USER
:
306 if (user_end
== 0 && args
.data
[offset
] == ')')
312 if (fd
->pos
>= fd
->stringlen
)
314 if (offset
== (args
.size
- 1))
316 return reset_flow_data(fd
);
319 case TNS_STATE_MESSAGE_DATA
:
321 if (fd
->pos
>= fd
->stringlen
)
323 if (offset
== (args
.size
- 1))
325 return reset_flow_data(fd
);
334 return APPID_INPROCESS
;
337 add_app(args
.asd
, APP_ID_ORACLE_TNS
, APP_ID_ORACLE_DATABASE
, fd
->version
, args
.change_bits
);
338 if (user_start
&& user_end
&& ((user_size
= user_end
- user_start
) > 0))
340 /* we truncate extra long usernames */
341 if (user_size
> TNS_MAX_INFO_SIZE
)
342 user_size
= TNS_MAX_INFO_SIZE
;
343 memcpy(username
, &args
.data
[user_start
], user_size
);
344 username
[user_size
] = 0;
345 add_user(args
.asd
, username
, APP_ID_ORACLE_DATABASE
, true, args
.change_bits
);
347 return APPID_SUCCESS
;