Branch data Line data Source code
1 : : // $Id: MIME.h 3526 2006-09-12 07:32:21Z vern $
2 : :
3 : : #ifndef mime_h
4 : : #define mime_h
5 : :
6 : : #include <assert.h>
7 : :
8 : : #include <stdio.h>
9 : : #include <vector>
10 : : #include <queue>
11 : : using namespace std;
12 : :
13 : : #include "md5.h"
14 : : #include "Base64.h"
15 : : #include "BroString.h"
16 : : #include "Analyzer.h"
17 : :
18 : : // MIME: Multipurpose Internet Mail Extensions
19 : : // Follows RFC 822 & 2822 (Internet Mail), 2045-2049 (MIME)
20 : : // See related files: SMTP.h and SMTP.cc
21 : :
22 : : // MIME Constants
23 : :
24 : : #define HT '\011'
25 : : #define SP '\040'
26 : : #define CR '\015'
27 : : #define LF '\012'
28 : :
29 : : enum MIME_CONTENT_TYPE {
30 : : CONTENT_TYPE_MULTIPART,
31 : : CONTENT_TYPE_MESSAGE,
32 : : CONTENT_TYPE_TEXT,
33 : : CONTENT_TYPE_OTHER, // image | audio | video | application | <other>
34 : : };
35 : :
36 : : enum MIME_EVENT_TYPE {
37 : : MIME_EVENT_ILLEGAL_FORMAT,
38 : : MIME_EVENT_ILLEGAL_ENCODING,
39 : : MIME_EVENT_CONTENT_GAP,
40 : : MIME_EVENT_OTHER,
41 : : };
42 : :
43 : :
44 : :
45 : : // MIME data structures.
46 : :
47 : : class MIME_Multiline;
48 : : class MIME_Header;
49 : : class MIME_Body;
50 : : class MIME_Entity; // an "entity" contains headers and a body
51 : : class MIME_Mail;
52 : : class MIME_Message;
53 : :
54 : : class MIME_Multiline {
55 : : public:
56 : : MIME_Multiline();
57 : : ~MIME_Multiline();
58 : :
59 : : void append(int len, const char* data);
60 : : BroString* get_concatenated_line();
61 : :
62 : : protected:
63 : : vector<const BroString*> buffer;
64 : : BroString* line;
65 : : };
66 : :
67 : : class MIME_Header {
68 : : public:
69 : : MIME_Header(MIME_Multiline* hl);
70 : : ~MIME_Header();
71 : :
72 : 63111 : data_chunk_t get_name() const { return name; }
73 : 16419 : data_chunk_t get_value() const { return value; }
74 : :
75 : : data_chunk_t get_value_token();
76 : : data_chunk_t get_value_after_token();
77 : :
78 : : protected:
79 : : int get_first_token();
80 : :
81 : : MIME_Multiline* lines;
82 : : data_chunk_t name;
83 : : data_chunk_t value;
84 : : data_chunk_t value_token, rest_value;
85 : : };
86 : :
87 : :
88 : : // declare(PList, MIME_Header);
89 : : typedef vector<MIME_Header*> MIME_HeaderList;
90 : :
91 : : class MIME_Entity {
92 : : public:
93 : : MIME_Entity(MIME_Message* output_message, MIME_Entity* parent_entity);
94 : : virtual ~MIME_Entity();
95 : :
96 : : virtual void Deliver(int len, const char* data, int trailing_CRLF);
97 : : virtual void EndOfData();
98 : :
99 : 881 : MIME_Entity* Parent() const { return parent; }
100 : 0 : StringVal* ContentType() const { return content_type_str; }
101 : 0 : StringVal* ContentSubType() const { return content_subtype_str; }
102 : 0 : int ContentTransferEncoding() const { return content_encoding; }
103 : :
104 : : protected:
105 : : void init();
106 : :
107 : : // {begin, continuation, end} of a header.
108 : : void NewHeader(int len, const char* data);
109 : : void ContHeader(int len, const char* data);
110 : : void FinishHeader();
111 : :
112 : : void ParseMIMEHeader(MIME_Header* h);
113 : : int LookupMIMEHeaderName(data_chunk_t name);
114 : : int ParseContentTypeField(MIME_Header* h);
115 : : int ParseContentEncodingField(MIME_Header* h);
116 : : int ParseFieldParameters(int len, const char* data);
117 : :
118 : : void ParseContentType(data_chunk_t type, data_chunk_t sub_type);
119 : : void ParseContentEncoding(data_chunk_t encoding_mechanism);
120 : : void ParseParameter(data_chunk_t attr, data_chunk_t val);
121 : :
122 : : void BeginBody();
123 : : void NewDataLine(int len, const char* data, int trailing_CRLF);
124 : :
125 : : int CheckBoundaryDelimiter(int len, const char* data);
126 : : void DecodeDataLine(int len, const char* data, int trailing_CRLF);
127 : : void DecodeBinary(int len, const char* data, int trailing_CRLF);
128 : : void DecodeQuotedPrintable(int len, const char* data);
129 : : void DecodeBase64(int len, const char* data);
130 : : void StartDecodeBase64();
131 : : void FinishDecodeBase64();
132 : :
133 : : int GetDataBuffer();
134 : : void DataOctet(char ch);
135 : : void DataOctets(int len, const char* data);
136 : : void SubmitData(int len, const char* buf);
137 : :
138 : : virtual void SubmitHeader(MIME_Header* h);
139 : : // Submit all headers in member "headers".
140 : : virtual void SubmitAllHeaders();
141 : :
142 : 0 : virtual MIME_Entity* NewChildEntity() { return new MIME_Entity(message, this); }
143 : : void BeginChildEntity();
144 : : void EndChildEntity();
145 : :
146 : : void IllegalFormat(const char* explanation);
147 : : void IllegalEncoding(const char* explanation);
148 : :
149 : : void DebugPrintHeaders();
150 : :
151 : : int in_header;
152 : : int end_of_data;
153 : : MIME_Multiline* current_header_line;
154 : : int current_field_type;
155 : : int need_to_parse_parameters;
156 : :
157 : : StringVal* content_type_str;
158 : : StringVal* content_subtype_str;
159 : : BroString* content_encoding_str;
160 : : BroString* multipart_boundary;
161 : :
162 : : int content_type, content_subtype, content_encoding;
163 : :
164 : : MIME_HeaderList headers;
165 : : MIME_Entity* parent;
166 : : MIME_Entity* current_child_entity;
167 : :
168 : : Base64Decoder* base64_decoder;
169 : :
170 : : int data_buf_length;
171 : : char* data_buf_data;
172 : : int data_buf_offset;
173 : :
174 : : MIME_Message* message;
175 : : };
176 : :
177 : : // The reason I separate MIME_Message as an abstract class is to
178 : : // present the *interface* separated from its implementation to
179 : : // generate Bro events.
180 : :
181 : : class MIME_Message {
182 : : public:
183 : 881 : MIME_Message(Analyzer* arg_analyzer)
184 : 881 : {
185 : : // Cannot initialize top_level entity because we do
186 : : // not know its type yet (MIME_Entity / MIME_Mail /
187 : : // etc.).
188 : 881 : top_level = 0;
189 : 881 : finished = 0;
190 : 881 : analyzer = arg_analyzer;
191 : 881 : }
192 : :
193 : 881 : virtual ~MIME_Message()
194 : 881 : {
195 [ - + ][ # # ]: 881 : if ( ! finished )
[ # # ]
196 : 0 : internal_error("Done() must be called before destruction");
197 [ - + ][ # # ]: 881 : }
[ # # ]
198 : :
199 : 881 : virtual void Done() { finished = 1; }
200 : :
201 : 331 : int Finished() const { return finished; }
202 : :
203 : 11277 : virtual void Deliver(int len, const char* data, int trailing_CRLF)
204 : : {
205 : 11277 : top_level->Deliver(len, data, trailing_CRLF);
206 : 11277 : }
207 : :
208 : 881 : Analyzer* GetAnalyzer() const { return analyzer; }
209 : :
210 : : // Events generated by MIME_Entity
211 : : virtual void BeginEntity(MIME_Entity*) = 0;
212 : : virtual void EndEntity(MIME_Entity*) = 0;
213 : : virtual void SubmitHeader(MIME_Header* h) = 0;
214 : : virtual void SubmitAllHeaders(MIME_HeaderList& hlist) = 0;
215 : : virtual void SubmitData(int len, const char* buf) = 0;
216 : : virtual int RequestBuffer(int* plen, char** pbuf) = 0;
217 : : virtual void SubmitEvent(int event_type, const char* detail) = 0;
218 : :
219 : : protected:
220 : : Analyzer* analyzer;
221 : :
222 : : MIME_Entity* top_level;
223 : : int finished;
224 : :
225 : : RecordVal* BuildHeaderVal(MIME_Header* h);
226 : : TableVal* BuildHeaderTable(MIME_HeaderList& hlist);
227 : : };
228 : :
229 : : class MIME_Mail : public MIME_Message {
230 : : public:
231 : : MIME_Mail(Analyzer* mail_conn, int buf_size = 0);
232 : : ~MIME_Mail();
233 : : void Done();
234 : :
235 : : void BeginEntity(MIME_Entity* entity);
236 : : void EndEntity(MIME_Entity* entity);
237 : : void SubmitHeader(MIME_Header* h);
238 : : void SubmitAllHeaders(MIME_HeaderList& hlist);
239 : : void SubmitData(int len, const char* buf);
240 : : int RequestBuffer(int* plen, char** pbuf);
241 : : void SubmitAllData();
242 : : void SubmitEvent(int event_type, const char* detail);
243 : :
244 : : protected:
245 : : int min_overlap_length;
246 : : int max_chunk_length;
247 : : int buffer_start;
248 : : int data_start;
249 : : int buffer_offset;
250 : : int compute_content_hash;
251 : : int content_hash_length;
252 : : md5_state_t md5_hash;
253 : : vector<const BroString*> entity_content;
254 : : vector<const BroString*> all_content;
255 : :
256 : : BroString* data_buffer;
257 : : };
258 : :
259 : :
260 : : extern int is_null_data_chunk(data_chunk_t b);
261 : : extern StringVal* new_string_val(int length, const char* data);
262 : : extern StringVal* new_string_val(const char* data, const char* end_of_data);
263 : : extern StringVal* new_string_val(const data_chunk_t buf);
264 : : extern int fputs(data_chunk_t b, FILE* fp);
265 : : extern int strcasecmp_n(data_chunk_t s, const char* t);
266 : : extern int is_lws(char ch);
267 : : extern int MIME_is_field_name_char(char ch);
268 : : extern int MIME_count_leading_lws(int len, const char* data);
269 : : extern int MIME_count_trailing_lws(int len, const char* data);
270 : : extern int MIME_skip_comments(int len, const char* data);
271 : : extern int MIME_skip_lws_comments(int len, const char* data);
272 : : extern int MIME_get_token(int len, const char* data, data_chunk_t* token);
273 : : extern int MIME_get_slash_token_pair(int len, const char* data, data_chunk_t* first, data_chunk_t* second);
274 : : extern int MIME_get_value(int len, const char* data, BroString*& buf);
275 : : extern int MIME_get_field_name(int len, const char* data, data_chunk_t* name);
276 : : extern BroString* MIME_decode_quoted_pairs(data_chunk_t buf);
277 : :
278 : : #endif
|