diff --git a/src/driver/fortdrv.c b/src/driver/fortdrv.c index 3fb7352f..4006c076 100644 --- a/src/driver/fortdrv.c +++ b/src/driver/fortdrv.c @@ -158,6 +158,29 @@ fort_conf_ref_flags_set (const PFORT_CONF_FLAGS conf_flags) return old_conf_flags; } +static void +fort_callout_classify_block (FWPS_CLASSIFY_OUT0 *classifyOut) +{ + classifyOut->actionType = FWP_ACTION_BLOCK; + classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; +} + +static void +fort_callout_classify_permit (const FWPS_FILTER0 *filter, + FWPS_CLASSIFY_OUT0 *classifyOut) +{ + classifyOut->actionType = FWP_ACTION_PERMIT; + if ((filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)) { + classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; + } +} + +static void +fort_callout_classify_continue (FWPS_CLASSIFY_OUT0 *classifyOut) +{ + classifyOut->actionType = FWP_ACTION_CONTINUE; +} + static void fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues, @@ -181,25 +204,26 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, conf_ref = fort_conf_ref_take(); if (conf_ref == NULL) { - if (g_device->prov_boot) - goto block; - - classifyOut->actionType = FWP_ACTION_CONTINUE; + if (g_device->prov_boot) { + fort_callout_classify_block(classifyOut); + } else { + fort_callout_classify_continue(classifyOut); + } return; } conf_flags = conf_ref->conf.flags; + if (conf_flags.stop_traffic) { + goto block; + } + flags = inFixedValues->incomingValue[flagsField].value.uint32; remote_ip = inFixedValues->incomingValue[remoteIpField].value.uint32; - if (!conf_flags.filter_enabled || conf_flags.stop_traffic + if (!conf_flags.filter_enabled || (flags & FWP_CONDITION_FLAG_IS_LOOPBACK) || remote_ip == 0xFFFFFFFF) { // Local broadcast - fort_conf_ref_put(conf_ref); - if (conf_flags.stop_traffic) { - goto block; - } goto permit; } @@ -212,8 +236,6 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, && ((app_index = fort_conf_app_index(&conf_ref->conf, path_len, path)), fort_conf_app_blocked(&conf_ref->conf, app_index)); - fort_conf_ref_put(conf_ref); - if (!blocked) { if (ip_included && conf_flags.log_stat) { const IPPROTO ip_proto = (IPPROTO) inFixedValues->incomingValue[ @@ -246,17 +268,15 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, } block: - classifyOut->actionType = FWP_ACTION_BLOCK; - classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; + fort_callout_classify_block(classifyOut); goto end; permit: - classifyOut->actionType = FWP_ACTION_PERMIT; - if ((filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)) { - classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; - } + fort_callout_classify_permit(filter, classifyOut); end: + fort_conf_ref_put(conf_ref); + if (irp != NULL) { fort_request_complete_info(irp, STATUS_SUCCESS, info); } @@ -312,6 +332,22 @@ fort_callout_flow_delete_v4 (UINT16 layerId, fort_stat_flow_delete(&g_device->stat, flowContext); } +static void +fort_callout_flow_classify_v4 (const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues, + UINT64 flowContext, + FWPS_CLASSIFY_OUT0 *classifyOut, + UINT32 dataSize, BOOL inbound) +{ + const UINT32 headerSize = inbound ? inMetaValues->transportHeaderSize : 0; + + if (fort_stat_flow_classify(&g_device->stat, flowContext, + headerSize + dataSize, inbound)) { + fort_callout_classify_block(classifyOut); + } else { + fort_callout_classify_continue(classifyOut); + } +} + static void fort_callout_stream_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues, @@ -325,12 +361,11 @@ fort_callout_stream_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, const BOOL inbound = (streamData->flags & FWPS_STREAM_FLAG_RECEIVE) != 0; - const UINT32 headerSize = inbound ? inMetaValues->transportHeaderSize : 0; + UNUSED(inFixedValues); + UNUSED(filter); - fort_stat_flow_classify(&g_device->stat, flowContext, - headerSize + dataSize, inbound); - - classifyOut->actionType = FWP_ACTION_CONTINUE; + fort_callout_flow_classify_v4(inMetaValues, flowContext, classifyOut, + dataSize, inbound); } static void @@ -348,12 +383,11 @@ fort_callout_datagram_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].value.uint8; const BOOL inbound = (direction == FWP_DIRECTION_INBOUND); - const UINT32 headerSize = inbound ? inMetaValues->transportHeaderSize : 0; + UNUSED(inFixedValues); + UNUSED(filter); - fort_stat_flow_classify(&g_device->stat, flowContext, - headerSize + dataSize, inbound); - - classifyOut->actionType = FWP_ACTION_CONTINUE; + fort_callout_flow_classify_v4(inMetaValues, flowContext, classifyOut, + dataSize, inbound); } static void diff --git a/src/driver/fortstat.c b/src/driver/fortstat.c index ce755ada..a342a72b 100644 --- a/src/driver/fortstat.c +++ b/src/driver/fortstat.c @@ -319,10 +319,19 @@ fort_stat_flow_remove_context (UINT64 flow_id, UINT16 layer_id, static void fort_stat_flow_transport_set_contexts (PFORT_STAT stat, UINT64 flow_id, - UINT64 flow_context, - BOOL is_udp, BOOL speed_limit) + UINT64 flow_context, BOOL is_udp, + BOOL speed_limit, BOOL is_reauth) { - if (!is_udp && speed_limit) { + if (is_udp) return; + + if (is_reauth) { + fort_stat_flow_remove_context(flow_id, + FWPS_LAYER_INBOUND_TRANSPORT_V4, stat->in_transport4_id); + fort_stat_flow_remove_context(flow_id, + FWPS_LAYER_OUTBOUND_TRANSPORT_V4, stat->out_transport4_id); + } + + if (speed_limit) { fort_stat_flow_set_context(flow_id, FWPS_LAYER_INBOUND_TRANSPORT_V4, stat->in_transport4_id, flow_context); fort_stat_flow_set_context(flow_id, FWPS_LAYER_OUTBOUND_TRANSPORT_V4, @@ -438,8 +447,15 @@ fort_stat_update_limits (PFORT_STAT stat, PFORT_CONF_IO conf_io) KLOCK_QUEUE_HANDLE lock_queue; KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue); - stat->limit_bits = conf_io->limit_bits; - RtlCopyMemory(stat->limits, conf_io->limits, sizeof(stat->limits)); + { + const UINT16 limit_bits = conf_io->limit_bits; + + stat->limit_bits = limit_bits; + + if (limit_bits != 0) { + RtlCopyMemory(stat->limits, conf_io->limits, sizeof(stat->limits)); + } + } KeReleaseInStackQueuedSpinLock(&lock_queue); } @@ -503,7 +519,7 @@ fort_stat_flow_associate (PFORT_STAT stat, UINT64 flow_id, if (NT_SUCCESS(status)) { // Set stream transport layer contexts fort_stat_flow_transport_set_contexts( - stat, flow_id, flow_context, is_udp, speed_limit); + stat, flow_id, flow_context, is_udp, speed_limit, is_reauth); fort_stat_proc_inc(stat, proc_index); } else { @@ -547,7 +563,7 @@ fort_stat_flow_delete (PFORT_STAT stat, UINT64 flow_context) KeReleaseInStackQueuedSpinLock(&lock_queue); } -static void +static BOOL fort_stat_flow_classify (PFORT_STAT stat, UINT64 flow_context, UINT32 data_len, BOOL inbound) { @@ -555,35 +571,44 @@ fort_stat_flow_classify (PFORT_STAT stat, UINT64 flow_context, const UINT16 proc_index = (UINT16) (flow_context >> 48); const UCHAR group_index = (UCHAR) (flow_context >> 40); const UCHAR stat_version = (UCHAR) (flow_context >> 32); + BOOL limited = FALSE; if (stat->closing) - return; + return FALSE; KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue); if (stat_version == stat->version) { PFORT_STAT_PROC proc = &stat->procs[proc_index]; + UINT32 *proc_bytes = inbound ? &proc->traf.in_bytes + : &proc->traf.out_bytes; // Add traffic to process - if (inbound) { - proc->traf.in_bytes += data_len; - } else { - proc->traf.out_bytes += data_len; - } + *proc_bytes += data_len; if (fort_stat_group_speed_limit(stat, group_index)) { - PFORT_STAT_GROUP group = &stat->groups[group_index]; + const PFORT_CONF_LIMIT group_limit = &stat->limits[group_index]; + const UINT32 limit_bytes = inbound ? group_limit->in_bytes + : group_limit->out_bytes; - // Add traffic to app. group - if (inbound) { - group->traf.in_bytes += data_len; - } else { - group->traf.out_bytes += data_len; + if (limit_bytes != 0) { + PFORT_STAT_GROUP group = &stat->groups[group_index]; + UINT32 *group_bytes = inbound ? &group->traf.in_bytes + : &group->traf.out_bytes; + + if (*group_bytes < limit_bytes) { + // Add traffic to app. group + *group_bytes += data_len; + } else { + limited = TRUE; + } } } stat->is_dirty = TRUE; } KeReleaseInStackQueuedSpinLock(&lock_queue); + + return limited; } static void @@ -604,6 +629,7 @@ fort_stat_dpc_traf_flush (PFORT_STAT stat, PCHAR out) const UINT32 proc_bits_len = FORT_LOG_STAT_PROC_SIZE(stat->proc_count); PFORT_STAT_TRAF out_traf = (PFORT_STAT_TRAF) (out + proc_bits_len); PUCHAR out_proc_bits = (PUCHAR) out; + UINT16 i; PFORT_STAT_PROC prev_proc = NULL; UINT16 proc_index = stat->proc_head_index; @@ -611,7 +637,7 @@ fort_stat_dpc_traf_flush (PFORT_STAT stat, PCHAR out) /* Mark processes as active to start */ memset(out_proc_bits, 0xFF, proc_bits_len); - for (UINT16 i = 0; proc_index != FORT_PROC_BAD_INDEX; ++i) { + for (i = 0; proc_index != FORT_PROC_BAD_INDEX; ++i) { PFORT_STAT_PROC proc = &stat->procs[proc_index]; const UINT16 next_index = proc->next_index; @@ -633,5 +659,18 @@ fort_stat_dpc_traf_flush (PFORT_STAT stat, PCHAR out) proc_index = next_index; } + if (stat->limit_bits) { + PFORT_STAT_GROUP group = stat->groups; + UINT16 limit_bits = stat->limit_bits; + + for (; limit_bits != 0; ++group) { + if (limit_bits & 1) { + group->traf_all.QuadPart = 0; + } + + limit_bits >>= 1; + } + } + stat->is_dirty = FALSE; } diff --git a/src/ui/util/confutil.cpp b/src/ui/util/confutil.cpp index ff4c1f61..0025b2b4 100644 --- a/src/ui/util/confutil.cpp +++ b/src/ui/util/confutil.cpp @@ -51,7 +51,7 @@ int ConfUtil::write(const FirewallConf &conf, QByteArray &buf) int appPathsLen = 0; QStringList appPaths; appperms_arr_t appPerms; - appgroups_arr_t appGroupIndexes; + appgroups_map_t appGroupIndexes; if (!parseAppGroups(conf.appGroupsList(), appPaths, appPathsLen, @@ -110,7 +110,7 @@ bool ConfUtil::parseAppGroups(const QList &appGroups, QStringList &appPaths, int &appPathsLen, appperms_arr_t &appPerms, - appgroups_arr_t &appGroupIndexes) + appgroups_map_t &appGroupIndexes) { const int groupsCount = appGroups.size(); if (groupsCount > APP_GROUP_MAX) { @@ -159,7 +159,7 @@ bool ConfUtil::parseAppGroups(const QList &appGroups, bool ConfUtil::parseApps(const QString &text, bool blocked, appperms_map_t &appPermsMap, - appgroups_arr_t &appGroupIndexes, + appgroups_map_t &appGroupIndexes, int groupOffset) { foreach (const QStringRef &line, @@ -184,7 +184,7 @@ bool ConfUtil::parseApps(const QString &text, bool blocked, if (appPermsMap.contains(appPath)) { appPerms |= appPermsMap.value(appPath); } else { - appGroupIndexes.append(groupOffset); + appGroupIndexes.insert(appPath, groupOffset); } appPermsMap.insert(appPath, appPerms); @@ -215,7 +215,7 @@ void ConfUtil::writeData(char *output, const FirewallConf &conf, const Ip4Range &incRange, const Ip4Range &excRange, const QStringList &appPaths, const appperms_arr_t &appPerms, - const appgroups_arr_t &appGroupIndexes) + const appgroups_map_t &appGroupIndexes) { PFORT_CONF_IO drvConfIo = (PFORT_CONF_IO) output; PFORT_CONF drvConf = &drvConfIo->conf; @@ -241,7 +241,7 @@ void ConfUtil::writeData(char *output, const FirewallConf &conf, writeNumbers(&data, excRange.toArray()); appGroupsOff = CONF_DATA_OFFSET; - writeChars(&data, appGroupIndexes); + writeChars(&data, appGroupIndexes.values().toVector()); appPermsOff = CONF_DATA_OFFSET; writeNumbers(&data, appPerms); diff --git a/src/ui/util/confutil.h b/src/ui/util/confutil.h index 0de7717d..618c2d16 100644 --- a/src/ui/util/confutil.h +++ b/src/ui/util/confutil.h @@ -1,7 +1,6 @@ #ifndef CONFUTIL_H #define CONFUTIL_H -#include #include #include #include @@ -15,7 +14,7 @@ QT_FORWARD_DECLARE_STRUCT(fort_conf_limit) typedef QMap appperms_map_t; typedef QVector appperms_arr_t; -typedef QVector appgroups_arr_t; +typedef QMap appgroups_map_t; class ConfUtil : public QObject { @@ -42,11 +41,11 @@ private: QStringList &appPaths, int &appPathsLen, appperms_arr_t &appPerms, - appgroups_arr_t &appGroupIndexes); + appgroups_map_t &appGroupIndexes); bool parseApps(const QString &text, bool blocked, appperms_map_t &appPermsMap, - appgroups_arr_t &appGroupIndexes, + appgroups_map_t &appGroupIndexes, int groupOffset); static QString parseAppPath(const QStringRef &line); @@ -55,7 +54,7 @@ private: const Ip4Range &incRange, const Ip4Range &excRange, const QStringList &appPaths, const appperms_arr_t &appPerms, - const appgroups_arr_t &appGroupIndexes); + const appgroups_map_t &appGroupIndexes); static quint16 writeLimits(struct fort_conf_limit *limits, const QList &appGroups);