if (asd.get_session_flags(APPID_SESSION_REXEC_STDERR))
{
ServiceDiscovery::get_instance().identify_service(asd, p, direction, change_bits);
- AppIdDnsSession* dsession = asd.get_dns_session();
- if (asd.service.get_id() == APP_ID_DNS &&
- asd.config->mod_config->dns_host_reporting && dsession->get_host() )
+ if (asd.get_session_flags(APPID_SESSION_SERVICE_DETECTED |
+ APPID_SESSION_CONTINUE) == APPID_SESSION_SERVICE_DETECTED)
{
- dns_host_scan_hostname((const uint8_t*)dsession->get_host(), dsession->get_host_len(),
- &client_id, &payload_id);
- asd.set_client_appid_data(client_id, change_bits);
+ asd.service_disco_state = APPID_DISCO_STATE_FINISHED;
+ if ( asd.payload.get_id() == APP_ID_NONE)
+ asd.payload.set_id(APP_ID_UNKNOWN);
}
- else if (asd.service.get_id() == APP_ID_RTMP)
- asd.examine_rtmp_metadata(change_bits);
- else if (asd.get_session_flags(APPID_SESSION_SSL_SESSION) && asd.tsession)
- asd.examine_ssl_metadata(p, change_bits);
}
// FIXIT-M - snort 2.x has added a check for midstream pickup to this, do we need that?
else if (protocol != IpProtocol::TCP || (p->packet_flags & PKT_STREAM_ORDER_OK))
#include "service_rexec.h"
+#include "appid_debug.h"
#include "appid_inspector.h"
#include "app_info_table.h"
#include "protocols/packet.h"
REXEC_STATE_COMMAND,
REXEC_STATE_REPLY,
REXEC_STATE_DONE,
+ REXEC_STATE_BAIL,
REXEC_STATE_STDERR_CONNECT_SYN,
- REXEC_STATE_STDERR_CONNECT_SYN_ACK
+ REXEC_STATE_STDERR_CONNECT_SYN_ACK,
+ REXEC_STATE_STDERR_WAIT,
+ REXEC_STATE_STDERR_DONE
};
struct ServiceREXECData
};
static const uint64_t REXEC_EXPECTED_SESSION_FLAGS = APPID_SESSION_CONTINUE |
- APPID_SESSION_REXEC_STDERR | APPID_SESSION_NO_TPI | APPID_SESSION_SERVICE_DETECTED |
- APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_PORT_SERVICE_DONE;
+ APPID_SESSION_REXEC_STDERR | APPID_SESSION_NO_TPI | APPID_SESSION_NOT_A_SERVICE |
+ APPID_SESSION_PORT_SERVICE_DONE;
RexecServiceDetector::RexecServiceDetector(ServiceDiscovery* sd)
{
}
}
+void RexecServiceDetector::rexec_bail(ServiceREXECData* rd)
+{
+ if (!rd)
+ return;
+ rd->state = REXEC_STATE_BAIL;
+ if(rd->child)
+ rd->child->state = REXEC_STATE_BAIL;
+
+ if(rd->parent)
+ rd->parent->state = REXEC_STATE_BAIL;
+}
+
int RexecServiceDetector::validate(AppIdDiscoveryArgs& args)
{
int i = 0;
data_add(args.asd, rd, &rexec_free_state);
rd->state = REXEC_STATE_PORT;
}
+ if (appidDebug->is_active())
+ LogMessage("AppIdDbg %s rexec state %d\n", appidDebug->get_debug_session(), rd->state);
switch (rd->state)
{
tmp_rd->parent = nullptr;
return APPID_ENULL;
}
- rd->child = tmp_rd;
- rd->state = REXEC_STATE_SERVER_CONNECT;
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
pf->scan_flags |= SCAN_HOST_PORT_FLAG;
initialize_expected_session(args.asd, *pf, REXEC_EXPECTED_SESSION_FLAGS, APP_ID_FROM_RESPONDER);
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
+ rd->child = tmp_rd;
+ rd->state = REXEC_STATE_SERVER_CONNECT;
+ args.asd.set_session_flags(APPID_SESSION_CONTINUE);
+ goto success;
}
else
rd->state = REXEC_STATE_USERNAME;
goto fail;
if (size != 1)
goto fail;
+ if (rd->child)
+ {
+ if(rd->child->state == REXEC_STATE_STDERR_WAIT)
+ rd->child->state = REXEC_STATE_STDERR_DONE;
+ else
+ goto fail;
+ }
+ args.asd.clear_session_flags(APPID_SESSION_CONTINUE);
goto success;
- break;
case REXEC_STATE_STDERR_CONNECT_SYN:
rd->state = REXEC_STATE_STDERR_CONNECT_SYN_ACK;
break;
if (rd->parent && rd->parent->state == REXEC_STATE_SERVER_CONNECT)
{
rd->parent->state = REXEC_STATE_USERNAME;
- args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR);
+ rd->state = REXEC_STATE_STDERR_WAIT;
+ break;
}
goto bail;
+ case REXEC_STATE_STDERR_WAIT:
+ if(!size)
+ break;
+ goto bail;
+ case REXEC_STATE_STDERR_DONE:
+ args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR | APPID_SESSION_CONTINUE);
+ goto success;
+ case REXEC_STATE_BAIL:
default:
goto bail;
}
inprocess:
- if (!args.asd.is_service_detected())
- service_inprocess(args.asd, args.pkt, args.dir);
+ service_inprocess(args.asd, args.pkt, args.dir);
return APPID_INPROCESS;
success:
- if (!args.asd.is_service_detected())
- return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_EXEC);
+ return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_EXEC);
bail:
- if (!args.asd.is_service_detected())
- incompatible_data(args.asd, args.pkt, args.dir);
- args.asd.clear_session_flags(APPID_SESSION_CONTINUE);
+ args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR);
+ rexec_bail(rd);
+ incompatible_data(args.asd, args.pkt, args.dir);
+ args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR);
return APPID_NOT_COMPATIBLE;
fail:
- if (!args.asd.is_service_detected())
- fail_service(args.asd, args.pkt, args.dir);
- args.asd.clear_session_flags(APPID_SESSION_CONTINUE);
+ args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR);
+ rexec_bail(rd);
+ fail_service(args.asd, args.pkt, args.dir);
return APPID_NOMATCH;
}
#include "service_detector.h"
class ServiceDiscovery;
+struct ServiceREXECData;
class RexecServiceDetector : public ServiceDetector
{
RexecServiceDetector(ServiceDiscovery*);
int validate(AppIdDiscoveryArgs&) override;
+private:
+ void rexec_bail(ServiceREXECData* rd);
};
#endif
RSHELL_STATE_COMMAND,
RSHELL_STATE_REPLY,
RSHELL_STATE_DONE,
+ RSHELL_STATE_BAIL,
RSHELL_STATE_STDERR_CONNECT_SYN,
- RSHELL_STATE_STDERR_CONNECT_SYN_ACK
+ RSHELL_STATE_STDERR_CONNECT_SYN_ACK,
+ RSHELL_STATE_STDERR_WAIT,
+ RSHELL_STATE_STDERR_DONE
};
struct ServiceRSHELLData
}
}
+void RshellServiceDetector::rshell_bail(ServiceRSHELLData* rd)
+{
+ if (!rd)
+ return;
+ rd->state = RSHELL_STATE_BAIL;
+ if(rd->child)
+ rd->child->state = RSHELL_STATE_BAIL;
+ if(rd->parent)
+ rd->parent->state = RSHELL_STATE_BAIL;
+}
+
int RshellServiceDetector::validate(AppIdDiscoveryArgs& args)
{
int i = 0;
if(rsh_error_snort_protocol_id == UNKNOWN_PROTOCOL_ID)
rsh_error_snort_protocol_id = SnortConfig::get_conf()->proto_ref->find("rsh-error");
- ServiceRSHELLData* tmp_rd = (ServiceRSHELLData*)snort_calloc(
- sizeof(ServiceRSHELLData));
- tmp_rd->state = RSHELL_STATE_STDERR_CONNECT_SYN;
- tmp_rd->parent = rd;
const SfIp* dip = args.pkt->ptrs.ip_api.get_dst();
const SfIp* sip = args.pkt->ptrs.ip_api.get_src();
AppIdSession* pf = AppIdSession::create_future_session(args.pkt, dip, 0, sip,
(uint16_t)port, IpProtocol::TCP, rsh_error_snort_protocol_id, APPID_EARLY_SESSION_FLAG_FW_RULE);
if (pf)
{
+ ServiceRSHELLData* tmp_rd = (ServiceRSHELLData*)snort_calloc(
+ sizeof(ServiceRSHELLData));
+ tmp_rd->state = RSHELL_STATE_STDERR_CONNECT_SYN;
+ tmp_rd->parent = rd;
pf->client_disco_state = APPID_DISCO_STATE_FINISHED;
data_add(*pf, tmp_rd, &rshell_free_state);
if (pf->add_flow_data_id((uint16_t)port, this))
pf->scan_flags |= SCAN_HOST_PORT_FLAG;
initialize_expected_session(args.asd, *pf,
APPID_SESSION_CONTINUE | APPID_SESSION_REXEC_STDERR | APPID_SESSION_NO_TPI |
- APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_NOT_A_SERVICE |
- APPID_SESSION_PORT_SERVICE_DONE, APP_ID_FROM_RESPONDER);
+ APPID_SESSION_NOT_A_SERVICE | APPID_SESSION_PORT_SERVICE_DONE,
+ APP_ID_FROM_RESPONDER);
pf->service_disco_state = APPID_DISCO_STATE_STATEFUL;
+ rd->child = tmp_rd;
+ rd->state = RSHELL_STATE_SERVER_CONNECT;
+ args.asd.set_session_flags(APPID_SESSION_CONTINUE);
+ goto success;
}
else
- {
- snort_free(tmp_rd);
- return APPID_ENOMEM;
- }
- rd->child = tmp_rd;
- rd->state = RSHELL_STATE_SERVER_CONNECT;
+ rd->state = RSHELL_STATE_USERNAME;
}
else
rd->state = RSHELL_STATE_USERNAME;
goto inprocess;
if (args.dir != APP_ID_FROM_RESPONDER)
goto fail;
- if (size == 1)
- goto success;
- if (*data == 0x01)
+ if (size == 1 || *data == 0x01)
{
- data++;
- size--;
- for (i=0; i<size && data[i]; i++)
+ if(size !=1)
{
- if (!isprint(data[i]) && data[i] != 0x0A && data[i] != 0x0D && data[i] != 0x09)
- goto fail;
+ data++;
+ size--;
+ for (i=0; i<size && data[i]; i++)
+ {
+ if (!isprint(data[i]) && data[i] != 0x0A && data[i] != 0x0D && data[i] != 0x09)
+ goto fail;
+ }
}
+ if(rd->child)
+ {
+ if(rd->child->state == RSHELL_STATE_STDERR_WAIT)
+ rd->child->state = RSHELL_STATE_STDERR_DONE;
+ else
+ goto fail;
+ }
+ args.asd.clear_session_flags(APPID_SESSION_CONTINUE);
goto success;
}
goto fail;
- break;
case RSHELL_STATE_STDERR_CONNECT_SYN:
rd->state = RSHELL_STATE_STDERR_CONNECT_SYN_ACK;
break;
case RSHELL_STATE_STDERR_CONNECT_SYN_ACK:
if (rd->parent && rd->parent->state == RSHELL_STATE_SERVER_CONNECT)
+ {
rd->parent->state = RSHELL_STATE_USERNAME;
- // FIXIT-M why is this set here and not when add_service is called?
- args.asd.set_service_detected();
- return APPID_SUCCESS;
+ rd->state = RSHELL_STATE_STDERR_WAIT;
+ break;
+ }
+ goto bail;
+ case RSHELL_STATE_STDERR_WAIT:
+ if(!size)
+ break;
+ goto bail;
+ case RSHELL_STATE_STDERR_DONE:
+ args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR | APPID_SESSION_CONTINUE);
+ goto success;
+ case RSHELL_STATE_BAIL:
default:
goto bail;
}
return add_service(args.change_bits, args.asd, args.pkt, args.dir, APP_ID_SHELL);
bail:
+ args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR);
+ rshell_bail(rd);
incompatible_data(args.asd, args.pkt, args.dir);
return APPID_NOT_COMPATIBLE;
fail:
+ args.asd.clear_session_flags(APPID_SESSION_REXEC_STDERR);
+ rshell_bail(rd);
fail_service(args.asd, args.pkt, args.dir);
return APPID_NOMATCH;
}
#include "service_detector.h"
class ServiceDiscovery;
+struct ServiceRSHELLData;
class RshellServiceDetector : public ServiceDetector
{
RshellServiceDetector(ServiceDiscovery*);
int validate(AppIdDiscoveryArgs&) override;
+private:
+ void rshell_bail(ServiceRSHELLData* rd);
};
#endif