VirtualBox

Changeset 91769 in vbox


Ignore:
Timestamp:
Oct 15, 2021 7:24:43 PM (3 years ago)
Author:
vboxsync
Message:

VBoxNetAdp: (bugref:10077) More administrative control over network ranges

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/en_US/user_Networking.xml

    r91416 r91769  
    11851185    </note>
    11861186
     1187    <para>
     1188      On Linux, Mac OS X and Solaris &product-name; will only allow IP
     1189      addresses in 192.68.56.0/21 range to be assigned to host-only
     1190      adapters. For IPv6 only link-local addresses are allowed. If other
     1191      ranges are desired, they can be enabled by creating
     1192      <filename>/etc/vbox/networks.conf</filename> and specifying allowed
     1193      ranges there. For example, to allow 10.0.0.0/8 and 192.168.0.0/16
     1194      IPv4 ranges as well as 2001::/64 range put the following lines into
     1195      <filename>/etc/vbox/networks.conf</filename>:
     1196      <screen>
     1197      * 10.0.0.0/8 192.168.0.0/16
     1198      * 2001::/64
     1199      </screen>
     1200      Lines starting with the hash <command>#</command> are ignored. Next
     1201      example allows any addresses, effectively disabling range control:
     1202      <screen>
     1203      * 0.0.0.0/0 ::/0
     1204      </screen>
     1205      If the file exists, but no ranges are specified in it, no addresses
     1206      will be assigned to host-only adapters. The following example
     1207      effectively disables all ranges:
     1208      <screen>
     1209      # No addresses are allowed for host-only adapters
     1210      </screen>
     1211    </para>
     1212
    11871213  </sect1>
    11881214
  • trunk/src/VBox/HostDrivers/adpctl/Makefile.kmk

    r82968 r91769  
    2121include $(KBUILD_PATH)/subheader.kmk
    2222
    23 PROGRAMS              += VBoxNetAdpCtl
     23PROGRAMS               += VBoxNetAdpCtl
    2424### Another template? We must *not* set RPATH!
    25 VBoxNetAdpCtl_TEMPLATE = VBOXR3HARDENEDEXE
    26 VBoxNetAdpCtl_SOURCES  = VBoxNetAdpCtl.cpp
     25ifneq ($(KBUILD_TYPE),debug)
     26 VBoxNetAdpCtl_TEMPLATE = VBoxR3SetUidToRoot
     27 VBoxNetAdpCtl_LIBS    += $(LIB_RUNTIME)
     28else
     29 VBoxNetAdpCtl_TEMPLATE = VBoxR3Static
     30endif
     31VBoxNetAdpCtl_SOURCES   = VBoxNetAdpCtl.cpp
    2732
    2833include $(FILE_KBUILD_SUB_FOOTER)
  • trunk/src/VBox/HostDrivers/adpctl/VBoxNetAdpCtl.cpp

    r90773 r91769  
    3333#include <sys/stat.h>
    3434#include <fcntl.h>
     35
     36#include <iprt/err.h>
     37#include <iprt/initterm.h>
     38#include <iprt/message.h>
     39#include <iprt/net.h>
     40#include <iprt/string.h>
     41#include <iprt/uint128.h>
     42
    3543#ifdef RT_OS_LINUX
    3644# include <arpa/inet.h>
     
    4957# include <sys/ioccom.h>
    5058#endif
    51 
    52 #define NOREF(x) (void)x
    5359
    5460/** @todo Error codes must be moved to some header file */
     
    729735
    730736/*********************************************************************************************************************************
     737*   Global config file implementation                                                                                            *
     738*********************************************************************************************************************************/
     739
     740#define VBOX_GLOBAL_NETWORK_CONFIG_PATH "/etc/vbox/networks.conf"
     741#define VBOXNET_DEFAULT_IPV4MASK "255.255.255.0"
     742
     743class NetworkAddress
     744{
     745    public:
     746        bool isValidString(const char *pcszNetwork);
     747        bool isValid() { return m_fValid; };
     748        virtual bool matches(const char *pcszNetwork) = 0;
     749        virtual const char *defaultNetwork() = 0;
     750    protected:
     751        bool m_fValid;
     752
     753        int RTNetStrToIPv4CidrWithZeroPrefixAllowed(const char *pcszAddr, PRTNETADDRIPV4 pAddr, int *piPrefix);
     754        int RTNetStrToIPv6CidrWithZeroPrefixAllowed(const char *pcszAddr, PRTNETADDRIPV6 pAddr, int *piPrefix);
     755};
     756
     757int NetworkAddress::RTNetStrToIPv4CidrWithZeroPrefixAllowed(const char *pcszAddr, PRTNETADDRIPV4 pAddr, int *piPrefix)
     758{
     759    RTNETADDRIPV4 addr;
     760    char *pszNext;
     761
     762    AssertPtrReturn(pcszAddr, VERR_INVALID_PARAMETER);
     763    AssertPtrReturn(pAddr, VERR_INVALID_PARAMETER);
     764    AssertPtrReturn(piPrefix, VERR_INVALID_PARAMETER);
     765
     766    pcszAddr = RTStrStripL(pcszAddr);
     767    int rc = RTNetStrToIPv4AddrEx(pcszAddr, &addr, &pszNext);
     768    if (RT_FAILURE(rc))
     769        return rc;
     770
     771    /*
     772     * If the prefix is missing, treat is as exact (/32) address
     773     * specification.
     774     */
     775    if (*pszNext == '\0' || rc == VWRN_TRAILING_SPACES)
     776    {
     777        *pAddr = addr;
     778        *piPrefix = 32;
     779        return VINF_SUCCESS;
     780    }
     781
     782    if (*pszNext == '/')
     783        ++pszNext;
     784    else
     785        return VERR_INVALID_PARAMETER;
     786
     787    uint32_t prefix;
     788    rc = RTStrToUInt32Ex(pszNext, &pszNext, 16, &prefix);
     789    if ((rc == VINF_SUCCESS || rc == VWRN_TRAILING_SPACES) && prefix == 0)
     790    {
     791        *pAddr = addr;
     792        *piPrefix = 0;
     793        return VINF_SUCCESS;
     794    }
     795    return RTNetStrToIPv4Cidr(pcszAddr, pAddr, piPrefix);
     796}
     797
     798RTDECL(int) NetworkAddress::RTNetStrToIPv6CidrWithZeroPrefixAllowed(const char *pcszAddr, PRTNETADDRIPV6 pAddr, int *piPrefix)
     799{
     800    RTNETADDRIPV6 Addr;
     801    uint8_t u8Prefix;
     802    char *pszNext;
     803    int rc;
     804
     805    AssertPtrReturn(pcszAddr, VERR_INVALID_PARAMETER);
     806    AssertPtrReturn(pAddr, VERR_INVALID_PARAMETER);
     807    AssertPtrReturn(piPrefix, VERR_INVALID_PARAMETER);
     808
     809    pcszAddr = RTStrStripL(pcszAddr);
     810    rc = RTNetStrToIPv6AddrEx(pcszAddr, &Addr, &pszNext);
     811    if (RT_FAILURE(rc))
     812        return rc;
     813
     814    /*
     815     * If the prefix is missing, treat is as exact (/128) address
     816     * specification.
     817     */
     818    if (*pszNext == '\0' || rc == VWRN_TRAILING_SPACES)
     819    {
     820        *pAddr = Addr;
     821        *piPrefix = 128;
     822        return VINF_SUCCESS;
     823    }
     824
     825    if (*pszNext != '/')
     826        return VERR_INVALID_PARAMETER;
     827
     828    ++pszNext;
     829    rc = RTStrToUInt8Ex(pszNext, &pszNext, 10, &u8Prefix);
     830    if (RT_FAILURE(rc) || rc == VWRN_TRAILING_CHARS)
     831        return VERR_INVALID_PARAMETER;
     832
     833    if (u8Prefix > 128)
     834        return VERR_INVALID_PARAMETER;
     835
     836    *pAddr = Addr;
     837    *piPrefix = u8Prefix;
     838    return VINF_SUCCESS;
     839}
     840
     841bool NetworkAddress::isValidString(const char *pcszNetwork)
     842{
     843    RTNETADDRIPV4 addrv4;
     844    RTNETADDRIPV6 addrv6;
     845    int prefix;
     846    int rc = RTNetStrToIPv4CidrWithZeroPrefixAllowed(pcszNetwork, &addrv4, &prefix);
     847    if (RT_SUCCESS(rc))
     848        return true;
     849    rc = RTNetStrToIPv6CidrWithZeroPrefixAllowed(pcszNetwork, &addrv6, &prefix);
     850    return RT_SUCCESS(rc);
     851}
     852
     853class NetworkAddressIPv4 : public NetworkAddress
     854{
     855    public:
     856        NetworkAddressIPv4(const char *pcszIpAddress, const char *pcszNetMask = VBOXNET_DEFAULT_IPV4MASK);
     857        virtual bool matches(const char *pcszNetwork);
     858        virtual const char *defaultNetwork() { return "192.168.56.1/21"; }; /* Matches defaults in VBox/Main/include/netif.h, see @bugref{10077}. */
     859
     860    private:
     861        RTNETADDRIPV4 m_address;
     862        int m_prefix;
     863};
     864
     865NetworkAddressIPv4::NetworkAddressIPv4(const char *pcszIpAddress, const char *pcszNetMask)
     866{
     867    int rc = RTNetStrToIPv4Addr(pcszIpAddress, &m_address);
     868    if (RT_SUCCESS(rc))
     869    {
     870        RTNETADDRIPV4 mask;
     871        rc = RTNetStrToIPv4Addr(pcszNetMask, &mask);
     872        if (RT_FAILURE(rc))
     873            m_fValid = false;
     874        else
     875            rc = RTNetMaskToPrefixIPv4(&mask, &m_prefix);
     876    }
     877#if 0 /* cmd.set() does not support CIDR syntax */
     878    else
     879        rc = RTNetStrToIPv4Cidr(pcszIpAddress, &m_address, &m_prefix);
     880#endif
     881    m_fValid = RT_SUCCESS(rc);
     882}
     883
     884bool NetworkAddressIPv4::matches(const char *pcszNetwork)
     885{
     886    RTNETADDRIPV4 allowedNet, allowedMask;
     887    int allowedPrefix;
     888    int rc = RTNetStrToIPv4CidrWithZeroPrefixAllowed(pcszNetwork, &allowedNet, &allowedPrefix);
     889    if (RT_SUCCESS(rc))
     890        rc = RTNetPrefixToMaskIPv4(allowedPrefix, &allowedMask);
     891    if (RT_FAILURE(rc))
     892        return false;
     893    return m_prefix >= allowedPrefix && (m_address.au32[0] & allowedMask.au32[0]) == (allowedNet.au32[0] & allowedMask.au32[0]);
     894}
     895
     896class NetworkAddressIPv6 : public NetworkAddress
     897{
     898    public:
     899        NetworkAddressIPv6(const char *pcszIpAddress);
     900        virtual bool matches(const char *pcszNetwork);
     901        virtual const char *defaultNetwork() { return "FE80::/10"; };
     902    private:
     903        RTNETADDRIPV6 m_address;
     904        int m_prefix;
     905};
     906
     907NetworkAddressIPv6::NetworkAddressIPv6(const char *pcszIpAddress)
     908{
     909    int rc = RTNetStrToIPv6Cidr(pcszIpAddress, &m_address, &m_prefix);
     910    m_fValid = RT_SUCCESS(rc);
     911}
     912
     913bool NetworkAddressIPv6::matches(const char *pcszNetwork)
     914{
     915    RTNETADDRIPV6 allowedNet, allowedMask;
     916    int allowedPrefix;
     917    int rc = RTNetStrToIPv6CidrWithZeroPrefixAllowed(pcszNetwork, &allowedNet, &allowedPrefix);
     918    if (RT_SUCCESS(rc))
     919        rc = RTNetPrefixToMaskIPv6(allowedPrefix, &allowedMask);
     920    if (RT_FAILURE(rc))
     921        return false;
     922    RTUINT128U u128Provided, u128Allowed;
     923    return m_prefix >= allowedPrefix
     924        && RTUInt128Compare(RTUInt128And(&u128Provided, &m_address, &allowedMask), RTUInt128And(&u128Allowed, &allowedNet, &allowedMask)) == 0;
     925}
     926
     927
     928class GlobalNetworkPermissionsConfig
     929{
     930    public:
     931        bool forbids(const char *pcszIpAddress); /* address or address with mask in cidr */
     932        bool forbids(const char *pcszIpAddress, const char *pcszNetMask);
     933
     934    private:
     935        bool forbids(NetworkAddress& address);
     936};
     937
     938bool GlobalNetworkPermissionsConfig::forbids(const char *pcszIpAddress)
     939{
     940    NetworkAddressIPv6 addrv6(pcszIpAddress);
     941
     942    if (addrv6.isValid())
     943        return forbids(addrv6);
     944
     945    NetworkAddressIPv4 addrv4(pcszIpAddress);
     946
     947    if (addrv4.isValid())
     948        return forbids(addrv4);
     949
     950    fprintf(stderr, "Error: invalid address '%s'\n", pcszIpAddress);
     951    return true;
     952}
     953
     954bool GlobalNetworkPermissionsConfig::forbids(const char *pcszIpAddress, const char *pcszNetMask)
     955{
     956    NetworkAddressIPv4 addrv4(pcszIpAddress, pcszNetMask);
     957
     958    if (addrv4.isValid())
     959        return forbids(addrv4);
     960
     961    fprintf(stderr, "Error: invalid address '%s' with mask '%s'\n", pcszIpAddress, pcszNetMask);
     962    return true;
     963}
     964
     965bool GlobalNetworkPermissionsConfig::forbids(NetworkAddress& address)
     966{
     967    FILE *fp = fopen(VBOX_GLOBAL_NETWORK_CONFIG_PATH, "r");
     968    if (!fp)
     969    {
     970        if (verbose)
     971            fprintf(stderr, "Info: matching against default '%s' => %s\n", address.defaultNetwork(),
     972                address.matches(address.defaultNetwork()) ? "MATCH" : "no match");
     973        return !address.matches(address.defaultNetwork());
     974    }
     975
     976    char *pszToken, szLine[1024];
     977    for (int line = 1; fgets(szLine, sizeof(szLine), fp); ++line)
     978    {
     979        /* Skip anything except '*' lines */
     980        if (strcmp("*", strtok(szLine, " \t\n")))
     981            continue;
     982        /* Match the specified address against each network */
     983        while ((pszToken = strtok(NULL, " \t\n")) != NULL)
     984        {
     985            if (!address.isValidString(pszToken))
     986            {
     987                fprintf(stderr, "Warning: %s(%d) invalid network '%s'\n", VBOX_GLOBAL_NETWORK_CONFIG_PATH, line, pszToken);
     988                continue;
     989            }
     990            if (verbose)
     991                fprintf(stderr, "Info: %s(%d) matching against '%s' => %s\n", VBOX_GLOBAL_NETWORK_CONFIG_PATH, line, pszToken,
     992                    address.matches(pszToken) ? "MATCH" : "no match");
     993            if (address.matches(pszToken))
     994                return false;
     995        }
     996    }
     997    fclose(fp);
     998    return true;
     999}
     1000
     1001
     1002/*********************************************************************************************************************************
    7311003*   Main logic, argument parsing, etc.                                                                                           *
    7321004*********************************************************************************************************************************/
     
    7561028{
    7571029    char szAdapterName[VBOXNETADP_MAX_NAME_LEN];
    758     int rc;
     1030    int rc = RTR3InitExe(argc, &argv, 0 /*fFlags*/);
     1031    if (RT_FAILURE(rc))
     1032        return RTMsgInitFailure(rc);
     1033
    7591034
    7601035    AddressCommand& cmd = chooseAddressCommand();
     
    8991174    const char * const keyword = argv[2];
    9001175
     1176    GlobalNetworkPermissionsConfig config;
    9011177
    9021178    /*
     
    9051181    if (keyword == NULL)
    9061182    {
     1183        if (config.forbids(addr))
     1184        {
     1185            fprintf(stderr, "Error: permission denied\n");
     1186            return -VERR_ACCESS_DENIED;
     1187        }
     1188
    9071189        return cmd.set(ifname, addr);
    9081190    }
     
    9171199
    9181200        const char * const mask = argv[3];
     1201        if (config.forbids(addr, mask))
     1202        {
     1203            fprintf(stderr, "Error: permission denied\n");
     1204            return -VERR_ACCESS_DENIED;
     1205        }
     1206
    9191207        return cmd.set(ifname, addr, mask);
    9201208    }
  • trunk/src/VBox/Main/src-server/HostNetworkInterfaceImpl.cpp

    r91503 r91769  
    603603            {
    604604                LogRel(("Failed to EnableStaticIpConfig with rc=%Rrc\n", rc));
    605                 return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : E_FAIL;
     605                return rc == VERR_NOT_IMPLEMENTED ? E_NOTIMPL : (rc == VERR_ACCESS_DENIED ? E_ACCESSDENIED : E_FAIL);
    606606            }
    607607
  • trunk/src/VBox/Main/src-server/generic/NetIf-generic.cpp

    r91503 r91769  
    8181            LogRel(("NetIfAdpCtl: failed to create process for %s: iStats=%d enmReason=%d\n",
    8282                    szAdpCtl, Status.iStatus, Status.enmReason));
    83             rc = VERR_GENERAL_FAILURE;
     83            rc = -Status.iStatus;
    8484        }
    8585    }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette