[PATCH V2] Makefile.am: Avoid redirection of input and output files
by Khem Raj
Ensure that directory is created before its written to
This can cause a build race in a highly parallelised build where a directory is not yet created but
output file is being written using redirection e.g.
rst2man.py --strict --no-raw --no-generator --no-datestamp < ../git/monitor/iwmon.rst > monitor/iwmon.1
/bin/sh: monitor/iwmon.1: No such file or directory
make[1]: *** [Makefile:3544: monitor/iwmon.1] Error 1
---
v2: create directory before emitting doc files into it
Makefile.am | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 823b7d02..1bd0005c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -626,8 +626,9 @@ SED_PROCESS = $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(SED) \
< $< > $@
if RUN_RST2MAN
-RST2MAN_PROCESS = $(AM_V_GEN)$(RST2MAN) --strict --no-raw --no-generator \
- --no-datestamp < $< > $@
+RST2MAN_PROCESS = $(AM_V_GEN)$(MKDIR_P) $(dir $@) && \
+ $(AM_V_GEN)$(RST2MAN) --strict --no-raw \
+ --no-generator --no-datestamp $< $@
else
RST2MAN_PROCESS = $(AM_V_GEN)test -f $@ || \
{ echo "Generated manual page $@ does not exist"; false; }
--
2.24.0
10 months, 3 weeks
[RFC/PATCH] Install iwd and ead into $sbindir rather than $libexecdir.
by Anton Khirnov
$libexecdir is supposed to contain "internal" binaries that are not
supposed to be executed "from the outside", e.g. directly by users.
Since iwd is a normal daemon that is directly executed from the outside,
$sbindir is the appropriate place for it.
---
Makefile.am | 8 ++++----
README | 4 ++--
src/iwd.service.in | 2 +-
wired/ead.service.in | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 9d378d3d..9e033599 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -135,7 +135,7 @@ ell_libell_internal_la_SOURCES = $(ell_headers) $(ell_sources)
endif
bin_PROGRAMS =
-libexec_PROGRAMS =
+sbin_PROGRAMS =
noinst_PROGRAMS =
if DBUS_POLICY
@@ -185,7 +185,7 @@ eap_sources = src/eap.c src/eap.h src/eap-private.h \
src/mschaputil.h src/mschaputil.c
if DAEMON
-libexec_PROGRAMS += src/iwd
+sbin_PROGRAMS += src/iwd
src_iwd_SOURCES = src/main.c linux/nl80211.h src/iwd.h src/missing.h \
src/plugin.h src/plugin.c \
@@ -313,7 +313,7 @@ endif
endif
if WIRED
-libexec_PROGRAMS += wired/ead
+sbin_PROGRAMS += wired/ead
wired_ead_SOURCES = wired/main.c wired/ethdev.h wired/ethdev.c \
wired/network.h wired/network.c \
@@ -627,7 +627,7 @@ ell/ell.h: Makefile
done
SED_PROCESS = $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(SED) \
- -e 's,@libexecdir\@,$(libexecdir),g' \
+ -e 's,@sbindir\@,$(sbindir),g' \
< $< > $@
if RUN_RST2MAN
diff --git a/README b/README
index fed9cf62..cffb8b1b 100644
--- a/README
+++ b/README
@@ -80,7 +80,7 @@ configuration options which are generally useful and enabled by default:
Disable installation of Wireless daemon
By default the Wireless daemon binary iwd is enabled and
- placed into --libexecdir directory.
+ placed into --sbindir directory.
--disable-client
@@ -159,7 +159,7 @@ that can be enabled if the functionality is required:
Enable installation of Ethernet authentication daemon
This allows enabling the Ethernet daemon binary ead which
- is then placed into --libexecdir directory.
+ is then placed into --sbindir directory.
With this option the support for 802.1x for wired Ethernet
connections can be enabled. It provides its own D-Bus
diff --git a/src/iwd.service.in b/src/iwd.service.in
index 77819eaf..a85f11fb 100644
--- a/src/iwd.service.in
+++ b/src/iwd.service.in
@@ -6,7 +6,7 @@ Wants=network.target
[Service]
Type=dbus
BusName=net.connman.iwd
-ExecStart=@libexecdir@/iwd
+ExecStart=@sbindir@/iwd
NotifyAccess=main
LimitNPROC=1
Restart=on-failure
diff --git a/wired/ead.service.in b/wired/ead.service.in
index 387fdb68..49b998a5 100644
--- a/wired/ead.service.in
+++ b/wired/ead.service.in
@@ -6,7 +6,7 @@ Wants=network.target
[Service]
Type=dbus
BusName=net.connman.ead
-ExecStart=@libexecdir@/ead
+ExecStart=@sbindir@/ead
NotifyAccess=main
LimitNPROC=1
Restart=on-failure
--
2.20.1
10 months, 3 weeks
[PATCH 1/2] client: Reorder interface creation ops
by Tim Kourt
Add the newly created proxy objects into the queue before the
interface specific initialization logic takes place. This way the new
proxy objects can be used within the initialization procedures.
---
client/dbus-proxy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/client/dbus-proxy.c b/client/dbus-proxy.c
index 83f91eea..37a09512 100644
--- a/client/dbus-proxy.c
+++ b/client/dbus-proxy.c
@@ -572,10 +572,10 @@ static void proxy_interface_create(const char *path,
proxy->path = l_strdup(path);
proxy->type = interface_type;
+ l_queue_push_tail(proxy_interfaces, proxy);
+
if (interface_type->ops && interface_type->ops->create)
proxy->data = interface_type->ops->create();
-
- l_queue_push_tail(proxy_interfaces, proxy);
}
}
--
2.13.6
11 months
[PATCH 1/6] frame-xchg: Try to call a handler only once per frame
by Andrew Zaborowski
Try to better deduplicate the frame watches. Until now we'd check if
we'd already registered a given frame body prefix with the kernel, or a
matching more general prefix (shorter). Now also try to check if we
have already have a watch with the same callback pointer and user_data
value, and:
* an identical or shorter (more general) prefix, in that case ignore
the new watch completely.
* a longer (more specific) prefix, in that case forget the existing
watch.
The use case for this is when we have a single callback for multiple
watches and multiple frame types, and inside that callback we're looking
at the frame body again and matching it to frame types. In that case
we don't want that function to be called multiple times for one frame
event.
---
src/frame-xchg.c | 70 +++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 64 insertions(+), 6 deletions(-)
diff --git a/src/frame-xchg.c b/src/frame-xchg.c
index d8f537f5..28b3a506 100644
--- a/src/frame-xchg.c
+++ b/src/frame-xchg.c
@@ -280,6 +280,60 @@ static void frame_watch_register_cb(struct l_genl_msg *msg, void *user_data)
L_PTR_TO_UINT(user_data), l_genl_msg_get_error(msg));
}
+struct frame_duplicate_info {
+ uint64_t wdev_id;
+ uint16_t frame_type;
+ const uint8_t *prefix;
+ size_t prefix_len;
+ frame_watch_cb_t handler;
+ void *user_data;
+ bool duplicate : 1;
+ bool registered : 1;
+};
+
+static bool frame_watch_check_duplicate(void *data, void *user_data)
+{
+ struct watchlist_item *super = data;
+ struct frame_watch *watch =
+ l_container_of(super, struct frame_watch, super);
+ struct frame_duplicate_info *info = user_data;
+ int common_len = info->prefix_len < watch->prefix_len ?
+ info->prefix_len : watch->prefix_len;
+
+ if (info->wdev_id != watch->wdev_id ||
+ info->frame_type != watch->frame_type ||
+ (common_len &&
+ memcmp(info->prefix, watch->prefix, common_len)))
+ /* No match */
+ return false;
+
+ if (info->prefix_len >= watch->prefix_len)
+ /*
+ * A matching shorter prefix is already registered with
+ * the kernel, no need to register the new prefix.
+ */
+ info->registered = true;
+
+ if (info->handler != watch->super.notify ||
+ info->user_data != watch->super.notify_data)
+ return false;
+
+ /*
+ * If we already have a watch with the exact same callback and
+ * user_data and a matching prefix (longer or shorter), drop
+ * either the existing watch, or the new watch, so as to preserve
+ * the set of frames that trigger the callback but avoid
+ * calling back twice with the same user_data.
+ */
+ if (info->prefix_len >= watch->prefix_len) {
+ info->duplicate = true;
+ return false;
+ }
+
+ /* Drop the existing watch as a duplicate of the new one */
+ return true;
+}
+
bool frame_watch_add(uint64_t wdev_id, uint32_t group_id, uint16_t frame_type,
const uint8_t *prefix, size_t prefix_len,
frame_watch_cb_t handler, void *user_data,
@@ -288,15 +342,19 @@ bool frame_watch_add(uint64_t wdev_id, uint32_t group_id, uint16_t frame_type,
struct watch_group *group = frame_watch_group_get(wdev_id, group_id);
struct frame_watch *watch;
struct l_genl_msg *msg;
- struct frame_prefix_info info = { frame_type, prefix, prefix_len, wdev_id };
- bool registered;
+ struct frame_duplicate_info info = {
+ wdev_id, frame_type, prefix, prefix_len,
+ handler, user_data, false, false
+ };
if (!group)
return false;
- registered = l_queue_find(group->watches.items,
- frame_watch_match_prefix,
- &info);
+ l_queue_foreach_remove(group->watches.items,
+ frame_watch_check_duplicate, &info);
+
+ if (info.duplicate)
+ return true;
watch = l_new(struct frame_watch, 1);
watch->frame_type = frame_type;
@@ -307,7 +365,7 @@ bool frame_watch_add(uint64_t wdev_id, uint32_t group_id, uint16_t frame_type,
watchlist_link(&group->watches, &watch->super, handler, user_data,
destroy);
- if (registered)
+ if (info.registered)
return true;
msg = l_genl_msg_new_sized(NL80211_CMD_REGISTER_FRAME, 32 + prefix_len);
--
2.20.1
11 months, 1 week
[PATCH 0/3] Update to ell's rntl API
by Daniel Wagner
The rtnlutil code has been moved to ell, let's use it.
Daniel Wagner (3):
netdev: Use ell's rtnl APIs
netconfig: Use ell's rtnl API
rtnlutil: Remove used rtnlutil
Makefile.am | 3 +-
src/netconfig.c | 31 ++-
src/netdev.c | 22 +-
src/rtnlutil.c | 640 ------------------------------------------------
src/rtnlutil.h | 103 --------
5 files changed, 28 insertions(+), 771 deletions(-)
delete mode 100644 src/rtnlutil.c
delete mode 100644 src/rtnlutil.h
--
2.25.0
11 months, 1 week
Connected network only shown after iwd restart
by Toke Høiland-Jørgensen
Hi
I'm having some trouble with getting iwctl to show which network is
currently connected. If I leave iwctl running while I start (or restart)
iwd, everything is fine:
[iwd]# station wlan0 show
Station: wlan0
--------------------------------------------------------------------------------
Settable Property Value
--------------------------------------------------------------------------------
Scanning no
State connected
Connected network myssid
But if I start iwctl after iwd (or, I suspect, after the network is
connected?), e.g. from the command line, I just get this:
$ iwctl station wlan0 show
Station: wlan0
--------------------------------------------------------------------------------
Settable Property Value
--------------------------------------------------------------------------------
Scanning no
State connected
Is this a bug, or am I doing something wrong when using iwctl?
-Toke
11 months, 2 weeks
[PATCH 1/5] nl80211util: Handle NL80211_ATTR_ACK flag in parser
by Andrew Zaborowski
If this attribute is included in the nl80211_parse_attrs parameters, set
the corresponding bool to true if flag was present and false if not.
---
src/nl80211util.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/nl80211util.c b/src/nl80211util.c
index c4942809..fa9abc1e 100644
--- a/src/nl80211util.c
+++ b/src/nl80211util.c
@@ -96,6 +96,14 @@ static bool extract_uint32(const void *data, uint16_t len, void *o)
return true;
}
+static bool extract_flag(const void *data, uint16_t len, void *o)
+{
+ if (len != 0)
+ return false;
+
+ return true;
+}
+
static attr_handler handler_for_type(enum nl80211_attrs type)
{
switch (type) {
@@ -112,6 +120,8 @@ static attr_handler handler_for_type(enum nl80211_attrs type)
return extract_name;
case NL80211_ATTR_MAC:
return extract_mac;
+ case NL80211_ATTR_ACK:
+ return extract_flag;
default:
break;
}
@@ -124,6 +134,7 @@ struct attr_entry {
void *data;
attr_handler handler;
bool present : 1;
+ bool flag : 1;
};
int nl80211_parse_attrs(struct l_genl_msg *msg, int tag, ...)
@@ -190,6 +201,11 @@ int nl80211_parse_attrs(struct l_genl_msg *msg, int tag, ...)
for (e = l_queue_get_entries(entries); e; e = e->next) {
entry = e->data;
+ if (entry->handler == extract_flag) {
+ *(bool *) entry->data = entry->present;
+ continue;
+ }
+
if (entry->present)
continue;
--
2.20.1
11 months, 2 weeks
[PATCH v2] client: Fix proxy object's dependency resolution
by Tim Kourt
Previously, the parsing of the OMs objects has been done in one pass,
therefore, the proxy object's dependencies may not have been parsed at the
time when they were looked up for the dependency assignments. Now, the
parsing of the OM objects is done in two passes: 1) Create proxy objects -
one per interface and path, 2) Populate the proxy objects with properties
and assign dependencies. Therefore, we are guaranteed to have the proxy
objects created by the time they are looked up for the dependency
assignments.
---
client/dbus-proxy.c | 99 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 63 insertions(+), 36 deletions(-)
diff --git a/client/dbus-proxy.c b/client/dbus-proxy.c
index 0555880d..83f91eea 100644
--- a/client/dbus-proxy.c
+++ b/client/dbus-proxy.c
@@ -511,6 +511,33 @@ static bool is_ignorable(const char *interface)
return false;
}
+static void proxy_interfaces_update_properties(const char *path,
+ struct l_dbus_message_iter *interfaces)
+{
+ const char *interface;
+ struct l_dbus_message_iter properties;
+ struct proxy_interface *proxy;
+ struct proxy_interface_type *interface_type;
+
+ if (!path)
+ return;
+
+ while (l_dbus_message_iter_next_entry(interfaces, &interface,
+ &properties)) {
+ interface_type = l_queue_find(proxy_interface_types,
+ interface_match_by_type_name,
+ interface);
+ if (!interface_type)
+ continue;
+
+ proxy = proxy_interface_find(interface_type->interface, path);
+ if (!proxy)
+ continue;
+
+ interface_update_properties(proxy, &properties, NULL);
+ }
+}
+
static void proxy_interface_create(const char *path,
struct l_dbus_message_iter *interfaces)
{
@@ -538,22 +565,16 @@ static void proxy_interface_create(const char *path,
proxy = proxy_interface_find(interface_type->interface, path);
- if (proxy) {
- interface_update_properties(proxy, &properties, NULL);
-
+ if (proxy)
continue;
- }
proxy = l_new(struct proxy_interface, 1);
proxy->path = l_strdup(path);
proxy->type = interface_type;
- if (interface_type->ops && interface_type->ops->create) {
+ if (interface_type->ops && interface_type->ops->create)
proxy->data = interface_type->ops->create();
- interface_update_properties(proxy, &properties, NULL);
- }
-
l_queue_push_tail(proxy_interfaces, proxy);
}
}
@@ -656,6 +677,12 @@ static void interfaces_added_callback(struct l_dbus_message *message,
return;
proxy_interface_create(path, &object);
+
+ if (!l_dbus_message_get_arguments(message, "oa{sa{sv}}", &path,
+ &object))
+ return;
+
+ proxy_interfaces_update_properties(path, &object);
}
static void interfaces_removed_callback(struct l_dbus_message *message,
@@ -692,52 +719,52 @@ static void get_managed_objects_callback(struct l_dbus_message *message,
const char *path;
if (dbus_message_has_error(message)) {
- l_error("Failed to retrieve IWD dbus objects, quitting...\n");
-
- if (!command_is_interactive_mode())
- command_set_exit_status(EXIT_FAILURE);
-
- l_main_quit();
+ display_error("Failed to retrieve IWD dbus objects, "
+ "quitting...\n");
- return;
+ goto error;
}
if (!l_dbus_message_get_arguments(message, "a{oa{sa{sv}}}", &objects)) {
- l_error("Failed to parse IWD dbus objects, quitting...\n");
+ display_error("Failed to parse IWD dbus objects, "
+ "quitting...\n");
- if (!command_is_interactive_mode())
- command_set_exit_status(EXIT_FAILURE);
-
- l_main_quit();
-
- return;
+ goto error;
}
while (l_dbus_message_iter_next_entry(&objects, &path, &object))
proxy_interface_create(path, &object);
- if (command_needs_no_agent())
- goto no_agent;
-
- if (!agent_manager_register_agent()) {
- display_error("Failed to register Agent.\n");
+ if (!l_dbus_message_get_arguments(message, "a{oa{sa{sv}}}", &objects))
+ /*
+ * Shouldn't happen since we parsed it above, but check return
+ * anyway.
+ */
+ goto error;
- if (!command_is_interactive_mode())
- command_set_exit_status(EXIT_FAILURE);
+ while (l_dbus_message_iter_next_entry(&objects, &path, &object))
+ proxy_interfaces_update_properties(path, &object);
- l_main_quit();
+ if (!command_needs_no_agent()) {
+ if (!agent_manager_register_agent()) {
+ display_error("Failed to register Agent.\n");
- return;
+ goto error;
+ }
}
-no_agent:
- if (!command_is_interactive_mode()) {
+ if (command_is_interactive_mode())
+ display_enable_cmd_prompt();
+ else
command_noninteractive_trigger();
- return;
- }
+ return;
+
+error:
+ if (!command_is_interactive_mode())
+ command_set_exit_status(EXIT_FAILURE);
- display_enable_cmd_prompt();
+ l_main_quit();
}
static void get_managed_objects(void)
--
2.13.6
11 months, 2 weeks
[PATCH] client: Fix proxy object's dependency resolution
by Tim Kourt
Previously, the parsing of the OMs objects has been done in one pass,
therefore, the proxy object's dependencies may not have been parsed at the
time when they were looked up for the dependency assignments. Now, the
parsing of the OM objects is done in two passes: 1) Create proxy objects -
one per interface and path, 2) Populate the proxy objects with properties
and assign dependencies. Therefore, we are guaranteed to have the proxy
objects created by the time they are looked up for the dependency
assignments.
---
client/dbus-proxy.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 54 insertions(+), 7 deletions(-)
diff --git a/client/dbus-proxy.c b/client/dbus-proxy.c
index 0555880d..9d6f4bcb 100644
--- a/client/dbus-proxy.c
+++ b/client/dbus-proxy.c
@@ -511,7 +511,7 @@ static bool is_ignorable(const char *interface)
return false;
}
-static void proxy_interface_create(const char *path,
+static void proxy_interfaces_update_properties(const char *path,
struct l_dbus_message_iter *interfaces)
{
const char *interface;
@@ -537,23 +537,50 @@ static void proxy_interface_create(const char *path,
}
proxy = proxy_interface_find(interface_type->interface, path);
+ if (!proxy)
+ continue;
+
+ interface_update_properties(proxy, &properties, NULL);
+ }
+}
+
+static void proxy_interface_create(const char *path,
+ struct l_dbus_message_iter *interfaces)
+{
+ const char *interface;
+ struct l_dbus_message_iter properties;
+ struct proxy_interface *proxy;
+ struct proxy_interface_type *interface_type;
- if (proxy) {
- interface_update_properties(proxy, &properties, NULL);
+ if (!path)
+ return;
+
+ while (l_dbus_message_iter_next_entry(interfaces, &interface,
+ &properties)) {
+ interface_type = l_queue_find(proxy_interface_types,
+ interface_match_by_type_name,
+ interface);
+
+ if (!interface_type) {
+ if (!is_ignorable(interface))
+ l_debug("Unknown DBus interface type %s",
+ interface);
continue;
}
+ proxy = proxy_interface_find(interface_type->interface, path);
+
+ if (proxy)
+ continue;
+
proxy = l_new(struct proxy_interface, 1);
proxy->path = l_strdup(path);
proxy->type = interface_type;
- if (interface_type->ops && interface_type->ops->create) {
+ if (interface_type->ops && interface_type->ops->create)
proxy->data = interface_type->ops->create();
- interface_update_properties(proxy, &properties, NULL);
- }
-
l_queue_push_tail(proxy_interfaces, proxy);
}
}
@@ -656,6 +683,12 @@ static void interfaces_added_callback(struct l_dbus_message *message,
return;
proxy_interface_create(path, &object);
+
+ if (!l_dbus_message_get_arguments(message, "oa{sa{sv}}", &path,
+ &object))
+ return;
+
+ proxy_interfaces_update_properties(path, &object);
}
static void interfaces_removed_callback(struct l_dbus_message *message,
@@ -716,6 +749,20 @@ static void get_managed_objects_callback(struct l_dbus_message *message,
while (l_dbus_message_iter_next_entry(&objects, &path, &object))
proxy_interface_create(path, &object);
+ if (!l_dbus_message_get_arguments(message, "a{oa{sa{sv}}}", &objects)) {
+ l_error("Failed to parse IWD dbus objects, quitting...\n");
+
+ if (!command_is_interactive_mode())
+ command_set_exit_status(EXIT_FAILURE);
+
+ l_main_quit();
+
+ return;
+ }
+
+ while (l_dbus_message_iter_next_entry(&objects, &path, &object))
+ proxy_interfaces_update_properties(path, &object);
+
if (command_needs_no_agent())
goto no_agent;
--
2.13.6
11 months, 3 weeks
[PATCH 1/4] eap-tls-common: Address PEAPv0 interoperability with Windows
by Tim Kourt
Windows Server 2008 - Network Policy Server (NPS) generates an invalid
Compound MAC for Cryptobinding TLV when is used within PEAPv0 due to
incorrect parsing of the message containing TLS Client Hello.
Setting L bit and including TLS Message Length field, even for the
packets that do not require fragmentation, corrects the issue. The
redundant TLS Message Length field in unfragmented packets doesn't
seem to effect the other server implementations.
---
src/eap-tls-common.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/src/eap-tls-common.c b/src/eap-tls-common.c
index 080e4f27..d62d7ca5 100644
--- a/src/eap-tls-common.c
+++ b/src/eap-tls-common.c
@@ -112,6 +112,7 @@ struct eap_tls_state {
size_t tx_frag_last_len;
bool expecting_frag_ack:1;
+ bool tunnel_ready:1;
struct l_queue *ca_cert;
struct l_certchain *client_cert;
@@ -128,6 +129,7 @@ static void __eap_tls_common_state_reset(struct eap_tls_state *eap_tls)
eap_tls->method_completed = false;
eap_tls->phase2_failed = false;
eap_tls->expecting_frag_ack = false;
+ eap_tls->tunnel_ready = false;
if (eap_tls->tunnel) {
l_tls_free(eap_tls->tunnel);
@@ -244,6 +246,8 @@ static void eap_tls_tunnel_ready(const char *peer_identity, void *user_data)
*/
eap_start_complete_timeout(eap);
+ eap_tls->tunnel_ready = true;
+
if (!eap_tls->variant_ops->tunnel_ready)
return;
@@ -261,6 +265,7 @@ static void eap_tls_tunnel_disconnected(enum l_tls_alert_desc reason,
eap_get_method_name(eap), l_tls_alert_to_str(reason));
eap_tls->method_completed = true;
+ eap_tls->tunnel_ready = false;
}
static bool eap_tls_validate_version(struct eap_state *eap,
@@ -325,11 +330,32 @@ static void eap_tls_send_fragment(struct eap_state *eap)
eap_tls->tx_frag_last_len = len;
}
+static bool needs_workaround(struct eap_state *eap)
+{
+ struct eap_tls_state *eap_tls = eap_get_data(eap);
+
+ /*
+ * Windows Server 2008 - Network Policy Server (NPS) generates an
+ * invalid Compound MAC for Cryptobinding TLV when is used within PEAPv0
+ * due to incorrect parsing of the message containing TLS Client Hello.
+ * Setting L bit and including TLS Message Length field, even for the
+ * packets that do not require fragmentation, corrects the issue. The
+ * redundant TLS Message Length field in unfragmented packets doesn't
+ * seem to effect the other server implementations.
+ */
+ return eap_get_method_type(eap) == EAP_TYPE_PEAP &&
+ eap_tls->version_negotiated == EAP_TLS_VERSION_0 &&
+ !eap_tls->tunnel_ready;
+}
+
static void eap_tls_send_response(struct eap_state *eap,
const uint8_t *pdu, size_t pdu_len)
{
struct eap_tls_state *eap_tls = eap_get_data(eap);
size_t msg_len = EAP_TLS_HEADER_LEN + pdu_len;
+ bool set_tls_msg_len = needs_workaround(eap);
+
+ msg_len += set_tls_msg_len ? 4 : 0;
if (msg_len <= eap_get_mtu(eap)) {
uint8_t *buf;
@@ -345,6 +371,15 @@ static void eap_tls_send_response(struct eap_state *eap,
buf[EAP_TLS_HEADER_OCTET_FLAGS + extra] =
eap_tls->version_negotiated;
+ if (set_tls_msg_len) {
+ buf[extra + EAP_TLS_HEADER_OCTET_FLAGS] |=
+ EAP_TLS_FLAG_L;
+ l_put_be32(pdu_len,
+ &buf[extra + EAP_TLS_HEADER_OCTET_FRAG_LEN]);
+
+ extra += 4;
+ }
+
memcpy(buf + EAP_TLS_HEADER_LEN + extra, pdu, pdu_len);
eap_send_response(eap, eap_get_method_type(eap), buf, msg_len);
--
2.13.6
11 months, 3 weeks