1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 #include "suricata-common.h"
19 #include "suricata.h"
20 
21 #include "debug.h"
22 #include "decode.h"
23 #include "threads.h"
24 
25 #include "util-print.h"
26 #include "util-pool.h"
27 #include "util-debug.h"
28 
29 #include "flow-util.h"
30 
31 #include "detect-engine-state.h"
32 
33 #include "stream-tcp-private.h"
34 #include "stream-tcp-reassemble.h"
35 #include "stream-tcp.h"
36 #include "stream.h"
37 
38 #include "app-layer-protos.h"
39 #include "app-layer-parser.h"
40 #include "app-layer.h"
41 
42 #include "util-spm.h"
43 #include "util-unittest.h"
44 
45 #include "app-layer-dcerpc-common.h"
46 #include "app-layer-dcerpc.h"
47 
DCERPCParseRequest(Flow * f,void * dcerpc_state,AppLayerParserState * pstate,const uint8_t * input,uint32_t input_len,void * local_data,const uint8_t flags)48 static AppLayerResult DCERPCParseRequest(Flow *f, void *dcerpc_state,
49                               AppLayerParserState *pstate,
50                               const uint8_t *input, uint32_t input_len,
51                               void *local_data, const uint8_t flags)
52 {
53     if (input == NULL && input_len > 0) {
54         AppLayerResult res = rs_parse_dcerpc_request_gap(dcerpc_state, input_len);
55         SCLogDebug("DCERPC request GAP of %u bytes, retval %d", input_len, res.status);
56         SCReturnStruct(res);
57     } else {
58         AppLayerResult res = rs_dcerpc_parse_request(
59                 f, dcerpc_state, pstate, input, input_len, local_data, flags);
60         SCLogDebug("DCERPC request%s of %u bytes, retval %d",
61                 (input == NULL && input_len > 0) ? " is GAP" : "", input_len, res.status);
62         SCReturnStruct(res);
63     }
64 }
65 
DCERPCParseResponse(Flow * f,void * dcerpc_state,AppLayerParserState * pstate,const uint8_t * input,uint32_t input_len,void * local_data,const uint8_t flags)66 static AppLayerResult DCERPCParseResponse(Flow *f, void *dcerpc_state,
67                                AppLayerParserState *pstate,
68                                const uint8_t *input, uint32_t input_len,
69                                void *local_data, const uint8_t flags)
70 {
71     if (input == NULL && input_len > 0) {
72         AppLayerResult res = rs_parse_dcerpc_response_gap(dcerpc_state, input_len);
73         SCLogDebug("DCERPC response GAP of %u bytes, retval %d", input_len, res.status);
74         SCReturnStruct(res);
75     } else {
76         AppLayerResult res = rs_dcerpc_parse_response(
77                 f, dcerpc_state, pstate, input, input_len, local_data, flags);
78         SCLogDebug("DCERPC response%s of %u bytes, retval %d",
79                 (input == NULL && input_len > 0) ? " is GAP" : "", input_len, res.status);
80         SCReturnStruct(res);
81     }
82 }
83 
RustDCERPCStateNew(void * state_orig,AppProto proto_orig)84 static void *RustDCERPCStateNew(void *state_orig, AppProto proto_orig)
85 {
86     return rs_dcerpc_state_new(state_orig, proto_orig);
87 }
88 
DCERPCStateFree(void * s)89 static void DCERPCStateFree(void *s)
90 {
91     return rs_dcerpc_state_free(s);
92 }
93 
DCERPCSetTxDetectState(void * vtx,DetectEngineState * de_state)94 static int DCERPCSetTxDetectState(void *vtx, DetectEngineState *de_state)
95 {
96     return rs_dcerpc_set_tx_detect_state(vtx, de_state);
97 }
98 
DCERPCGetTxDetectState(void * vtx)99 static DetectEngineState *DCERPCGetTxDetectState(void *vtx)
100 {
101     return rs_dcerpc_get_tx_detect_state(vtx);
102 }
103 
DCERPCStateTransactionFree(void * state,uint64_t tx_id)104 static void DCERPCStateTransactionFree(void *state, uint64_t tx_id)
105 {
106     return rs_dcerpc_state_transaction_free(state, tx_id);
107 }
108 
DCERPCGetTx(void * state,uint64_t tx_id)109 static void *DCERPCGetTx(void *state, uint64_t tx_id)
110 {
111     return rs_dcerpc_get_tx(state, tx_id);
112 }
113 
DCERPCGetTxCnt(void * state)114 static uint64_t DCERPCGetTxCnt(void *state)
115 {
116     return rs_dcerpc_get_tx_cnt(state);
117 }
118 
DCERPCGetAlstateProgressCompletionStatus(uint8_t direction)119 static int DCERPCGetAlstateProgressCompletionStatus(uint8_t direction)
120 {
121     return rs_dcerpc_get_alstate_progress_completion_status(direction);
122 }
123 
DCERPCGetAlstateProgress(void * tx,uint8_t direction)124 static int DCERPCGetAlstateProgress(void *tx, uint8_t direction)
125 {
126     return rs_dcerpc_get_alstate_progress(tx, direction);
127 }
128 
DCERPCTCPProbe(Flow * f,uint8_t direction,const uint8_t * input,uint32_t len,uint8_t * rdir)129 static uint16_t DCERPCTCPProbe(
130         Flow *f, uint8_t direction, const uint8_t *input, uint32_t len, uint8_t *rdir)
131 {
132     SCLogDebug("DCERPCTCPProbe");
133 
134     const int r = rs_dcerpc_probe_tcp(direction, input, len, rdir);
135     switch (r) {
136         case 1:
137             return ALPROTO_DCERPC;
138         case 0:
139             return ALPROTO_UNKNOWN;
140         case -1:
141         default:
142             return ALPROTO_FAILED;
143     }
144 }
145 
DCERPCRegisterPatternsForProtocolDetection(void)146 static int DCERPCRegisterPatternsForProtocolDetection(void)
147 {
148     if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0,
149                 STREAM_TOSERVER, DCERPCTCPProbe, 0, 0) < 0) {
150         return -1;
151     }
152     if (AppLayerProtoDetectPMRegisterPatternCSwPP(IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0,
153                 STREAM_TOCLIENT, DCERPCTCPProbe, 0, 0) < 0) {
154         return -1;
155     }
156 
157     return 0;
158 }
159 
RegisterDCERPCParsers(void)160 void RegisterDCERPCParsers(void)
161 {
162     const char *proto_name = "dcerpc";
163 
164     if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
165         AppLayerProtoDetectRegisterProtocol(ALPROTO_DCERPC, proto_name);
166         if (DCERPCRegisterPatternsForProtocolDetection() < 0)
167             return;
168     } else {
169         SCLogInfo("Protocol detection and parser disabled for %s protocol.",
170                   proto_name);
171         return;
172     }
173 
174     if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
175         AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DCERPC, STREAM_TOSERVER,
176                                      DCERPCParseRequest);
177         AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_DCERPC, STREAM_TOCLIENT,
178                                      DCERPCParseResponse);
179         AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_DCERPC, RustDCERPCStateNew,
180                                          DCERPCStateFree);
181         AppLayerParserRegisterParserAcceptableDataDirection(IPPROTO_TCP, ALPROTO_DCERPC, STREAM_TOSERVER);
182 
183 
184         AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCStateTransactionFree);
185 
186         AppLayerParserRegisterDetectStateFuncs(IPPROTO_TCP, ALPROTO_DCERPC,
187                                                DCERPCGetTxDetectState, DCERPCSetTxDetectState);
188 
189         AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCGetTx);
190         AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_DCERPC, rs_dcerpc_get_tx_data);
191 
192         AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCGetTxCnt);
193 
194         AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_DCERPC, DCERPCGetAlstateProgress);
195 
196         AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_DCERPC,
197                                                                DCERPCGetAlstateProgressCompletionStatus);
198         /* This parser accepts gaps. */
199         AppLayerParserRegisterOptionFlags(IPPROTO_TCP, ALPROTO_DCERPC, APP_LAYER_PARSER_OPT_ACCEPT_GAPS);
200 
201         AppLayerParserRegisterTruncateFunc(IPPROTO_TCP, ALPROTO_DCERPC, rs_dcerpc_state_trunc);
202     } else {
203         SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
204                   "still on.", proto_name);
205     }
206     return;
207 }
208