using namespace snort;
using namespace std;
+#define USER_LOGIN_SUCCESS 1
+#define USER_LOGIN_FAILURE 2
+
THREAD_LOCAL struct HostTrackerStats host_tracker_stats;
const uint8_t snort::zero_mac[MAC_SIZE] = {0, 0, 0, 0, 0, 0};
available->last_seen = lseen;
available->inferred_appid = false;
available->user[0] = '\0';
+ available->user_login = 0;
+ available->banner_updated = false;
available->visibility = true;
return available;
}
}
bool HostTracker::update_service_user(Port port, IpProtocol proto, const char* user,
- uint32_t lseen, uint16_t max_services)
+ uint32_t lseen, uint16_t max_services, bool success)
{
host_tracker_stats.service_finds++;
bool is_new = false;
{
strncpy(ha->user, user, INFO_SIZE);
ha->user[INFO_SIZE-1] = '\0';
+ ha->user_login = success ? USER_LOGIN_SUCCESS : USER_LOGIN_FAILURE;
+ return true;
+ }
+
+ if ( success )
+ {
+ if ( ha->user_login & USER_LOGIN_SUCCESS )
+ return false;
+ ha->user_login |= USER_LOGIN_SUCCESS;
+ return true;
+ }
+ else
+ {
+ if ( ha->user_login & USER_LOGIN_FAILURE )
+ return false;
+ ha->user_login |= USER_LOGIN_FAILURE;
return true;
}
- return false;
}
void HostTracker::remove_inferred_services()
uint32_t hits = 0;
uint32_t last_seen = 0;
char user[INFO_SIZE] = { '\0' };
+ uint8_t user_login = 0;
bool banner_updated = false;
size_t num_visible_payloads = 0;
uint16_t max_info);
bool update_service_banner(Port, IpProtocol);
bool update_service_user(Port, IpProtocol, const char* username, uint32_t lseen,
- uint16_t max_services);
+ uint16_t max_services, bool success);
void remove_inferred_services();
size_t get_client_count();
CHECK(clients.size() == 1);
}
+// Test user login information updates for service
+TEST(host_tracker, update_service_user_test)
+{
+ HostTracker ht;
+
+ CHECK(ht.add_service(110, IpProtocol::TCP, 788, false) == true);
+
+ // The first discoveries of both login success and login failure are updated
+ CHECK(ht.update_service_user(110, IpProtocol::TCP, "user1", 1, 1, true) == true);
+ CHECK(ht.update_service_user(110, IpProtocol::TCP, "user1", 1, 1, false) == true);
+
+ // Subsequent discoveries for login success and login failure are not updated
+ CHECK(ht.update_service_user(110, IpProtocol::TCP, "user1", 1, 1, true) == false);
+ CHECK(ht.update_service_user(110, IpProtocol::TCP, "user1", 1, 1, false) == false);
+
+ // Discoveries for a new user name are updated
+ CHECK(ht.update_service_user(110, IpProtocol::TCP, "user2", 1, 1, false) == true);
+ CHECK(ht.update_service_user(110, IpProtocol::TCP, "user2", 1, 1, true) == true);
+}
+
// Test copying data and deleting copied list
TEST(host_tracker, copy_data_test)
{
discover_banner(p, proto, ht, &p->flow->server_ip, src_mac, logger, service);
}
- // Appid supports only login success event. Change checks once login failure and
- // logoff is supported
+ // Appid supports login success/failure events, but not logoff event.
if ( appid_change_bits[APPID_USER_INFO_BIT] and filter.is_user_monitored(p) )
{
- bool login;
- const char* username = appid_session_api.get_user_info(service, login);
- if ( login and service > APP_ID_NONE and username and *username )
+ bool login_success;
+ const char* username = appid_session_api.get_user_info(service, login_success);
+ if ( service > APP_ID_NONE and username and *username )
discover_user(p, ht, (const struct in6_addr*) p->ptrs.ip_api.get_dst()->get_ip6_ptr(),
- logger, username, service, proto, conf);
+ logger, username, service, proto, conf, login_success);
}
if ( p->is_from_client() and ( appid_change_bits[APPID_HOST_BIT] or
void RnaAppDiscovery::discover_user(const Packet* p, RnaTracker& rt,
const struct in6_addr* ip, RnaLogger& logger, const char* username,
- AppId service, IpProtocol proto, RnaConfig* conf)
+ AppId service, IpProtocol proto, RnaConfig* conf, bool login_success)
{
if ( rt->update_service_user(p->flow->server_port, proto, username,
- (uint32_t) packet_time(), conf ? conf->max_host_services : 0) )
+ (uint32_t) packet_time(), conf ? conf->max_host_services : 0, login_success) )
{
- logger.log(RUA_EVENT, CHANGE_USER_LOGIN, p, &rt, ip, username,
- service, (uint32_t) packet_time());
+ logger.log(RUA_EVENT, login_success ? CHANGE_USER_LOGIN : FAILED_USER_LOGIN,
+ p, &rt, ip, username, service, (uint32_t) packet_time());
}
}
RnaLogger&, const char*, AppId client, AppId service);
static void discover_user(const snort::Packet*, RnaTracker&, const struct in6_addr*,
- RnaLogger&, const char* username, AppId, IpProtocol, RnaConfig*);
+ RnaLogger&, const char* username, AppId, IpProtocol, RnaConfig*, bool);
static void discover_banner(const snort::Packet*, IpProtocol, RnaTracker&,
const snort::SfIp*, const uint8_t* mac, RnaLogger&, AppId);
#endif
using namespace snort;
+using namespace std;
#ifdef DEBUG_MSGS
static inline void rna_logger_message(const RnaLoggerEvent& rle, const Packet* p)
debug_logf(rna_trace, p, "RNA Banner log: true\n");
}
- if ( rle.user )
+ if ( rle.user and *rle.user )
{
- if ( rle.user and *rle.user )
- debug_logf(rna_trace, p,
- "RNA user login: service %u, user name %s\n", rle.appid, rle.user);
+ string login_str;
+ if ( rle.type == RUA_EVENT )
+ {
+ if ( rle.subtype == CHANGE_USER_LOGIN )
+ login_str = " login success";
+ else if ( rle.subtype == FAILED_USER_LOGIN )
+ login_str = " login failure";
+ }
+ debug_logf(rna_trace, nullptr, "RNA user%s: service %u, user name %s\n",
+ login_str.c_str(), rle.appid, rle.user);
}
}
else
#define RUA_EVENT 1004
#define CHANGE_USER_LOGIN 2
+ #define FAILED_USER_LOGIN 5
#endif