"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/dynamic-preprocessors/appid/detector_plugins/detector_smtp.c" (16 Oct 2020, 40120 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "detector_smtp.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /*
2 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2005-2013 Sourcefire, Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License Version 2 as
7 ** published by the Free Software Foundation. You may not use, modify or
8 ** distribute this program under any other version of the GNU General
9 ** Public License.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21
22 #include <ctype.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include "appIdApi.h"
29 #include "appInfoTable.h"
30 //#include "flow.h"
31 #include "detector_api.h"
32
33 //#define UNIT_TESTING
34
35 #ifdef UNIT_TESTING
36 #include "fw_appid.h"
37 #endif
38
39 typedef enum
40 {
41 SMTP_CLIENT_STATE_NONE,
42 SMTP_CLIENT_STATE_HELO,
43 SMTP_CLIENT_STATE_MAIL_FROM,
44 SMTP_CLIENT_STATE_RCPT_TO,
45 SMTP_CLIENT_STATE_DATA,
46 SMTP_CLIENT_STATE_MESSAGE,
47 SMTP_CLIENT_STATE_GET_PRODUCT_VERSION,
48 SMTP_CLIENT_STATE_SKIP_LINE,
49 SMTP_CLIENT_STATE_SKIP_SPACE,
50 SMTP_CLIENT_STATE_SKIP_EOL,
51 SMTP_CLIENT_STATE_CONNECTION_ERROR,
52 SMTP_CLIENT_STATE_STARTTLS,
53 SMTP_CLIENT_STATE_LOGIN_USER,
54 SMTP_CLIENT_STATE_LOGIN_PASSWORD
55 } SMTPClientState;
56
57 #define MAX_HEADER_LINE_SIZE 1024
58
59 #ifdef UNIT_TESTING
60 char *stateName [] =
61 {
62 "SMTP_CLIENT_STATE_NONE",
63 "SMTP_CLIENT_STATE_HELO",
64 "SMTP_CLIENT_STATE_MAIL_FROM",
65 "SMTP_CLIENT_STATE_RCPT_TO",
66 "SMTP_CLIENT_STATE_DATA",
67 "SMTP_CLIENT_STATE_MESSAGE",
68 "SMTP_CLIENT_STATE_GET_PRODUCT_VERSION",
69 "SMTP_CLIENT_STATE_SKIP_LINE",
70 "SMTP_CLIENT_STATE_CONNECTION_ERROR",
71 "SMTP_CLIENT_STATE_STARTTLS"
72 };
73 #endif
74
75 /* flag values for ClientSMTPData */
76 #define CLIENT_FLAG_STARTTLS_SUCCESS 0x01
77
78 #define MAX_VERSION_SIZE 64
79 #define SSL_WAIT_PACKETS 8 // This many un-decrypted packets without a HELO and we quit.
80 typedef struct
81 {
82 int flags;
83 SMTPClientState state;
84 SMTPClientState nextstate;
85 uint8_t version[MAX_VERSION_SIZE];
86 unsigned pos;
87 uint8_t *headerline;
88 int decryption_countdown;
89 } ClientSMTPData;
90
91 typedef struct _SMTP_CLIENT_APP_CONFIG
92 {
93 int enabled;
94 } SMTP_CLIENT_APP_CONFIG;
95
96 static SMTP_CLIENT_APP_CONFIG smtp_config;
97
98 static CLIENT_APP_RETCODE smtp_ca_init(const InitClientAppAPI * const init_api, SF_LIST *config);
99 static CLIENT_APP_RETCODE smtp_ca_validate(const uint8_t *data, uint16_t size, const int dir,
100 tAppIdData *flowp, SFSnortPacket *pkt,
101 struct _Detector *userData, const struct appIdConfig_ *pConfig);
102
103 tRNAClientAppModule smtp_client_mod =
104 {
105 .name = "SMTP",
106 .proto = IPPROTO_TCP,
107 .init = &smtp_ca_init,
108 .validate = &smtp_ca_validate,
109 .minimum_matches = 1
110 };
111
112 typedef struct {
113 const u_int8_t *pattern;
114 unsigned length;
115 int index;
116 unsigned appId;
117 } Client_App_Pattern;
118
119 #define HELO "HELO"
120 #define EHLO "EHLO"
121 #define MAILFROM "MAIL FROM:"
122 #define RCPTTO "RCPT TO:"
123 #define DATA "DATA"
124 #define RSET "RSET"
125 #define AUTH "AUTH "
126 #define AUTH_PLAIN "AUTH PLAIN"
127 #define AUTH_LOGIN "AUTH LOGIN"
128 #define STARTTLS "STARTTLS"
129
130 #define STARTTLS_COMMAND_SUCCESS "220 "
131
132 #define MICROSOFT "Microsoft"
133 #define OUTLOOK "Outlook"
134 #define EXPRESS "Express "
135 #define IMO "IMO, "
136 #define MAC "Mac"
137
138 #define XMAILER "X-Mailer: "
139 #define USERAGENT "User-Agent: "
140
141 static const uint8_t APP_SMTP_OUTLOOK[] = "Microsoft Outlook";
142 static const uint8_t APP_SMTP_OUTLOOK_MAC[] = "Microsoft-MacOutlook";
143 static const uint8_t APP_SMTP_OUTLOOK_EXPRESS[] = "Microsoft Outlook Express ";
144 static const uint8_t APP_SMTP_IMO[] = "IMO, ";
145 static const uint8_t APP_SMTP_EVOLUTION[] = "Ximian Evolution ";
146 static const uint8_t APP_SMTP_LOTUSNOTES[] = "Lotus Notes ";
147 static const uint8_t APP_SMTP_APPLEMAIL[] = "Apple Mail (";
148 static const uint8_t APP_SMTP_EUDORA[] = "QUALCOMM Windows Eudora Version ";
149 static const uint8_t APP_SMTP_EUDORAPRO[] = "Windows Eudora Pro Version ";
150 static const uint8_t APP_SMTP_AOL[] = "AOL ";
151 static const uint8_t APP_SMTP_MUTT[] = "Mutt/";
152 static const uint8_t APP_SMTP_KMAIL[] = "KMail/";
153 static const uint8_t APP_SMTP_MTHUNDERBIRD[] = "Mozilla Thunderbird ";
154 static const uint8_t APP_SMTP_THUNDERBIRD[] = "Thunderbird ";
155 static const uint8_t APP_SMTP_MOZILLA[] = "Mozilla";
156 static const uint8_t APP_SMTP_THUNDERBIRD_SHORT[] = "Thunderbird/";
157
158 static Client_App_Pattern patterns[] =
159 {
160 {(uint8_t *)HELO, sizeof(HELO)-1, 0, APP_ID_SMTP},
161 {(uint8_t *)EHLO, sizeof(EHLO)-1, 0, APP_ID_SMTP},
162 {APP_SMTP_OUTLOOK, sizeof(APP_SMTP_OUTLOOK)-1, -1, APP_ID_OUTLOOK},
163 {APP_SMTP_OUTLOOK_MAC, sizeof(APP_SMTP_OUTLOOK_MAC)-1, -1, APP_ID_OUTLOOK},
164 {APP_SMTP_OUTLOOK_EXPRESS, sizeof(APP_SMTP_OUTLOOK_EXPRESS)-1,-1, APP_ID_OUTLOOK_EXPRESS},
165 {APP_SMTP_IMO, sizeof(APP_SMTP_IMO)-1, -1, APP_ID_SMTP_IMO},
166 {APP_SMTP_EVOLUTION, sizeof(APP_SMTP_EVOLUTION)-1, -1, APP_ID_EVOLUTION},
167 {APP_SMTP_LOTUSNOTES, sizeof(APP_SMTP_LOTUSNOTES)-1, -1, APP_ID_LOTUS_NOTES},
168 {APP_SMTP_APPLEMAIL, sizeof(APP_SMTP_APPLEMAIL)-1, -1, APP_ID_APPLE_EMAIL},
169 {APP_SMTP_EUDORA, sizeof(APP_SMTP_EUDORA)-1, -1, APP_ID_EUDORA},
170 {APP_SMTP_EUDORAPRO, sizeof(APP_SMTP_EUDORAPRO)-1, -1, APP_ID_EUDORA_PRO},
171 {APP_SMTP_AOL, sizeof(APP_SMTP_AOL)-1, -1, APP_ID_AOL_EMAIL},
172 {APP_SMTP_MUTT, sizeof(APP_SMTP_MUTT)-1, -1, APP_ID_MUTT},
173 {APP_SMTP_KMAIL, sizeof(APP_SMTP_KMAIL)-1, -1, APP_ID_KMAIL},
174 {APP_SMTP_MTHUNDERBIRD, sizeof(APP_SMTP_MTHUNDERBIRD)-1, -1, APP_ID_THUNDERBIRD},
175 {APP_SMTP_THUNDERBIRD, sizeof(APP_SMTP_THUNDERBIRD)-1, -1, APP_ID_THUNDERBIRD},
176 };
177
178 static tAppRegistryEntry clientAppIdRegistry[] =
179 {
180 {APP_ID_THUNDERBIRD, APPINFO_FLAG_CLIENT_ADDITIONAL},
181 {APP_ID_OUTLOOK, APPINFO_FLAG_CLIENT_ADDITIONAL},
182 {APP_ID_KMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL},
183 {APP_ID_EUDORA_PRO, APPINFO_FLAG_CLIENT_ADDITIONAL},
184 {APP_ID_EVOLUTION, APPINFO_FLAG_CLIENT_ADDITIONAL},
185 {APP_ID_SMTP_IMO, APPINFO_FLAG_CLIENT_ADDITIONAL},
186 {APP_ID_EUDORA, APPINFO_FLAG_CLIENT_ADDITIONAL},
187 {APP_ID_LOTUS_NOTES, APPINFO_FLAG_CLIENT_ADDITIONAL},
188 {APP_ID_APPLE_EMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL},
189 {APP_ID_AOL_EMAIL, APPINFO_FLAG_CLIENT_ADDITIONAL},
190 {APP_ID_MUTT, APPINFO_FLAG_CLIENT_ADDITIONAL},
191 {APP_ID_SMTP, APPINFO_FLAG_CLIENT_ADDITIONAL},
192 {APP_ID_OUTLOOK_EXPRESS, APPINFO_FLAG_CLIENT_ADDITIONAL},
193 {APP_ID_SMTPS, APPINFO_FLAG_CLIENT_ADDITIONAL}
194 };
195
196 static CLIENT_APP_RETCODE smtp_ca_init(const InitClientAppAPI * const init_api, SF_LIST *config)
197 {
198 unsigned i;
199 RNAClientAppModuleConfigItem *item;
200
201 smtp_config.enabled = 1;
202
203 if (config)
204 {
205 for (item = (RNAClientAppModuleConfigItem *)sflist_first(config);
206 item;
207 item = (RNAClientAppModuleConfigItem *)sflist_next(config))
208 {
209 _dpd.debugMsg(DEBUG_LOG,"Processing %s: %s\n",item->name, item->value);
210 if (strcasecmp(item->name, "enabled") == 0)
211 {
212 smtp_config.enabled = atoi(item->value);
213 }
214 }
215 }
216
217 if (smtp_config.enabled)
218 {
219 for (i=0; i < sizeof(patterns)/sizeof(*patterns); i++)
220 {
221 init_api->RegisterPattern(&smtp_ca_validate, IPPROTO_TCP, patterns[i].pattern, patterns[i].length, patterns[i].index, init_api->pAppidConfig);
222 }
223 }
224
225 unsigned j;
226 for (j=0; j < sizeof(clientAppIdRegistry)/sizeof(*clientAppIdRegistry); j++)
227 {
228 _dpd.debugMsg(DEBUG_LOG,"registering appId: %d\n",clientAppIdRegistry[j].appId);
229 init_api->RegisterAppId(&smtp_ca_validate, clientAppIdRegistry[j].appId, clientAppIdRegistry[j].additionalInfo, init_api->pAppidConfig);
230 }
231
232 return CLIENT_APP_SUCCESS;
233 }
234
235 #define SMTP_PORT 25
236 #define SMTP_CLOSING_CONN "closing connection\x0d\x0a"
237
238 typedef enum
239 {
240 SMTP_SERVICE_STATE_NONE,
241 SMTP_SERVICE_STATE_CONNECTION,
242 SMTP_SERVICE_STATE_HELO,
243 SMTP_SERVICE_STATE_BAD_CLIENT,
244 SMTP_SERVICE_STATE_TRANSFER,
245 SMTP_SERVICE_STATE_CONNECTION_ERROR,
246 SMTP_SERVICE_STATE_STARTTLS,
247 SMTP_SERVICE_STATE_SSL_HANDSHAKE
248 } SMTPServiceState;
249
250 typedef struct _SERVICE_SMTP_DATA
251 {
252 SMTPServiceState state;
253 int code;
254 int multiline;
255 int set_flags;
256 } ServiceSMTPData;
257
258 #pragma pack(1)
259
260 typedef struct _SERVICE_SMTP_CODE
261 {
262 uint8_t code[3];
263 uint8_t sp;
264 } ServiceSMTPCode;
265
266 #pragma pack()
267
268 static int smtp_svc_init(const InitServiceAPI * const init_api);
269 static int smtp_svc_validate(ServiceValidationArgs* args);
270
271 static tRNAServiceElement svc_element =
272 {
273 .next = NULL,
274 .validate = &smtp_svc_validate,
275 .detectorType = DETECTOR_TYPE_DECODER,
276 .name = "smtp",
277 .ref_count = 1,
278 .current_ref_count = 1,
279 };
280
281 static RNAServiceValidationPort pp[] =
282 {
283 {&smtp_svc_validate, SMTP_PORT, IPPROTO_TCP},
284 {NULL, 0, 0}
285 };
286
287 tRNAServiceValidationModule smtp_service_mod =
288 {
289 .name = "SMTP",
290 .init = &smtp_svc_init,
291 .pp = pp,
292 };
293
294 #define SMTP_PATTERN1 "220 "
295 #define SMTP_PATTERN2 "220-"
296 #define SMTP_PATTERN3 "SMTP"
297 #define SMTP_PATTERN4 "smtp"
298
299 static tAppRegistryEntry appIdRegistry[] =
300 {
301 {APP_ID_SMTP, APPINFO_FLAG_SERVICE_ADDITIONAL},
302 {APP_ID_SMTPS, APPINFO_FLAG_SERVICE_ADDITIONAL}
303 };
304
305 typedef struct _SMTP_DETECTOR_DATA
306 {
307 ClientSMTPData client;
308 ServiceSMTPData server;
309 int need_continue;
310 } SMTPDetectorData;
311
312 SF_SO_PUBLIC RNADetectorValidationModule smtp_detector_mod =
313 {
314 .service = &smtp_service_mod,
315 .client = &smtp_client_mod,
316 };
317
318 static int smtp_svc_init(const InitServiceAPI * const init_api)
319 {
320 init_api->RegisterPattern(&smtp_svc_validate, IPPROTO_TCP, (uint8_t *)SMTP_PATTERN1, sizeof(SMTP_PATTERN1)-1, 0, "smtp", init_api->pAppidConfig);
321 init_api->RegisterPattern(&smtp_svc_validate, IPPROTO_TCP, (uint8_t *)SMTP_PATTERN2, sizeof(SMTP_PATTERN2)-1, 0, "smtp", init_api->pAppidConfig);
322 init_api->RegisterPattern(&smtp_svc_validate, IPPROTO_TCP, (uint8_t *)SMTP_PATTERN3, sizeof(SMTP_PATTERN3)-1, -1, "smtp", init_api->pAppidConfig);
323 init_api->RegisterPattern(&smtp_svc_validate, IPPROTO_TCP, (uint8_t *)SMTP_PATTERN4, sizeof(SMTP_PATTERN4)-1, -1, "smtp", init_api->pAppidConfig);
324
325 unsigned i;
326 for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
327 {
328 _dpd.debugMsg(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[i].appId);
329 init_api->RegisterAppId(&smtp_svc_validate, appIdRegistry[i].appId, appIdRegistry[i].additionalInfo, init_api->pAppidConfig);
330 }
331
332 return 0;
333 }
334
335 static int ExtractVersion(ClientSMTPData * const fd, const uint8_t *product,
336 const uint8_t *data, tAppIdData *flowp, SFSnortPacket *pkt, const int dir, const tAppIdConfig *pConfig)
337 {
338 const u_int8_t *p;
339 u_int8_t *v;
340 u_int8_t *v_end;
341 unsigned len;
342 unsigned sublen;
343
344 v_end = fd->version;
345 v_end += MAX_VERSION_SIZE - 1;
346 len = data - product;
347 if (len >= sizeof(MICROSOFT) && memcmp(product, MICROSOFT, sizeof(MICROSOFT)-1) == 0)
348 {
349 p = product + sizeof(MICROSOFT) - 1;
350
351 if (*p == '-' || isspace(*p)) p++;
352 else return 1;
353
354 if (data-p >= (int)sizeof(MAC) && memcmp(p, MAC, sizeof(MAC)-1) == 0)
355 p += sizeof(MAC) - 1;
356
357 if (data-p >= (int)sizeof(OUTLOOK) && memcmp(p, OUTLOOK, sizeof(OUTLOOK)-1) == 0)
358 {
359 p += sizeof(OUTLOOK) - 1;
360
361 if (*p == ',' || *p == '/' || isspace(*p))
362 {
363 p++;
364
365 if (data-p >= (int)sizeof(EXPRESS) && memcmp(p, EXPRESS, sizeof(EXPRESS)-1) == 0)
366 {
367 p += sizeof(EXPRESS) - 1;
368 if (p >= data || isspace(*p)) return 1;
369 for (v=fd->version; v<v_end && p < data; v++,p++)
370 {
371 *v = *p;
372 }
373 *v = 0;
374 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_OUTLOOK_EXPRESS, (char *)fd->version);
375 return 0;
376 }
377 else if (data-p >= (int)sizeof(IMO) && memcmp(p, IMO, sizeof(IMO)-1) == 0)
378 {
379 p += sizeof(IMO) - 1;
380 if (p >= data || isspace(*p)) return 1;
381 for (v=fd->version; v<v_end && p < data; v++,p++)
382 {
383 *v = *p;
384 }
385 *v = 0;
386 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_SMTP_IMO, (char *)fd->version);
387 return 0;
388 }
389 else
390 {
391 if (p >= data || isspace(*p)) return 1;
392 for (v=fd->version; v<v_end && p < data; v++,p++)
393 {
394 *v = *p;
395 }
396 *v = 0;
397 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_OUTLOOK, (char *)fd->version);
398 return 0;
399 }
400 }
401 }
402 }
403 else if (len >= sizeof(APP_SMTP_EVOLUTION) && memcmp(product, APP_SMTP_EVOLUTION, sizeof(APP_SMTP_EVOLUTION)-1) == 0)
404 {
405 p = product + sizeof(APP_SMTP_EVOLUTION) - 1;
406 if (p >= data || isspace(*p)) return 1;
407 for (v=fd->version; v<v_end && p < data; v++,p++)
408 {
409 *v = *p;
410 }
411 *v = 0;
412 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_EVOLUTION, (char *)fd->version);
413 return 0;
414 }
415 else if (len >= sizeof(APP_SMTP_LOTUSNOTES) && memcmp(product, APP_SMTP_LOTUSNOTES, sizeof(APP_SMTP_LOTUSNOTES)-1) == 0)
416 {
417 p = product + sizeof(APP_SMTP_LOTUSNOTES) - 1;
418 if (p >= data || isspace(*p)) return 1;
419 for (v=fd->version; v<v_end && p < data; v++,p++)
420 {
421 *v = *p;
422 }
423 *v = 0;
424 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_LOTUS_NOTES, (char *)fd->version);
425 return 0;
426 }
427 else if (len >= sizeof(APP_SMTP_APPLEMAIL) && memcmp(product, APP_SMTP_APPLEMAIL, sizeof(APP_SMTP_APPLEMAIL)-1) == 0)
428 {
429 p = product + sizeof(APP_SMTP_APPLEMAIL) - 1;
430 if (p >= data || *(data - 1) != ')' || *p == ')' || isspace(*p)) return 1;
431 for (v=fd->version; v<v_end && p < data-1; v++,p++)
432 {
433 *v = *p;
434 }
435 *v = 0;
436 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_APPLE_EMAIL, (char *)fd->version);
437 return 0;
438 }
439 else if (len >= sizeof(APP_SMTP_EUDORA) && memcmp(product, APP_SMTP_EUDORA, sizeof(APP_SMTP_EUDORA)-1) == 0)
440 {
441 p = product + sizeof(APP_SMTP_EUDORA) - 1;
442 if (p >= data || isspace(*p)) return 1;
443 for (v=fd->version; v<v_end && p < data; v++,p++)
444 {
445 *v = *p;
446 }
447 *v = 0;
448 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_EUDORA, (char *)fd->version);
449 return 0;
450 }
451 else if (len >= sizeof(APP_SMTP_EUDORAPRO) && memcmp(product, APP_SMTP_EUDORAPRO, sizeof(APP_SMTP_EUDORAPRO)-1) == 0)
452 {
453 p = product + sizeof(APP_SMTP_EUDORAPRO) - 1;
454 if (p >= data || isspace(*p)) return 1;
455 for (v=fd->version; v<v_end && p < data; v++,p++)
456 {
457 *v = *p;
458 }
459 *v = 0;
460 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_EUDORA_PRO, (char *)fd->version);
461 return 0;
462 }
463 else if (len >= sizeof(APP_SMTP_AOL) && memcmp(product, APP_SMTP_AOL, sizeof(APP_SMTP_AOL)-1) == 0)
464 {
465 p = product + sizeof(APP_SMTP_AOL) - 1;
466 if (p >= data || isspace(*p)) return 1;
467 for (v=fd->version; v<v_end && p < data; v++,p++)
468 {
469 *v = *p;
470 }
471 *v = 0;
472 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_AOL_EMAIL, (char *)fd->version);
473 return 0;
474 }
475 else if (len >= sizeof(APP_SMTP_MUTT) && memcmp(product, APP_SMTP_MUTT, sizeof(APP_SMTP_MUTT)-1) == 0)
476 {
477 p = product + sizeof(APP_SMTP_MUTT) - 1;
478 if (p >= data || isspace(*p)) return 1;
479 for (v=fd->version; v<v_end && p < data; v++,p++)
480 {
481 *v = *p;
482 }
483 *v = 0;
484 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_MUTT, (char *)fd->version);
485 return 0;
486 }
487 else if (len >= sizeof(APP_SMTP_KMAIL) && memcmp(product, APP_SMTP_KMAIL, sizeof(APP_SMTP_KMAIL)-1) == 0)
488 {
489 p = product + sizeof(APP_SMTP_KMAIL) - 1;
490 if (p >= data || isspace(*p)) return 1;
491 for (v=fd->version; v<v_end && p < data; v++,p++)
492 {
493 *v = *p;
494 }
495 *v = 0;
496 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_SMTP/*KMAIL_ID*/, (char *)fd->version);
497 return 0;
498 }
499 else if (len >= sizeof(APP_SMTP_THUNDERBIRD) && memcmp(product, APP_SMTP_THUNDERBIRD, sizeof(APP_SMTP_THUNDERBIRD)-1) == 0)
500 {
501 p = product + sizeof(APP_SMTP_THUNDERBIRD) - 1;
502 if (p >= data || isspace(*p)) return 1;
503 for (v=fd->version; v<v_end && p < data; v++,p++)
504 {
505 *v = *p;
506 }
507 *v = 0;
508 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_THUNDERBIRD, (char *)fd->version);
509 return 0;
510 }
511 else if (len >= sizeof(APP_SMTP_MTHUNDERBIRD) && memcmp(product, APP_SMTP_MTHUNDERBIRD, sizeof(APP_SMTP_MTHUNDERBIRD)-1) == 0)
512 {
513 p = product + sizeof(APP_SMTP_MTHUNDERBIRD) - 1;
514 if (p >= data || isspace(*p)) return 1;
515 for (v=fd->version; v<v_end && p < data; v++,p++)
516 {
517 *v = *p;
518 }
519 *v = 0;
520 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_THUNDERBIRD, (char *)fd->version);
521 return 0;
522 }
523 else if (len >= sizeof(APP_SMTP_MOZILLA) && memcmp(product, APP_SMTP_MOZILLA, sizeof(APP_SMTP_MOZILLA)-1) == 0)
524 {
525 for (p = product + sizeof(APP_SMTP_MOZILLA) - 1; p < data; p++)
526 {
527 if (*p == 'T')
528 {
529 sublen = data - p;
530 if (sublen >= sizeof(APP_SMTP_THUNDERBIRD_SHORT) && memcmp(p, APP_SMTP_THUNDERBIRD_SHORT, sizeof(APP_SMTP_THUNDERBIRD_SHORT)-1) == 0)
531 {
532 p = p + sizeof(APP_SMTP_THUNDERBIRD_SHORT) - 1;
533 for (v=fd->version; v<v_end && p < data; p++)
534 {
535 if (*p == 0x0A || *p == 0x0D || !isprint(*p)) break;
536 *v = *p;
537 v++;
538 }
539 *v = 0;
540 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_THUNDERBIRD, (char *)fd->version);
541 return 0;
542 }
543 }
544 }
545 }
546
547 return 1;
548 }
549 static void smtp_free_state(void *data)
550 {
551 SMTPDetectorData *dd = (SMTPDetectorData *)data;
552 ClientSMTPData *cd;
553
554 if (dd)
555 {
556 cd = &dd->client;
557 if (cd->headerline)
558 free(cd->headerline);
559 free(dd);
560 }
561 }
562 static inline SMTPDetectorData *smtp_get_SMTPDetectorData(tAppIdData *flowp)
563 {
564 SMTPDetectorData *dd = smtp_detector_mod.api->data_get(flowp, smtp_detector_mod.flow_data_index);
565 if (dd)
566 return dd;
567
568 if ((dd = calloc(1, sizeof(*dd))) == NULL)
569 return NULL;
570 if (smtp_detector_mod.api->data_add(flowp, dd, smtp_detector_mod.flow_data_index, &smtp_free_state))
571 {
572 free(dd);
573 return NULL;
574 }
575 dd->server.state = SMTP_SERVICE_STATE_CONNECTION;
576 dd->client.state = SMTP_CLIENT_STATE_HELO;
577 dd->need_continue = 1;
578 setAppIdFlag(flowp, APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
579 return dd;
580 }
581
582 // #define UNIT_TEST_SKIP
583 static CLIENT_APP_RETCODE smtp_ca_validate(const uint8_t *data, uint16_t size, const int dir,
584 tAppIdData *flowp, SFSnortPacket *pkt, struct _Detector *userData,
585 const struct appIdConfig_ *pConfig)
586 {
587 SMTPDetectorData *dd;
588 ClientSMTPData *fd;
589 const uint8_t *end;
590 unsigned len;
591 int line_break = 0;
592 SMTPServiceState serviceState;
593 #ifdef UNIT_TESTING
594 SMTPClientState currState = SMTP_CLIENT_STATE_NONE;
595 #endif
596
597 #ifdef APP_ID_USES_REASSEMBLED
598 smtp_detector_mod.streamAPI->response_flush_stream(pkt);
599 #endif
600 if ((dd = smtp_get_SMTPDetectorData(flowp)) == NULL)
601 return CLIENT_APP_ENOMEM;
602
603 if (dir != APP_ID_FROM_INITIATOR)
604 return CLIENT_APP_INPROCESS;
605
606 fd = &dd->client;
607
608 if (getAppIdFlag(flowp, APPID_SESSION_ENCRYPTED | APPID_SESSION_DECRYPTED) == APPID_SESSION_ENCRYPTED)
609 {
610 if ((fd->flags & CLIENT_FLAG_STARTTLS_SUCCESS))
611 {
612 fd->decryption_countdown--;
613 if (!fd->decryption_countdown)
614 #ifdef UNIT_TEST_SKIP
615 if (flowp->session_packet_count == 0)
616 #endif
617 {
618 /* Because we can't see any further info without decryption we settle for
619 plain APP_ID_SMTPS instead of perhaps finding data that would make calling
620 ExtractVersion() worthwhile, So set the appid and call it good. */
621 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTPS, APP_ID_SMTPS, NULL);
622 goto done;
623 }
624 }
625 return CLIENT_APP_INPROCESS;
626 }
627
628
629 for (end = data + size; data < end; data++)
630 {
631 #ifdef UNIT_TESTING
632 if (app_id_debug_session_flag && currState != fd->state)
633 {
634 DEBUG_WRAP(DebugMessage(DEBUG_APPID, "AppIdDbg %s SMTP client state %s\n", app_id_debug_session, stateName[fd->state]););
635 currState = fd->state;
636 }
637 #endif
638 len = end - data;
639 switch (fd->state)
640 {
641 case SMTP_CLIENT_STATE_HELO:
642 if (len >= (sizeof(HELO)-1) && strncasecmp((const char *)data, HELO, sizeof(HELO)-1) == 0)
643 {
644 data += (sizeof(HELO)-1)-1;
645 fd->nextstate = SMTP_CLIENT_STATE_MAIL_FROM;
646 fd->state = SMTP_CLIENT_STATE_SKIP_SPACE;
647 fd->flags &= ~ CLIENT_FLAG_STARTTLS_SUCCESS;
648 }
649 else if (len >= (sizeof(EHLO)-1) && strncasecmp((const char *)data, EHLO, sizeof(EHLO)-1) == 0)
650 {
651 data += (sizeof(EHLO)-1)-1;
652 fd->nextstate = SMTP_CLIENT_STATE_MAIL_FROM;
653 fd->state = SMTP_CLIENT_STATE_SKIP_SPACE;
654 fd->flags &= ~ CLIENT_FLAG_STARTTLS_SUCCESS;
655 }
656 else goto done;
657 break;
658
659 case SMTP_CLIENT_STATE_MAIL_FROM:
660 serviceState = dd->server.state;
661 if (len >= (sizeof(MAILFROM)-1) && strncasecmp((const char *)data, MAILFROM, sizeof(MAILFROM)-1) == 0)
662 {
663 data += (sizeof(MAILFROM)-1)-1;
664 fd->nextstate = SMTP_CLIENT_STATE_RCPT_TO;
665 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
666 }
667 else if (len >= (sizeof(RSET)-1) && strncasecmp((const char *)data, RSET, sizeof(RSET)-1) == 0)
668 {
669 data += (sizeof(RSET)-1)-1;
670 fd->nextstate = fd->state;
671 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
672 }
673 else if (len >= (sizeof(AUTH_PLAIN)-1) && strncasecmp((const char *)data, AUTH_PLAIN, sizeof(AUTH_PLAIN)-1) == 0)
674 {
675 data += (sizeof(AUTH_PLAIN)-1)-1;
676 fd->nextstate = fd->state;
677 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
678 }
679 else if (len >= (sizeof(AUTH_LOGIN)-1) && strncasecmp((const char *)data, AUTH_LOGIN, sizeof(AUTH_LOGIN)-1) == 0)
680 {
681 data += (sizeof(AUTH_LOGIN)-1)-1;
682 fd->nextstate = SMTP_CLIENT_STATE_LOGIN_USER;
683 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
684 }
685 else if (len >= (sizeof(AUTH)-1) && strncasecmp((const char *)data, AUTH, sizeof(AUTH)-1) == 0)
686 {
687 data += (sizeof(AUTH)-1)-1;
688 fd->nextstate = fd->state;
689 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
690 }
691 else if (len >= (sizeof(STARTTLS)-1) && strncasecmp((const char *)data, STARTTLS, sizeof(STARTTLS)-1) == 0)
692 {
693 data += (sizeof(STARTTLS)-1)-1;
694 serviceState = dd->server.state = SMTP_SERVICE_STATE_STARTTLS;
695 fd->nextstate = fd->state;
696 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
697 }
698 /* check for state reversion */
699 else if (len >= (sizeof(HELO)-1) && strncasecmp((const char *)data, HELO, sizeof(HELO)-1) == 0)
700 {
701 data += (sizeof(HELO)-1)-1;
702 fd->nextstate = fd->state;
703 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
704 dd->server.state = SMTP_SERVICE_STATE_HELO; // make sure that service side expects the 250
705 }
706 else if (len >= (sizeof(EHLO)-1) && strncasecmp((const char *)data, EHLO, sizeof(EHLO)-1) == 0)
707 {
708 data += (sizeof(EHLO)-1)-1;
709 fd->nextstate = fd->state;
710 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
711 dd->server.state = SMTP_SERVICE_STATE_HELO; // make sure that service side expects the 250
712 }
713 else goto done;
714 if (serviceState == SMTP_SERVICE_STATE_TRANSFER)
715 {
716 setAppIdFlag(flowp, APPID_SESSION_CONTINUE);
717 smtp_service_mod.api->add_service(flowp, pkt, dir, &svc_element,
718 APP_ID_SMTP, NULL, NULL, NULL, NULL);
719 }
720 break;
721 case SMTP_CLIENT_STATE_LOGIN_USER:
722 {
723 fd->nextstate = SMTP_CLIENT_STATE_LOGIN_PASSWORD;
724 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
725 }
726 break;
727 case SMTP_CLIENT_STATE_LOGIN_PASSWORD:
728 {
729 fd->nextstate = SMTP_CLIENT_STATE_MAIL_FROM;
730 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
731 }
732 break;
733 case SMTP_CLIENT_STATE_RCPT_TO:
734 if (len >= (sizeof(RCPTTO)-1) && strncasecmp((const char *)data, RCPTTO, sizeof(RCPTTO)-1) == 0)
735 {
736 data += (sizeof(RCPTTO)-1)-1;
737 fd->nextstate = SMTP_CLIENT_STATE_DATA;
738 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
739 }
740 else
741 goto done;
742 break;
743
744 case SMTP_CLIENT_STATE_DATA:
745 if (len >= (sizeof(DATA)-1) && strncasecmp((const char *)data, DATA, sizeof(DATA)-1) == 0)
746 {
747 data += (sizeof(DATA)-1)-1;
748 fd->nextstate = SMTP_CLIENT_STATE_MESSAGE;
749 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
750 }
751 else if (len >= (sizeof(RCPTTO)-1) && strncasecmp((const char *)data, RCPTTO, sizeof(RCPTTO)-1) == 0)
752 {
753 data += (sizeof(RCPTTO)-1)-1;
754 fd->nextstate = fd->state;
755 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
756 }
757 break;
758 case SMTP_CLIENT_STATE_MESSAGE:
759 if (*data == '.')
760 {
761 if (len == 0 ||
762 (len >= 1 && data[1] == '\n') ||
763 (len >= 2 && data[1] == '\r' && data[2] == '\n'))
764 {
765 smtp_client_mod.api->add_app(pkt, dir, pConfig, flowp, APP_ID_SMTP, APP_ID_SMTP, NULL);
766 goto done;
767 }
768 }
769 else if (len >= (sizeof(XMAILER)-1) && strncasecmp((const char *)data, XMAILER, sizeof(XMAILER)-1) == 0)
770 {
771 data += (sizeof(XMAILER)-1)-1;
772 fd->state = SMTP_CLIENT_STATE_GET_PRODUCT_VERSION;
773 }
774 else if (len >= (sizeof(USERAGENT)-1) && strncasecmp((const char *)data, USERAGENT, sizeof(USERAGENT)-1) == 0)
775 {
776 data += (sizeof(USERAGENT)-1)-1;
777 fd->state = SMTP_CLIENT_STATE_GET_PRODUCT_VERSION;
778 }
779 else if (!isprint(*data) && *data != '\t')
780 goto done;
781 else
782 {
783 fd->nextstate = fd->state;
784 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
785 }
786 break;
787
788 case SMTP_CLIENT_STATE_GET_PRODUCT_VERSION:
789 if (!fd->headerline)
790 {
791 if (!(fd->headerline = malloc(MAX_HEADER_LINE_SIZE)))
792 goto done;
793 }
794 while((data < end) && (fd->pos < (MAX_HEADER_LINE_SIZE-1)))
795 {
796 if ((*data == ' ') || (*data == '\t'))
797 {
798 line_break = 0;
799 fd->headerline[fd->pos++] = *data;
800 }
801 else if((*data == '\n') && (line_break != 1))
802 {
803 /* Can't have multiple LFs in a row, but if we get one it
804 * needs to be followed by at least one space */
805 line_break = 1;
806 }
807 else if(*data == '\r')
808 {
809 // CR needs to be followed by LF and can't start a line
810 line_break = 2;
811 }
812 else if (!isprint(*data))
813 {
814 free(fd->headerline);
815 fd->headerline = NULL;
816 fd->pos = 0;
817 goto done;
818 }
819 else if(!line_break)
820 {
821 fd->headerline[fd->pos++] = *data;
822 }
823 else
824 {
825 // We have reached the end of the header
826 break;
827 }
828 data++;
829 }
830 data--;
831 if (line_break || fd->pos >= (MAX_HEADER_LINE_SIZE-1))
832 {
833 ExtractVersion(fd, fd->headerline, fd->headerline + fd->pos, flowp, pkt, dir, pConfig);
834 free(fd->headerline);
835 fd->headerline = NULL;
836 fd->pos = 0;
837 goto done;
838 }
839 break;
840
841 case SMTP_CLIENT_STATE_SKIP_SPACE:
842 if (*data == ' ')
843 {
844 fd->state = SMTP_CLIENT_STATE_SKIP_LINE;
845 }
846 else if (*data == '\n')
847 {
848 fd->pos = 0;
849 fd->state = fd->nextstate;
850 fd->nextstate = SMTP_CLIENT_STATE_NONE;
851 }
852 else if (*data == '\r')
853 fd->state = SMTP_CLIENT_STATE_SKIP_EOL;
854 else
855 goto done;
856 break;
857
858 case SMTP_CLIENT_STATE_SKIP_EOL:
859 if (*data == '\n')
860 {
861 fd->pos = 0;
862 fd->state = fd->nextstate;
863 fd->nextstate = SMTP_CLIENT_STATE_NONE;
864 }
865 else
866 goto done;
867 break;
868
869 case SMTP_CLIENT_STATE_SKIP_LINE:
870 if (*data == '\n')
871 {
872 fd->pos = 0;
873 fd->state = fd->nextstate;
874 fd->nextstate = SMTP_CLIENT_STATE_NONE;
875 }
876 else if (!(*data == '\r' || isprint(*data)))
877 goto done;
878 break;
879
880 default:
881 goto done;
882 }
883 }
884 return CLIENT_APP_INPROCESS;
885
886 done:
887 dd->need_continue = 0;
888 if (getAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED))
889 clearAppIdFlag(flowp, APPID_SESSION_CONTINUE | APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
890 else
891 clearAppIdFlag(flowp, APPID_SESSION_CLIENT_GETS_SERVER_PACKETS);
892 setAppIdFlag(flowp, APPID_SESSION_CLIENT_DETECTED);
893 return CLIENT_APP_SUCCESS;
894 }
895
896 static inline int smtp_validate_reply(const uint8_t *data, uint16_t *offset,
897 uint16_t size, int *multi, int *code)
898 {
899 const ServiceSMTPCode *code_hdr;
900 int tmp;
901
902 /* Trim any blank lines (be a little tolerant) */
903 for (; *offset<size; (*offset)++)
904 {
905 if (data[*offset] != 0x0D && data[*offset] != 0x0A) break;
906 }
907
908 if (size - *offset < (int)sizeof(ServiceSMTPCode))
909 {
910 for (; *offset<size; (*offset)++)
911 {
912 if (!isspace(data[*offset])) return -1;
913 }
914 return 0;
915 }
916
917 code_hdr = (ServiceSMTPCode *)(data + *offset);
918
919 if (code_hdr->code[0] < '1' || code_hdr->code[0] > '5') return -1;
920 tmp = (code_hdr->code[0] - '0') * 100;
921
922 if (code_hdr->code[1] < '0' || code_hdr->code[1] > '5') return -1;
923 tmp += (code_hdr->code[1] - '0') * 10;
924
925 if (!isdigit(code_hdr->code[2])) return -1;
926 tmp += code_hdr->code[2] - '0';
927
928 if (*multi && tmp != *code) return -1;
929 *code = tmp;
930 if (code_hdr->sp == '-') *multi = 1;
931 else if (code_hdr->sp == ' ') *multi = 0;
932 else return -1;
933
934 /* We have a valid code, now we need to see if the rest of the line
935 is okay */
936
937 *offset += sizeof(ServiceSMTPCode);
938 for (; *offset < size; (*offset)++)
939 {
940 if (data[*offset] == 0x0D)
941 {
942 (*offset)++;
943 if (*offset >= size) return -1;
944 if (data[*offset] != 0x0A) return -1;
945 }
946 if (data[*offset] == 0x0A)
947 {
948 if (*multi)
949 {
950 if ((*offset + 1) >= size) return 0;
951
952 if (size - (*offset + 1) < (int)sizeof(ServiceSMTPCode)) return -1;
953
954 code_hdr = (ServiceSMTPCode *)(data + *offset + 1);
955
956 if (code_hdr->code[0] < '1' || code_hdr->code[0] > '5')
957 return -1;
958 tmp = (code_hdr->code[0] - '0') * 100;
959
960 if (code_hdr->code[1] < '1' || code_hdr->code[1] > '5')
961 return -1;
962 tmp += (code_hdr->code[1] - '0') * 10;
963
964 if (!isdigit(code_hdr->code[2])) return -1;
965 tmp += code_hdr->code[2] - '0';
966
967 if (tmp != *code) return -1;
968
969 if (code_hdr->sp == ' ') *multi = 0;
970 else if (code_hdr->sp != '-') return -1;
971
972 *offset += sizeof(ServiceSMTPCode);
973 }
974 else
975 {
976 (*offset)++;
977 return *code;
978 }
979 }
980 else if (!isprint(data[*offset])) return -1;
981 }
982
983
984 return 0;
985 }
986
987 static int smtp_svc_validate(ServiceValidationArgs* args)
988 {
989 SMTPDetectorData *dd;
990 ServiceSMTPData *fd;
991 tAppIdData *flowp = args->flowp;
992 const uint8_t *data = args->data;
993 uint16_t size = args->size;
994 uint16_t offset;
995
996 #ifdef APP_ID_USES_REASSEMBLED
997 pop3_detector_mod.streamAPI->response_flush_stream(pkt);
998 #endif
999
1000 if ((dd = smtp_get_SMTPDetectorData(flowp)) == NULL)
1001 return SERVICE_ENOMEM;
1002
1003 if (!size)
1004 goto inprocess;
1005
1006 if (getAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED))
1007 {
1008 if (!dd->need_continue)
1009 clearAppIdFlag(flowp, APPID_SESSION_CONTINUE);
1010 return SERVICE_SUCCESS; // client made the decision so we are totally done
1011 }
1012
1013 fd = &dd->server;
1014
1015 if (args->dir != APP_ID_FROM_RESPONDER)
1016 {
1017 if (SMTP_SERVICE_STATE_HELO == fd->state)
1018 {
1019 if (!((size >= (sizeof(HELO)-1) && strncasecmp((const char *)data, HELO, sizeof(HELO)-1) == 0) ||
1020 (size >= (sizeof(EHLO)-1) && strncasecmp((const char *)data, EHLO, sizeof(EHLO)-1) == 0)))
1021 {
1022 fd->state = SMTP_SERVICE_STATE_BAD_CLIENT;
1023 }
1024 }
1025 goto inprocess;
1026 }
1027
1028 offset = 0;
1029 while (offset < size)
1030 {
1031 if (smtp_validate_reply(data, &offset, size, &fd->multiline, &fd->code) < 0)
1032 {
1033 if (!(dd->client.flags & CLIENT_FLAG_STARTTLS_SUCCESS))
1034 goto fail;
1035 goto inprocess;
1036 }
1037 if (!fd->code) goto inprocess;
1038 switch (fd->state)
1039 {
1040 case SMTP_SERVICE_STATE_CONNECTION:
1041 switch (fd->code)
1042 {
1043 case 220:
1044 fd->state = SMTP_SERVICE_STATE_HELO;
1045 break;
1046 case 421:
1047 if (service_strstr(data, size, (const uint8_t *)SMTP_CLOSING_CONN, sizeof(SMTP_CLOSING_CONN)-1))
1048 goto success;
1049 goto fail;
1050 case 554:
1051 goto success;
1052 default:
1053 goto fail;
1054 }
1055 break;
1056 case SMTP_SERVICE_STATE_HELO:
1057 switch (fd->code)
1058 {
1059 case 250:
1060 fd->state = SMTP_SERVICE_STATE_TRANSFER;
1061 break;
1062 case 220:
1063 case 500:
1064 case 501:
1065 case 502:
1066 case 504:
1067 break;
1068 case 421:
1069 case 553:
1070 fd->state = SMTP_SERVICE_STATE_CONNECTION_ERROR;
1071 break;
1072 default:
1073 goto fail;
1074 }
1075 break;
1076 case SMTP_SERVICE_STATE_STARTTLS:
1077 // success or fail, return client to connection-complete state.
1078 dd->client.state = SMTP_CLIENT_STATE_HELO;
1079 fd->state = SMTP_SERVICE_STATE_HELO;
1080 if (fd->code == 220)
1081 {
1082 dd->client.flags |= CLIENT_FLAG_STARTTLS_SUCCESS;
1083 if (_dpd.isSSLPolicyEnabled(NULL))
1084 dd->client.decryption_countdown = SSL_WAIT_PACKETS; // max wait if decryption fails (e.g., cert error)
1085 else
1086 dd->client.decryption_countdown = 1; // no wait for decryption
1087 smtp_service_mod.api->add_service(flowp, args->pkt, args->dir, &svc_element,
1088 APP_ID_SMTPS, NULL, NULL, NULL, NULL);
1089 if (dd->need_continue > 0)
1090 setAppIdFlag(flowp, APPID_SESSION_ENCRYPTED | APPID_SESSION_STICKY_SERVICE | APPID_SESSION_CONTINUE);
1091 else
1092 setAppIdFlag(flowp, APPID_SESSION_ENCRYPTED | APPID_SESSION_STICKY_SERVICE);
1093 return SERVICE_SUCCESS;
1094 }
1095 /* STARTTLS failed. Fall through and call this SMTP */
1096 case SMTP_SERVICE_STATE_TRANSFER:
1097 goto success;
1098 case SMTP_SERVICE_STATE_BAD_CLIENT:
1099 switch (fd->code)
1100 {
1101 case 500:
1102 case 501:
1103 case 502:
1104 case 550:
1105 goto not_compatible;
1106 }
1107 case SMTP_SERVICE_STATE_CONNECTION_ERROR:
1108 default:
1109 goto fail;
1110 }
1111 }
1112
1113 inprocess:
1114 smtp_service_mod.api->service_inprocess(flowp, args->pkt, args->dir, &svc_element, NULL);
1115 return SERVICE_INPROCESS;
1116
1117 success:
1118 if (dd->need_continue > 0)
1119 setAppIdFlag(flowp, APPID_SESSION_CONTINUE);
1120
1121 smtp_service_mod.api->add_service(flowp, args->pkt, args->dir, &svc_element,
1122 APP_ID_SMTP, NULL, NULL, NULL, NULL);
1123 return SERVICE_SUCCESS;
1124
1125 fail:
1126 smtp_service_mod.api->fail_service(flowp, args->pkt, args->dir, &svc_element,
1127 smtp_service_mod.flow_data_index, args->pConfig, NULL);
1128 return SERVICE_NOMATCH;
1129
1130 not_compatible:
1131 smtp_service_mod.api->incompatible_data(flowp, args->pkt, args->dir, &svc_element,
1132 smtp_service_mod.flow_data_index, args->pConfig, NULL);
1133 return SERVICE_NOT_COMPATIBLE;
1134 }