[RFC ] include with wildcard filenames

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[RFC ] include with wildcard filenames

Ulf Samuelsson
I was trying out a dhcpd configuration, and found to my dismay
that the DHCP server did not support wildcards for include statements.
include "/etc/dhcp/pools/*.conf";
did not work.

BACKGROUND:

I have an application, where I want to use the DHCP server
as part of the authentication process for connected machines.

I want to use three ranges.
pool 0 => 169.254.128.x            trusted units
pool 1 => 169.254.254.x            units demanding to be trusted
pool 2 => 169.254.1.x              normal units
pool 3 => 169.254.253.x            untrusted units/intruders

The DHCP CPU Ethernet Controller communicates through a five port switch.
port 0: trusted units    pool 0
port 2: internet port
port 3: service port
port 4: CPU port    169.254.1.1

Units connected on port 0, provides a dhcp-client-identifier indicating
that they want an address in pool 0, but initially they will get a short
term lease in pool 1, until it is verified that they are on port 0.

Units without this dhcp-client-identifier, should get an address in pool 2.

An intruder, trying to get a pool 0 address, will supply the same
dhcp-client-identifier as port 0 units. They will also initially get a
short term pool 1 address, but when the intrusion attempt is detected,
they should be declared "untrusted". Future leases should be in pool 3.

=====
When a pool 1 address is allocated, the commit event is used to run a
script which will read out information from the switch and determine if
the request comes from port 0.

Request comes from (port == 0) => the mac address should be "trusted"
Request comes from (port != 0) => the mac address should be "untrusted".

I define:
class "trusted" {
     match hardware;
}

class "untrusted" {
     match hardware;
}

An incoming request from "00:11:22:33:44:55" adds a file:
/etc/dhcp/trusted/00:11:22:33:44:55:
       sub-class "trusted" 1:00:11:22:33:44:55;
or
/etc/dhcp/untrusted/00:11:22:33:44:55:
       sub-class "trusted" 1:00:11:22:33:44:55;


When the short term pool 1 lease expires (after 1-2 minutes)
the new lease will be classified either as "trusted" (getting a pool 0
lease) or "untrusted" (getting a pool 3 lease).

It would be practical to have the dhcpd.conf file contain:

include "/etc/dhcp/trusted/*";
include "/etc/dhcp/untrusted/*";

but unfortunately wildcards in include statements are not supported.

====================================

I did a patch for dhcp-4.3.6 which is slightly limited.
It supports only wildcards on files within a single directory.
I.E: include "/etc/dhcp/pools/*.conf"; is supported
I.E: include "/etc/dhcp/*/dhcp.conf"; is not supported
The wildcard may not be in a directory.

Did a small test program which tested the functionality of wildcards,
and then patched the dhcp server, but it has not been tested yet, as
part of dhcp
Still would like to have peoples opinion, whether this type of
functionality is desirable.
It is certainly possible to do this without wildcards,
but wildcards seems a much cleaner solution.
====================================

 From dcc981f1371f390befffc950b9dc3a8107059643 Mon Sep 17 00:00:00 2001
From: Ulf Samuelsson <[hidden email]>
Date: Tue, 27 Feb 2018 21:03:52 +0100
Subject: [PATCH 14/14] Support wildcard in include files

Signed-off-by: Ulf Samuelsson <[hidden email]>
---
  includes/dhcpd.h  |  3 +++
  server/confpars.c | 71
+++++++++++++++++++++++++++++++++++++++++++++++++++++--
  2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index eab09a6..8208fbe 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -53,6 +53,9 @@
  #include <sys/mman.h>
  #include <ctype.h>
  #include <time.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <fnmatch.h>

  #include <net/if.h>
  #undef FDDI
diff --git a/server/confpars.c b/server/confpars.c
index c0735fe..c12f5c7 100644
--- a/server/confpars.c
+++ b/server/confpars.c
@@ -327,7 +327,7 @@ isc_result_t lease_file_subparse (struct parse *cfile)
     parameter :== DEFAULT_LEASE_TIME lease_time
             | MAX_LEASE_TIME lease_time
             | DYNAMIC_BOOTP_LEASE_CUTOFF date
-           | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
+           | DYNAMIC_BOOTP_LEASE_LENGTH l#include <string.h>ease_time
             | BOOT_UNKNOWN_CLIENTS boolean
             | ONE_LEASE_PER_CLIENT boolean
             | GET_LEASE_HOSTNAMES boolean
@@ -352,6 +352,73 @@ isc_result_t lease_file_subparse (struct parse *cfile)
           | VENDOR_CLASS class-declaration
           | USER_CLASS class-declaration
           | RANGE address-range-declaration */
+#include <string.h>
+isc_result_t read_multiple_conf_files(path, group, type)
+    const char *path;
+    struct group *group;
+    int type;
+{
+    char    *buf_dir;
+    char    *dir;
+    char    *buf_base;
+    char    *base;
+    DIR    *d;
+    struct    dirent *entry;
+    int reti;
+    isc_result_t status;
+
+    dir    = dirname (buf_dir    = strdup(path));
+    base    = basename(buf_base    = strdup(path));
+
+    if (!(d = opendir(dir))) {
+        status = DHCP_R_INVALIDARG;
+        goto    exit;
+    }
+
+    while ((entry = readdir(d)) != NULL) {
+        if (entry->d_type == DT_DIR) {
+            continue;
+        } else {
+            reti = fnmatch(base, entry->d_name, 0);
+            if (reti == 0) {
+                status = read_conf_file (path, group, type, 0);
+                if (status != ISC_R_SUCCESS) {
+                    goto exit;
+                }
+            } else {
+                continue;
+            }
+        }
+    }
+    closedir(d);
+exit:
+    free(buf_dir);
+    free(buf_base);
+    return status;
+}
+
+isc_result_t include_files(path, group, type)
+    const char *path;
+    struct group *group;
+    int type;
+{
+    const char    *eos;
+    const char    *wildcard = strchr(path, '*');
+    char    *p;
+
+    if (wildcard == NULL) {
+        return read_conf_file (path, group, type, 0);
+    }
+
+    eos = &path[strlen(path)];
+    for (wildcard++; wildcard < eos; wildcard++) {
+        if (*wildcard == '/') {
+            /* wildcard in directory, not allowed */
+            return DHCP_R_INVALIDARG;
+        }
+    }
+    return read_multiple_conf_files(path, group, type);
+}

  int parse_statement (cfile, group, type, host_decl, declaration)
      struct parse *cfile;
@@ -383,7 +450,7 @@ int parse_statement (cfile, group, type, host_decl,
declaration)
              parse_warn (cfile, "filename string expected.");
              skip_to_semi (cfile);
          } else {
-            status = read_conf_file (val, group, type, 0);
+            status = include_files(val, group, type);
              if (status != ISC_R_SUCCESS)
                  parse_warn (cfile, "%s: bad parse.", val);
              parse_semi (cfile);
--
1.9.1

Best Regards
Ulf Samuelsson
_______________________________________________
dhcp-users mailing list
[hidden email]
https://lists.isc.org/mailman/listinfo/dhcp-users
Reply | Threaded
Open this post in threaded view
|

Re: [RFC ] include with wildcard filenames

Bill Shirley-2
This sounds like the wrong approach to addressing your problem because
for dhcpd to honor the new configuration, it would need to be restarted every
time a file is added/deleted/changed in the wildcard directory.

This sounds more like a task for iptables and ipsets.

Are all four of these private networks on the same NIC?  Are these subnets
VLANs?

As far as I know, there is no mechanism to consult an source external to the
dhcpd program for information.

Bill

On 2/27/2018 5:33 PM, Ulf Samuelsson wrote:

> I was trying out a dhcpd configuration, and found to my dismay
> that the DHCP server did not support wildcards for include statements.
> include "/etc/dhcp/pools/*.conf";
> did not work.
>
> BACKGROUND:
>
> I have an application, where I want to use the DHCP server
> as part of the authentication process for connected machines.
>
> I want to use three ranges.
> pool 0 => 169.254.128.x            trusted units
> pool 1 => 169.254.254.x            units demanding to be trusted
> pool 2 => 169.254.1.x              normal units
> pool 3 => 169.254.253.x            untrusted units/intruders
>
> The DHCP CPU Ethernet Controller communicates through a five port switch.
> port 0: trusted units    pool 0
> port 2: internet port
> port 3: service port
> port 4: CPU port    169.254.1.1
>
> Units connected on port 0, provides a dhcp-client-identifier indicating that they want an address in pool 0, but initially
> they will get a short term lease in pool 1, until it is verified that they are on port 0.
>
> Units without this dhcp-client-identifier, should get an address in pool 2.
>
> An intruder, trying to get a pool 0 address, will supply the same dhcp-client-identifier as port 0 units. They will also
> initially get a short term pool 1 address, but when the intrusion attempt is detected, they should be declared "untrusted".
> Future leases should be in pool 3.
>
> =====
> When a pool 1 address is allocated, the commit event is used to run a script which will read out information from the switch
> and determine if the request comes from port 0.
>
> Request comes from (port == 0) => the mac address should be "trusted"
> Request comes from (port != 0) => the mac address should be "untrusted".
>
> I define:
> class "trusted" {
>     match hardware;
> }
>
> class "untrusted" {
>     match hardware;
> }
>
> An incoming request from "00:11:22:33:44:55" adds a file:
> /etc/dhcp/trusted/00:11:22:33:44:55:
>       sub-class "trusted" 1:00:11:22:33:44:55;
> or
> /etc/dhcp/untrusted/00:11:22:33:44:55:
>       sub-class "trusted" 1:00:11:22:33:44:55;
>
>
> When the short term pool 1 lease expires (after 1-2 minutes)
> the new lease will be classified either as "trusted" (getting a pool 0 lease) or "untrusted" (getting a pool 3 lease).
>
> It would be practical to have the dhcpd.conf file contain:
>
> include "/etc/dhcp/trusted/*";
> include "/etc/dhcp/untrusted/*";
>
> but unfortunately wildcards in include statements are not supported.
>
> ====================================
>
> I did a patch for dhcp-4.3.6 which is slightly limited.
> It supports only wildcards on files within a single directory.
> I.E: include "/etc/dhcp/pools/*.conf"; is supported
> I.E: include "/etc/dhcp/*/dhcp.conf"; is not supported
> The wildcard may not be in a directory.
>
> Did a small test program which tested the functionality of wildcards,
> and then patched the dhcp server, but it has not been tested yet, as part of dhcp
> Still would like to have peoples opinion, whether this type of functionality is desirable.
> It is certainly possible to do this without wildcards,
> but wildcards seems a much cleaner solution.
> ====================================
>
> From dcc981f1371f390befffc950b9dc3a8107059643 Mon Sep 17 00:00:00 2001
> From: Ulf Samuelsson <[hidden email]>
> Date: Tue, 27 Feb 2018 21:03:52 +0100
> Subject: [PATCH 14/14] Support wildcard in include files
>
> Signed-off-by: Ulf Samuelsson <[hidden email]>
> ---
>  includes/dhcpd.h  |  3 +++
>  server/confpars.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 72 insertions(+), 2 deletions(-)
>
> diff --git a/includes/dhcpd.h b/includes/dhcpd.h
> index eab09a6..8208fbe 100644
> --- a/includes/dhcpd.h
> +++ b/includes/dhcpd.h
> @@ -53,6 +53,9 @@
>  #include <sys/mman.h>
>  #include <ctype.h>
>  #include <time.h>
> +#include <dirent.h>
> +#include <libgen.h>
> +#include <fnmatch.h>
>
>  #include <net/if.h>
>  #undef FDDI
> diff --git a/server/confpars.c b/server/confpars.c
> index c0735fe..c12f5c7 100644
> --- a/server/confpars.c
> +++ b/server/confpars.c
> @@ -327,7 +327,7 @@ isc_result_t lease_file_subparse (struct parse *cfile)
>     parameter :== DEFAULT_LEASE_TIME lease_time
>             | MAX_LEASE_TIME lease_time
>             | DYNAMIC_BOOTP_LEASE_CUTOFF date
> -           | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
> +           | DYNAMIC_BOOTP_LEASE_LENGTH l#include <string.h>ease_time
>             | BOOT_UNKNOWN_CLIENTS boolean
>             | ONE_LEASE_PER_CLIENT boolean
>             | GET_LEASE_HOSTNAMES boolean
> @@ -352,6 +352,73 @@ isc_result_t lease_file_subparse (struct parse *cfile)
>           | VENDOR_CLASS class-declaration
>           | USER_CLASS class-declaration
>           | RANGE address-range-declaration */
> +#include <string.h>
> +isc_result_t read_multiple_conf_files(path, group, type)
> +    const char *path;
> +    struct group *group;
> +    int type;
> +{
> +    char    *buf_dir;
> +    char    *dir;
> +    char    *buf_base;
> +    char    *base;
> +    DIR    *d;
> +    struct    dirent *entry;
> +    int reti;
> +    isc_result_t status;
> +
> +    dir    = dirname (buf_dir    = strdup(path));
> +    base    = basename(buf_base    = strdup(path));
> +
> +    if (!(d = opendir(dir))) {
> +        status = DHCP_R_INVALIDARG;
> +        goto    exit;
> +    }
> +
> +    while ((entry = readdir(d)) != NULL) {
> +        if (entry->d_type == DT_DIR) {
> +            continue;
> +        } else {
> +            reti = fnmatch(base, entry->d_name, 0);
> +            if (reti == 0) {
> +                status = read_conf_file (path, group, type, 0);
> +                if (status != ISC_R_SUCCESS) {
> +                    goto exit;
> +                }
> +            } else {
> +                continue;
> +            }
> +        }
> +    }
> +    closedir(d);
> +exit:
> +    free(buf_dir);
> +    free(buf_base);
> +    return status;
> +}
> +
> +isc_result_t include_files(path, group, type)
> +    const char *path;
> +    struct group *group;
> +    int type;
> +{
> +    const char    *eos;
> +    const char    *wildcard = strchr(path, '*');
> +    char    *p;
> +
> +    if (wildcard == NULL) {
> +        return read_conf_file (path, group, type, 0);
> +    }
> +
> +    eos = &path[strlen(path)];
> +    for (wildcard++; wildcard < eos; wildcard++) {
> +        if (*wildcard == '/') {
> +            /* wildcard in directory, not allowed */
> +            return DHCP_R_INVALIDARG;
> +        }
> +    }
> +    return read_multiple_conf_files(path, group, type);
> +}
>
>  int parse_statement (cfile, group, type, host_decl, declaration)
>      struct parse *cfile;
> @@ -383,7 +450,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
>              parse_warn (cfile, "filename string expected.");
>              skip_to_semi (cfile);
>          } else {
> -            status = read_conf_file (val, group, type, 0);
> +            status = include_files(val, group, type);
>              if (status != ISC_R_SUCCESS)
>                  parse_warn (cfile, "%s: bad parse.", val);
>              parse_semi (cfile);

_______________________________________________
dhcp-users mailing list
[hidden email]
https://lists.isc.org/mailman/listinfo/dhcp-users
Reply | Threaded
Open this post in threaded view
|

Re: [RFC ] include with wildcard filenames

Ulf Samuelsson
The device consist of a master and several slaves.
Normally, the unit is installed and the slave configuration rarely changes.
Restarting the dhcp server during installation is not a problem
In many cases, the slaves never change after installation.
If the slave configuration changes, then the unit does not need to operate normally during the installation  so a few restarts are not a problem.

In this scenario, only an intruder will cause the adding to the ”untrusted” class.

I was thinking that omshell might help avoid a restart here, but I have not studied
it in detail, so this is still an unknown.

The DHCP server has a single ethernet MAC, connected directly to the switch.

There were VLANs before protecting the slaves, but they were removed for some reason, but I do not know the details.

Having wildcards still seems useful, anyway.

Best Regards,
Ulf Samuelsson

> 28 feb. 2018 kl. 09:52 skrev Bill Shirley <[hidden email]>:
>
> This sounds like the wrong approach to addressing your problem because
> for dhcpd to honor the new configuration, it would need to be restarted every
> time a file is added/deleted/changed in the wildcard directory.
>
> This sounds more like a task for iptables and ipsets.
>
> Are all four of these private networks on the same NIC?  Are these subnets
> VLANs?
>
> As far as I know, there is no mechanism to consult an source external to the
> dhcpd program for information.
>
> Bill
>
>> On 2/27/2018 5:33 PM, Ulf Samuelsson wrote:
>> I was trying out a dhcpd configuration, and found to my dismay
>> that the DHCP server did not support wildcards for include statements.
>> include "/etc/dhcp/pools/*.conf";
>> did not work.
>>
>> BACKGROUND:
>>
>> I have an application, where I want to use the DHCP server
>> as part of the authentication process for connected machines.
>>
>> I want to use three ranges.
>> pool 0 => 169.254.128.x            trusted units
>> pool 1 => 169.254.254.x            units demanding to be trusted
>> pool 2 => 169.254.1.x              normal units
>> pool 3 => 169.254.253.x            untrusted units/intruders
>>
>> The DHCP CPU Ethernet Controller communicates through a five port switch.
>> port 0: trusted units    pool 0
>> port 2: internet port
>> port 3: service port
>> port 4: CPU port    169.254.1.1
>>
>> Units connected on port 0, provides a dhcp-client-identifier indicating that they want an address in pool 0, but initially they will get a short term lease in pool 1, until it is verified that they are on port 0.
>>
>> Units without this dhcp-client-identifier, should get an address in pool 2.
>>
>> An intruder, trying to get a pool 0 address, will supply the same dhcp-client-identifier as port 0 units. They will also initially get a short term pool 1 address, but when the intrusion attempt is detected, they should be declared "untrusted". Future leases should be in pool 3.
>>
>> =====
>> When a pool 1 address is allocated, the commit event is used to run a script which will read out information from the switch and determine if the request comes from port 0.
>>
>> Request comes from (port == 0) => the mac address should be "trusted"
>> Request comes from (port != 0) => the mac address should be "untrusted".
>>
>> I define:
>> class "trusted" {
>>     match hardware;
>> }
>>
>> class "untrusted" {
>>     match hardware;
>> }
>>
>> An incoming request from "00:11:22:33:44:55" adds a file:
>> /etc/dhcp/trusted/00:11:22:33:44:55:
>>       sub-class "trusted" 1:00:11:22:33:44:55;
>> or
>> /etc/dhcp/untrusted/00:11:22:33:44:55:
>>       sub-class "trusted" 1:00:11:22:33:44:55;
>>
>>
>> When the short term pool 1 lease expires (after 1-2 minutes)
>> the new lease will be classified either as "trusted" (getting a pool 0 lease) or "untrusted" (getting a pool 3 lease).
>>
>> It would be practical to have the dhcpd.conf file contain:
>>
>> include "/etc/dhcp/trusted/*";
>> include "/etc/dhcp/untrusted/*";
>>
>> but unfortunately wildcards in include statements are not supported.
>>
>> ====================================
>>
>> I did a patch for dhcp-4.3.6 which is slightly limited.
>> It supports only wildcards on files within a single directory.
>> I.E: include "/etc/dhcp/pools/*.conf"; is supported
>> I.E: include "/etc/dhcp/*/dhcp.conf"; is not supported
>> The wildcard may not be in a directory.
>>
>> Did a small test program which tested the functionality of wildcards,
>> and then patched the dhcp server, but it has not been tested yet, as part of dhcp
>> Still would like to have peoples opinion, whether this type of functionality is desirable.
>> It is certainly possible to do this without wildcards,
>> but wildcards seems a much cleaner solution.
>> ====================================
>>
>> From dcc981f1371f390befffc950b9dc3a8107059643 Mon Sep 17 00:00:00 2001
>> From: Ulf Samuelsson <[hidden email]>
>> Date: Tue, 27 Feb 2018 21:03:52 +0100
>> Subject: [PATCH 14/14] Support wildcard in include files
>>
>> Signed-off-by: Ulf Samuelsson <[hidden email]>
>> ---
>>  includes/dhcpd.h  |  3 +++
>>  server/confpars.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>>  2 files changed, 72 insertions(+), 2 deletions(-)
>>
>> diff --git a/includes/dhcpd.h b/includes/dhcpd.h
>> index eab09a6..8208fbe 100644
>> --- a/includes/dhcpd.h
>> +++ b/includes/dhcpd.h
>> @@ -53,6 +53,9 @@
>>  #include <sys/mman.h>
>>  #include <ctype.h>
>>  #include <time.h>
>> +#include <dirent.h>
>> +#include <libgen.h>
>> +#include <fnmatch.h>
>>
>>  #include <net/if.h>
>>  #undef FDDI
>> diff --git a/server/confpars.c b/server/confpars.c
>> index c0735fe..c12f5c7 100644
>> --- a/server/confpars.c
>> +++ b/server/confpars.c
>> @@ -327,7 +327,7 @@ isc_result_t lease_file_subparse (struct parse *cfile)
>>     parameter :== DEFAULT_LEASE_TIME lease_time
>>             | MAX_LEASE_TIME lease_time
>>             | DYNAMIC_BOOTP_LEASE_CUTOFF date
>> -           | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
>> +           | DYNAMIC_BOOTP_LEASE_LENGTH l#include <string.h>ease_time
>>             | BOOT_UNKNOWN_CLIENTS boolean
>>             | ONE_LEASE_PER_CLIENT boolean
>>             | GET_LEASE_HOSTNAMES boolean
>> @@ -352,6 +352,73 @@ isc_result_t lease_file_subparse (struct parse *cfile)
>>           | VENDOR_CLASS class-declaration
>>           | USER_CLASS class-declaration
>>           | RANGE address-range-declaration */
>> +#include <string.h>
>> +isc_result_t read_multiple_conf_files(path, group, type)
>> +    const char *path;
>> +    struct group *group;
>> +    int type;
>> +{
>> +    char    *buf_dir;
>> +    char    *dir;
>> +    char    *buf_base;
>> +    char    *base;
>> +    DIR    *d;
>> +    struct    dirent *entry;
>> +    int reti;
>> +    isc_result_t status;
>> +
>> +    dir    = dirname (buf_dir    = strdup(path));
>> +    base    = basename(buf_base    = strdup(path));
>> +
>> +    if (!(d = opendir(dir))) {
>> +        status = DHCP_R_INVALIDARG;
>> +        goto    exit;
>> +    }
>> +
>> +    while ((entry = readdir(d)) != NULL) {
>> +        if (entry->d_type == DT_DIR) {
>> +            continue;
>> +        } else {
>> +            reti = fnmatch(base, entry->d_name, 0);
>> +            if (reti == 0) {
>> +                status = read_conf_file (path, group, type, 0);
>> +                if (status != ISC_R_SUCCESS) {
>> +                    goto exit;
>> +                }
>> +            } else {
>> +                continue;
>> +            }
>> +        }
>> +    }
>> +    closedir(d);
>> +exit:
>> +    free(buf_dir);
>> +    free(buf_base);
>> +    return status;
>> +}
>> +
>> +isc_result_t include_files(path, group, type)
>> +    const char *path;
>> +    struct group *group;
>> +    int type;
>> +{
>> +    const char    *eos;
>> +    const char    *wildcard = strchr(path, '*');
>> +    char    *p;
>> +
>> +    if (wildcard == NULL) {
>> +        return read_conf_file (path, group, type, 0);
>> +    }
>> +
>> +    eos = &path[strlen(path)];
>> +    for (wildcard++; wildcard < eos; wildcard++) {
>> +        if (*wildcard == '/') {
>> +            /* wildcard in directory, not allowed */
>> +            return DHCP_R_INVALIDARG;
>> +        }
>> +    }
>> +    return read_multiple_conf_files(path, group, type);
>> +}
>>
>>  int parse_statement (cfile, group, type, host_decl, declaration)
>>      struct parse *cfile;
>> @@ -383,7 +450,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
>>              parse_warn (cfile, "filename string expected.");
>>              skip_to_semi (cfile);
>>          } else {
>> -            status = read_conf_file (val, group, type, 0);
>> +            status = include_files(val, group, type);
>>              if (status != ISC_R_SUCCESS)
>>                  parse_warn (cfile, "%s: bad parse.", val);
>>              parse_semi (cfile);
>
> _______________________________________________
> dhcp-users mailing list
> [hidden email]
> https://lists.isc.org/mailman/listinfo/dhcp-users

_______________________________________________
dhcp-users mailing list
[hidden email]
https://lists.isc.org/mailman/listinfo/dhcp-users
Reply | Threaded
Open this post in threaded view
|

Re: [RFC ] include with wildcard filenames

Bob Harold

On Wed, Feb 28, 2018 at 4:48 AM, Ulf Samuelsson <[hidden email]> wrote:
The device consist of a master and several slaves.
Normally, the unit is installed and the slave configuration rarely changes.
Restarting the dhcp server during installation is not a problem
In many cases, the slaves never change after installation.
If the slave configuration changes, then the unit does not need to operate normally during the installation  so a few restarts are not a problem.

In this scenario, only an intruder will cause the adding to the ”untrusted” class.

I was thinking that omshell might help avoid a restart here, but I have not studied
it in detail, so this is still an unknown.

The DHCP server has a single ethernet MAC, connected directly to the switch.

There were VLANs before protecting the slaves, but they were removed for some reason, but I do not know the details.

Having wildcards still seems useful, anyway.

Best Regards,
Ulf Samuelsson

> 28 feb. 2018 kl. 09:52 skrev Bill Shirley <[hidden email]>:
>
> This sounds like the wrong approach to addressing your problem because
> for dhcpd to honor the new configuration, it would need to be restarted every
> time a file is added/deleted/changed in the wildcard directory.
>
> This sounds more like a task for iptables and ipsets.
>
> Are all four of these private networks on the same NIC?  Are these subnets
> VLANs?
>
> As far as I know, there is no mechanism to consult an source external to the
> dhcpd program for information.
>
> Bill
>
>> On 2/27/2018 5:33 PM, Ulf Samuelsson wrote:
>> I was trying out a dhcpd configuration, and found to my dismay
>> that the DHCP server did not support wildcards for include statements.
>> include "/etc/dhcp/pools/*.conf";
>> did not work.
>>
>> BACKGROUND:
>>
>> I have an application, where I want to use the DHCP server
>> as part of the authentication process for connected machines.
>>
>> I want to use three ranges.
>> pool 0 => 169.254.128.x            trusted units
>> pool 1 => 169.254.254.x            units demanding to be trusted
>> pool 2 => 169.254.1.x              normal units
>> pool 3 => 169.254.253.x            untrusted units/intruders
>>
>> The DHCP CPU Ethernet Controller communicates through a five port switch.
>> port 0: trusted units    pool 0
>> port 2: internet port
>> port 3: service port
>> port 4: CPU port    169.254.1.1
>>
>> Units connected on port 0, provides a dhcp-client-identifier indicating that they want an address in pool 0, but initially they will get a short term lease in pool 1, until it is verified that they are on port 0.
>>
>> Units without this dhcp-client-identifier, should get an address in pool 2.
>>
>> An intruder, trying to get a pool 0 address, will supply the same dhcp-client-identifier as port 0 units. They will also initially get a short term pool 1 address, but when the intrusion attempt is detected, they should be declared "untrusted". Future leases should be in pool 3.
>>
>> =====
>> When a pool 1 address is allocated, the commit event is used to run a script which will read out information from the switch and determine if the request comes from port 0.
>>
>> Request comes from (port == 0) => the mac address should be "trusted"
>> Request comes from (port != 0) => the mac address should be "untrusted".
>>
>> I define:
>> class "trusted" {
>>     match hardware;
>> }
>>
>> class "untrusted" {
>>     match hardware;
>> }
>>
>> An incoming request from "00:11:22:33:44:55" adds a file:
>> /etc/dhcp/trusted/00:11:22:33:44:55:
>>       sub-class "trusted" 1:00:11:22:33:44:55;
>> or
>> /etc/dhcp/untrusted/00:11:22:33:44:55:
>>       sub-class "trusted" 1:00:11:22:33:44:55;
>>
>>
>> When the short term pool 1 lease expires (after 1-2 minutes)
>> the new lease will be classified either as "trusted" (getting a pool 0 lease) or "untrusted" (getting a pool 3 lease).
>>
>> It would be practical to have the dhcpd.conf file contain:
>>
>> include "/etc/dhcp/trusted/*";
>> include "/etc/dhcp/untrusted/*";
>>
>> but unfortunately wildcards in include statements are not supported.
>>
>> ====================================
>>
>> I did a patch for dhcp-4.3.6 which is slightly limited.
>> It supports only wildcards on files within a single directory.
>> I.E: include "/etc/dhcp/pools/*.conf"; is supported
>> I.E: include "/etc/dhcp/*/dhcp.conf"; is not supported
>> The wildcard may not be in a directory.
>>
>> Did a small test program which tested the functionality of wildcards,
>> and then patched the dhcp server, but it has not been tested yet, as part of dhcp
>> Still would like to have peoples opinion, whether this type of functionality is desirable.
>> It is certainly possible to do this without wildcards,
>> but wildcards seems a much cleaner solution.
>> ====================================
>>
>> From dcc981f1371f390befffc950b9dc3a8107059643 Mon Sep 17 00:00:00 2001
>> From: Ulf Samuelsson <[hidden email]>
>> Date: Tue, 27 Feb 2018 21:03:52 +0100
>> Subject: [PATCH 14/14] Support wildcard in include files
>>
>> Signed-off-by: Ulf Samuelsson <[hidden email]>
>> ---
>>  includes/dhcpd.h  |  3 +++
>>  server/confpars.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>>  2 files changed, 72 insertions(+), 2 deletions(-)
>>
>> diff --git a/includes/dhcpd.h b/includes/dhcpd.h
>> index eab09a6..8208fbe 100644
>> --- a/includes/dhcpd.h
>> +++ b/includes/dhcpd.h
>> @@ -53,6 +53,9 @@
>>  #include <sys/mman.h>
>>  #include <ctype.h>
>>  #include <time.h>
>> +#include <dirent.h>
>> +#include <libgen.h>
>> +#include <fnmatch.h>
>>
>>  #include <net/if.h>
>>  #undef FDDI
>> diff --git a/server/confpars.c b/server/confpars.c
>> index c0735fe..c12f5c7 100644
>> --- a/server/confpars.c
>> +++ b/server/confpars.c
>> @@ -327,7 +327,7 @@ isc_result_t lease_file_subparse (struct parse *cfile)
>>     parameter :== DEFAULT_LEASE_TIME lease_time
>>             | MAX_LEASE_TIME lease_time
>>             | DYNAMIC_BOOTP_LEASE_CUTOFF date
>> -           | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
>> +           | DYNAMIC_BOOTP_LEASE_LENGTH l#include <string.h>ease_time
>>             | BOOT_UNKNOWN_CLIENTS boolean
>>             | ONE_LEASE_PER_CLIENT boolean
>>             | GET_LEASE_HOSTNAMES boolean
>> @@ -352,6 +352,73 @@ isc_result_t lease_file_subparse (struct parse *cfile)
>>           | VENDOR_CLASS class-declaration
>>           | USER_CLASS class-declaration
>>           | RANGE address-range-declaration */
>> +#include <string.h>
>> +isc_result_t read_multiple_conf_files(path, group, type)
>> +    const char *path;
>> +    struct group *group;
>> +    int type;
>> +{
>> +    char    *buf_dir;
>> +    char    *dir;
>> +    char    *buf_base;
>> +    char    *base;
>> +    DIR    *d;
>> +    struct    dirent *entry;
>> +    int reti;
>> +    isc_result_t status;
>> +
>> +    dir    = dirname (buf_dir    = strdup(path));
>> +    base    = basename(buf_base    = strdup(path));
>> +
>> +    if (!(d = opendir(dir))) {
>> +        status = DHCP_R_INVALIDARG;
>> +        goto    exit;
>> +    }
>> +
>> +    while ((entry = readdir(d)) != NULL) {
>> +        if (entry->d_type == DT_DIR) {
>> +            continue;
>> +        } else {
>> +            reti = fnmatch(base, entry->d_name, 0);
>> +            if (reti == 0) {
>> +                status = read_conf_file (path, group, type, 0);
>> +                if (status != ISC_R_SUCCESS) {
>> +                    goto exit;
>> +                }
>> +            } else {
>> +                continue;
>> +            }
>> +        }
>> +    }
>> +    closedir(d);
>> +exit:
>> +    free(buf_dir);
>> +    free(buf_base);
>> +    return status;
>> +}
>> +
>> +isc_result_t include_files(path, group, type)
>> +    const char *path;
>> +    struct group *group;
>> +    int type;
>> +{
>> +    const char    *eos;
>> +    const char    *wildcard = strchr(path, '*');
>> +    char    *p;
>> +
>> +    if (wildcard == NULL) {
>> +        return read_conf_file (path, group, type, 0);
>> +    }
>> +
>> +    eos = &path[strlen(path)];
>> +    for (wildcard++; wildcard < eos; wildcard++) {
>> +        if (*wildcard == '/') {
>> +            /* wildcard in directory, not allowed */
>> +            return DHCP_R_INVALIDARG;
>> +        }
>> +    }
>> +    return read_multiple_conf_files(path, group, type);
>> +}
>>
>>  int parse_statement (cfile, group, type, host_decl, declaration)
>>      struct parse *cfile;
>> @@ -383,7 +450,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
>>              parse_warn (cfile, "filename string expected.");
>>              skip_to_semi (cfile);
>>          } else {
>> -            status = read_conf_file (val, group, type, 0);
>> +            status = include_files(val, group, type);
>>              if (status != ISC_R_SUCCESS)
>>                  parse_warn (cfile, "%s: bad parse.", val);
>>              parse_semi (cfile);


omshell would be much better - it avoids restarts.  I use an appliance (BlueCat) that does it for me, so I have not scripted it myself.

If you don't use omshell, then you could simply in your scripting:
cat /etc/dhcp/pools/*.conf > /etc/dhcp/pools.conf
and then in the dhcpd.conf:
include "/etc/dhcp/pools.conf";

--
Bob Harold



_______________________________________________
dhcp-users mailing list
[hidden email]
https://lists.isc.org/mailman/listinfo/dhcp-users
Reply | Threaded
Open this post in threaded view
|

Re: [RFC ] include with wildcard filenames

Timothe Litt
In reply to this post by Ulf Samuelsson
On 28-Feb-18 04:48, [hidden email] wrote:
Message: 1
Date: Tue, 27 Feb 2018 23:33:10 +0100
From: Ulf Samuelsson [hidden email]
To: [hidden email]
Subject: [RFC ] include with wildcard filenames
Message-ID: [hidden email]
Content-Type: text/plain; charset=utf-8; format=flowed

I was trying out a dhcpd configuration, and found to my dismay
that the DHCP server did not support wildcards for include statements.
include "/etc/dhcp/pools/*.conf";
did not work.

[snip]
====================================

I did a patch for dhcp-4.3.6 which is slightly limited.
It supports only wildcards on files within a single directory.
I.E: include "/etc/dhcp/pools/*.conf"; is supported
I.E: include "/etc/dhcp/*/dhcp.conf"; is not supported
The wildcard may not be in a directory.

Did a small test program which tested the functionality of wildcards,
and then patched the dhcp server, but it has not been tested yet, as 
part of dhcp
Still would like to have peoples opinion, whether this type of 
functionality is desirable.
It is certainly possible to do this without wildcards,
but wildcards seems a much cleaner solution.
====================================
[snip]
.

Without commenting on your application, a note on your patch:

You should be aware that readdir does not order the directory entries.  They are returned in
some implementation-specific order - which is generally NOT that of a directory listing.  Commands
such as ls sort the results for presentation.

Users of config files in applications that have a wildcard option for include generally assume
that the files will be included in lexical order; e.g. foo-001.conf will be included before foo-002.conf.
This will not reliably be the case with your code.  The results will not even be deterministic on most
platforms.

If you pursue this, you should sort the results of readdir before including them.

See qsort() for a fairly portable approach.  Or look at scandir() (especially with versionsort()) for
a more convenient, if less portable approach to this.

Timothe Litt
ACM Distinguished Engineer
--------------------------
This communication may not represent the ACM or my employer's views,
if any, on the matters discussed. 

_______________________________________________
dhcp-users mailing list
[hidden email]
https://lists.isc.org/mailman/listinfo/dhcp-users

smime.p7s (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [RFC ] include with wildcard filenames

Ulf Samuelsson
Thank You.
Yes, the result should be in lexical order.
Will have a look at how to get it sorted.

Best Regards,
Ulf Samuelsson.

28 feb. 2018 kl. 23:27 skrev Timothe Litt <[hidden email]>:

On 28-Feb-18 04:48, [hidden email] wrote:
Message: 1
Date: Tue, 27 Feb 2018 23:33:10 +0100
From: Ulf Samuelsson [hidden email]
To: [hidden email]
Subject: [RFC ] include with wildcard filenames
Message-ID: [hidden email]
Content-Type: text/plain; charset=utf-8; format=flowed

I was trying out a dhcpd configuration, and found to my dismay
that the DHCP server did not support wildcards for include statements.
include "/etc/dhcp/pools/*.conf";
did not work.

[snip]
====================================

I did a patch for dhcp-4.3.6 which is slightly limited.
It supports only wildcards on files within a single directory.
I.E: include "/etc/dhcp/pools/*.conf"; is supported
I.E: include "/etc/dhcp/*/dhcp.conf"; is not supported
The wildcard may not be in a directory.

Did a small test program which tested the functionality of wildcards,
and then patched the dhcp server, but it has not been tested yet, as 
part of dhcp
Still would like to have peoples opinion, whether this type of 
functionality is desirable.
It is certainly possible to do this without wildcards,
but wildcards seems a much cleaner solution.
====================================
[snip]
.

Without commenting on your application, a note on your patch:

You should be aware that readdir does not order the directory entries.  They are returned in
some implementation-specific order - which is generally NOT that of a directory listing.  Commands
such as ls sort the results for presentation.

Users of config files in applications that have a wildcard option for include generally assume
that the files will be included in lexical order; e.g. foo-001.conf will be included before foo-002.conf.
This will not reliably be the case with your code.  The results will not even be deterministic on most
platforms.

If you pursue this, you should sort the results of readdir before including them.

See qsort() for a fairly portable approach.  Or look at scandir() (especially with versionsort()) for
a more convenient, if less portable approach to this.

Timothe Litt
ACM Distinguished Engineer
--------------------------
This communication may not represent the ACM or my employer's views,
if any, on the matters discussed. 

_______________________________________________
dhcp-users mailing list
[hidden email]
https://lists.isc.org/mailman/listinfo/dhcp-users