1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2004-2013 Sourcefire, Inc.
4 //
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.
9 //
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.
14 //
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 //--------------------------------------------------------------------------
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "telnet.h"
25 
26 #include "detection/detection_engine.h"
27 #include "log/messages.h"
28 #include "profiler/profiler.h"
29 #include "protocols/packet.h"
30 
31 #include "ft_main.h"
32 #include "ftp_print.h"
33 #include "ftpp_return_codes.h"
34 #include "ftpp_si.h"
35 #include "ftpp_ui_config.h"
36 #include "pp_telnet.h"
37 #include "telnet_module.h"
38 
39 using namespace snort;
40 
41 THREAD_LOCAL ProfileStats telnetPerfStats;
42 THREAD_LOCAL TelnetStats tnstats;
43 
44 //-------------------------------------------------------------------------
45 // implementation
46 //-------------------------------------------------------------------------
47 
TelnetCheckConfigs(SnortConfig *,void * pData)48 static int TelnetCheckConfigs(SnortConfig*, void* pData)
49 {
50     TELNET_PROTO_CONF* telnet_config = (TELNET_PROTO_CONF*)pData;
51 
52     if ((telnet_config->ayt_threshold > 0) &&
53         !telnet_config->normalize)
54     {
55         ParseWarning(WARN_CONF, "telnet configuration check: using an "
56             "AreYouThere threshold requires telnet normalization to be "
57             "turned on.\n");
58     }
59     if ( telnet_config->detect_encrypted &&
60         !telnet_config->normalize)
61     {
62         ParseWarning(WARN_CONF, "telnet configuration check: checking for "
63             "encrypted traffic requires telnet normalization to be turned on.\n");
64     }
65 
66     return 0;
67 }
68 
SnortTelnet(TELNET_PROTO_CONF * telnet_config,TELNET_SESSION * Telnetsession,Packet * p,int iInspectMode)69 static int SnortTelnet(TELNET_PROTO_CONF* telnet_config, TELNET_SESSION* Telnetsession,
70     Packet* p, int iInspectMode)
71 {
72     Profile profile(telnetPerfStats);
73 
74     if ( !Telnetsession )
75         return FTPP_NONFATAL_ERR;
76 
77     if ( Telnetsession->encr_state &&
78          !Telnetsession->telnet_conf->check_encrypted_data )
79         return FTPP_SUCCESS;
80 
81     if ( telnet_config->normalize )
82     {
83         DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
84         int ret = normalize_telnet(Telnetsession, p, buf, iInspectMode,
85             FTPP_APPLY_TNC_ERASE_CMDS, false);
86 
87         if ( ret == FTPP_SUCCESS || ret == FTPP_NORMALIZED )
88             do_detection(p);
89     }
90 
91     else
92     {
93         do_detection(p);
94     }
95 
96     return FTPP_SUCCESS;
97 }
98 
snort_telnet(TELNET_PROTO_CONF * GlobalConf,Packet * p)99 static int snort_telnet(TELNET_PROTO_CONF* GlobalConf, Packet* p)
100 {
101     FTPP_SI_INPUT SiInput;
102     int iInspectMode = FTPP_SI_NO_MODE;
103     FTP_TELNET_SESSION* ft_ssn = nullptr;
104 
105     /*
106      * Set up the FTPP_SI_INPUT pointer.  This is what the session_inspection()
107      * routines use to determine client and server traffic.  Plus, this makes
108      * the FTPTelnet library very independent from snort.
109      */
110     SetSiInput(&SiInput, p);
111 
112     if (p->flow)
113     {
114         TelnetFlowData* fd = (TelnetFlowData*)
115             p->flow->get_flow_data(FtpFlowData::inspector_id);
116 
117         ft_ssn = fd ? &fd->session.ft_ssn : nullptr;
118 
119         if (ft_ssn != nullptr)
120         {
121             SiInput.pproto = ft_ssn->proto;
122 
123             if (ft_ssn->proto == FTPP_SI_PROTO_TELNET)
124             {
125                 if (SiInput.pdir != FTPP_SI_NO_MODE)
126                 {
127                     iInspectMode = SiInput.pdir;
128                 }
129                 else
130                 {
131                     if ( p->is_from_server() )
132                     {
133                         iInspectMode = FTPP_SI_SERVER_MODE;
134                     }
135                     else if ( p->is_from_client() )
136                     {
137                         iInspectMode = FTPP_SI_CLIENT_MODE;
138                     }
139                 }
140             }
141             else
142             {
143                 assert(false);
144                 p->flow->free_flow_data(FtpFlowData::inspector_id);
145                 return 0;
146             }
147         }
148     }
149 
150     if (GlobalConf == nullptr)
151         return 0;
152 
153     if (ft_ssn == nullptr)
154     {
155         SiInput.pproto = FTPP_SI_PROTO_UNKNOWN;
156         iInspectMode = FTPP_SI_NO_MODE;
157 
158         TelnetsessionInspection(p, GlobalConf, (TELNET_SESSION**)&ft_ssn, &SiInput, &iInspectMode);
159 
160         if ( SiInput.pproto != FTPP_SI_PROTO_TELNET )
161             return FTPP_INVALID_PROTO;
162     }
163 
164     if (ft_ssn != nullptr)
165     {
166         switch (SiInput.pproto)
167         {
168         case FTPP_SI_PROTO_TELNET:
169             return SnortTelnet(GlobalConf, (TELNET_SESSION*)ft_ssn, p, iInspectMode);
170         }
171     }
172 
173     /* Uh, shouldn't get here  */
174     return FTPP_INVALID_PROTO;
175 }
176 
177 //-------------------------------------------------------------------------
178 // class stuff
179 //-------------------------------------------------------------------------
180 
181 class Telnet : public Inspector
182 {
183 public:
184     Telnet(TELNET_PROTO_CONF*);
185     ~Telnet() override;
186 
187     bool configure(SnortConfig*) override;
188     void show(const SnortConfig*) const override;
189     void eval(Packet*) override;
190 
191     bool get_buf(InspectionBuffer::Type, Packet*, InspectionBuffer&) override;
192     void clear(Packet*) override;
193 
194 private:
195     TELNET_PROTO_CONF* config;
196 };
197 
Telnet(TELNET_PROTO_CONF * pc)198 Telnet::Telnet(TELNET_PROTO_CONF* pc)
199 {
200     config = pc;
201 }
202 
~Telnet()203 Telnet::~Telnet()
204 {
205     if ( config )
206         delete config;
207 }
208 
configure(SnortConfig * sc)209 bool Telnet::configure(SnortConfig* sc)
210 {
211     return !TelnetCheckConfigs(sc, config);
212 }
213 
show(const SnortConfig *) const214 void Telnet::show(const SnortConfig*) const
215 {
216     if ( !config )
217         return;
218 
219     ConfigLogger::log_value("ayt_attack_thresh", config->ayt_threshold);
220     ConfigLogger::log_flag("check_encrypted", config->detect_encrypted);
221     ConfigLogger::log_flag("encrypted_traffic", config->check_encrypted_data);
222     ConfigLogger::log_flag("normalize", config->normalize);
223 }
224 
eval(Packet * p)225 void Telnet::eval(Packet* p)
226 {
227     // precondition - what we registered for
228     assert(p->has_tcp_data());
229 
230     ++tnstats.total_packets;
231     snort_telnet(config, p);
232 }
233 
get_buf(InspectionBuffer::Type ibt,Packet * p,InspectionBuffer & b)234 bool Telnet::get_buf(
235     InspectionBuffer::Type ibt, Packet* p, InspectionBuffer& b)
236 {
237     if ( ibt != InspectionBuffer::IBT_ALT )
238         return false;
239 
240     b.data = get_telnet_buffer(p, b.len);
241 
242     return (b.data != nullptr);
243 }
244 
clear(Packet * p)245 void Telnet::clear(Packet* p)
246 {
247     reset_telnet_buffer(p);
248 }
249 
250 //-------------------------------------------------------------------------
251 // api stuff
252 //-------------------------------------------------------------------------
253 
mod_ctor()254 static Module* mod_ctor()
255 { return new TelnetModule; }
256 
mod_dtor(Module * m)257 static void mod_dtor(Module* m)
258 { delete m; }
259 
tn_init()260 static void tn_init()
261 {
262     TelnetFlowData::init();
263 }
264 
tn_ctor(Module * m)265 static Inspector* tn_ctor(Module* m)
266 {
267     TelnetModule* mod = (TelnetModule*)m;
268     return new Telnet(mod->get_data());
269 }
270 
tn_dtor(Inspector * p)271 static void tn_dtor(Inspector* p)
272 {
273     delete p;
274 }
275 
276 // exported in ftp.cc
277 const InspectApi tn_api =
278 {
279     {
280         PT_INSPECTOR,
281         sizeof(InspectApi),
282         INSAPI_VERSION,
283         0,
284         API_RESERVED,
285         API_OPTIONS,
286         TEL_NAME,
287         TEL_HELP,
288         mod_ctor,
289         mod_dtor
290     },
291     IT_SERVICE,
292     PROTO_BIT__PDU,
293     nullptr, // buffers
294     "telnet",
295     tn_init,
296     nullptr, // pterm
297     nullptr, // tinit
298     nullptr, // tterm
299     tn_ctor,
300     tn_dtor,
301     nullptr, // ssn
302     nullptr  // reset
303 };
304 
305