From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by mx.groups.io with SMTP id smtpd.web11.886.1570653274041153490 for ; Wed, 09 Oct 2019 13:34:35 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@infradead.org header.s=merlin.20170209 header.b=1gumvYdi; spf=none, err=permanent DNS error (domain: merlin.srs.infradead.org, ip: 205.233.59.134, mailfrom: batv+0916131553139b357411+5890+infradead.org+dwmw2@merlin.srs.infradead.org) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Message-ID:From:CC:To:Subject: Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To: Date:Sender:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=d+F9ZmWGZHSkEgClr/QyvL2/nO62OOe0Owgxg9ko4no=; b=1gumvYdiD/qKThJAm7A+srAz7z 7MxVuUMnzN8+00JE6pjh8GEdr46MH5wz0etdgXtLlxmBc9P867YFCTcZ9SMR4xskSqB+G18QsOong nUQZGTkMDDBFmK5RyafePDi6R9XAWn8Q/lp//IQPmNbWVhzfhTfHPXcbJq12/PSg8mmrgQsNjAx/+ a7MLOCz9yMhReRy12C3I5Vr99WmaVKjn26eCXjGerVJIOCNweWY85PprJH74XXewuP7az0eDjgpwS mqfBKYxQ0P2rf2qZ4d/5H0S6gfMaXdWhmr+q0chYW8lGwn/DI7B4QU/hxPtFRMYhV4NqYrMtw0ry7 s7WKsTTg==; Received: from [2001:8b0:10b:1:48d6:ff6d:fd14:b98f] by merlin.infradead.org with esmtpsa (Exim 4.92.2 #3 (Red Hat Linux)) id 1iIIfA-00087n-ME; Wed, 09 Oct 2019 20:34:25 +0000 Date: Wed, 09 Oct 2019 21:34:21 +0100 User-Agent: K-9 Mail for Android In-Reply-To: <6bb5d2f6-ec6f-1766-e19b-03fd45c1bc12@redhat.com> References: <20190927034441.3096-1-Jiaxin.wu@intel.com> <69774fe6-ea00-44b9-5468-c092dea6cd36@redhat.com> <8106467c9f4132c831d0aa604e897fe9d4dda12a.camel@infradead.org> <895558F6EA4E3B41AC93A00D163B727416F5D921@SHSMSX107.ccr.corp.intel.com> <777053db79600eb90a19945700293d14f4978344.camel@infradead.org> <6bb5d2f6-ec6f-1766-e19b-03fd45c1bc12@redhat.com> MIME-Version: 1.0 Subject: Re: [edk2-devel] [PATCH v1 0/4] Support HTTPS HostName validation feature(CVE-2019-14553) To: Laszlo Ersek ,"Wu, Jiaxin" ,"devel@edk2.groups.io" ,"Wang, Jian J" ,Bret Barkelew CC: Richard Levitte From: "David Woodhouse" Message-ID: <9A4966EE-76CD-465C-A6CA-70DD9E38D834@infradead.org> X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Content-Type: multipart/alternative; boundary="----YMS4WWKV9XXMSRLHFO6KTCVQGIUBGY" Content-Transfer-Encoding: 7bit ------YMS4WWKV9XXMSRLHFO6KTCVQGIUBGY Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Can you show result of 'openssl x509 -noout -text -in xxxxxx=2Epem' on your= certs please=2E Would like to check if you really have a cert for the hostname string "192= =2E168=2E124=2E2" or to the IP address=2E They are different things=2E On 9 October 2019 21:24:34 BST, Laszlo Ersek wrote: >Hi All, > >(multi-hour composition ahead=2E=2E=2E) > >On 10/09/19 09:53, David Woodhouse wrote: >> On Tue, 2019-10-08 at 06:19 +0000, Wu, Jiaxin wrote: >>> Hi David, >>> >>> I just realized you have the comments on Bugzilla 960: >>> >>>> "=2E=2E=2Egiven that testing is failing and code inspection shows it >>>> would never have been expected to work=2E" >>> >>> Do you mean you didn't pass the verification if URLs with IPv6 >>> literals (https://[2001:8b0:10b:1236::1]/)? Can you also show me >>> where the code inspection indicated it would never have been >expected >>> to work? We do pass the testing for the URLs with IPv6 if the CN or >>> SAN in certificate has the corresponding IPv6 address (at least >>> working with openssl 1=2E1=2E0)=2E >> >> I have not tested this, but I started looking when there was a >message >> on the edk2 list from someone who was reporting that it didn't work >> for IPv6 URIs, IIRC=2E >> >> You are using SSL_set1_host(), and I believe you're just passing in >> the bare hostname part of the URI, be it "1=2E2=2E3=2E4" or >> "[2001:8b0:10b::5]"=2E >> >> That just adds it to the 'hosts' list in the X509_VERIFY_PARAM for >the >> SSL connection=2E >> >> In the check_hosts() function in openssl/crypto/x509/v509_vfy=2Ec, the >> code simply iterates over the members of that list, calling >> X509_check_host() for each one=2E It never calls X509_check_ip()=2E >> >> If you look in openssl/crypto/x509/v3_utl=2Ec you can see the >> X509_check_host() really does only check hostnames=2E You'd need to >call >> X509_check_ip_asc() to check hostnames=2E And something would need to >> have stripped the [] which surround an IPv6 literal=2E >> >> I can't see how this can work=2E Have you tested it since the report on >> the list that it wasn't working? >> >> cf=2E https://github=2Ecom/openssl/openssl/pull/9201 which is being >> ignored by the OpenSSL developers =14 OpenSSL really doesn't make >> life easy for you here, which is a shame=2E >> >> >>> For the series patches here, we are intending to support the host >>> name validation, I think we can commit the series patches since we >>> pass the verification of IPV6 URL, what do you think? >> >> If it passes the verification of IPv6 literals, then all my analysis >> is broken and so was the report on the list that prompted me to start >> looking (or I'm misremembering that report)=2E In that case, sure, go >> ahead and commit=2E > >Here's a summary of my setup=2E > >* I've generated a brand new CA certificate, and two HTTP server > certificates, signed by the CA=2E > >* One HTTP server certificate is for Common Name =3D 192=2E168=2E124=2E2 > >* The other HTTP server certificate is for Common Name =3D > fd33:eb1b:9b36::2 > >* I have a "net-server" virtual machine that runs Apache on the above >IP > addresses (TCP port 443)=2E > > - This virtual machine also runs DHCP (v4) and DHCP (v6) daemons=2E > > - The DHCP servers send the following boot file names: > >- "https://192=2E168=2E124=2E2/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot= =2Eiso" =20 > [IPv4] >- >"https://[fd33:eb1b:9b36::2]/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot= =2Eiso" >[IPv6] > >* For sanity-checking the environment, I run the following two commands > on the *host* (connecting to the "net-server" virtual machine): > >- curl -I >'https://192=2E168=2E124=2E2/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot= =2Eiso' >- curl --globoff -I >'https://[fd33:eb1b:9b36::2]/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot= =2Eiso' > > - The host is configured to trust the brand new test CA certificate > (see near the top)=2E > > - When the certificates are assigned *correctly* to the IP addresses > in the Apache configuration, the above "curl" commands complete just > fine=2E If I add the "-v" option to "curl", it confirms the right > certificates are used, and it confirms the test CA as issuer too=2E > > - When the certificates are (intentionally) *cross-assigned* to the IP > addresses in the Apache configuration, then both "curl" commands > break with the following error message: > >> curl: (51) Unable to communicate securely with peer: requested domain >> name does not match the server's certificate=2E > > - If I add the "-v" option, I also see > >> NSS error -12276 (SSL_ERROR_BAD_CERT_DOMAIN) > > - As a side comment: Apache itself warns about the misconfig, in > "/var/log/httpd/ssl_error_log": > >> =2E=2E=2E [ssl:warn] =2E=2E=2E AH01909: RSA certificate configured for = =2E=2E=2E:443 >> does NOT include an ID which matches the server name > >* I have a "net-client" virtual machine, running OVMF=2E > > - The edk2 HTTPS/TLS client booting in this virtual machine is > configured to trust the exact same set of CA certificates that the > host trusts too=2E > > - In other words, HTTPS boot in the "net-client" VM accepts server > certificates signed by the new test CA=2E > >* The following is the test plan=2E > >1=2E The patch set is *not* applied (that is, OVMF is built at current > master, commit 976d0353a6ce)=2E > > 1=2E Properly assigned certificates: > > 1=2E HTTPSv4 boot --> expect success (correct behavior, establishes > baseline) > > 2=2E HTTPSv6 boot --> expect success (correct behavior, establishes > baseline) > > 2=2E Cross-assigned certificates: > > 1=2E HTTPSv4 boot --> expect success (for reproducing the bug) > > 2=2E HTTPSv6 boot --> expect success (for reproducing the bug) > >2=2E With the patch set applied: > > 1=2E Properly assigned certificates: > > 1=2E HTTPSv4 boot --> expect success (failure means a regression) > > 2=2E HTTPSv6 boot --> expect success (failure means a regression) > > 2=2E Cross-assigned certificates: > > 1=2E HTTPSv4 boot --> expect failure (for verifying the bugfix) > > 2=2E HTTPSv6 boot --> expect failure (for verifying the bugfix) > >* Results: > >- 1=2E1=2E1=2E as expected (HTTPSv4 baseline established) >- 1=2E1=2E2=2E as expected (HTTPSv6 baseline established) >- 1=2E2=2E1=2E as expected (HTTPSv4 MITM bug reproduced) >- 1=2E2=2E2=2E as expected (HTTPSv6 MITM bug reproduced) >- 2=2E1=2E1=2E as expected (HTTPSv4 not regressed by series) >- 2=2E1=2E2=2E as expected (HTTPSv6 not regressed by series) >- 2=2E2=2E1=2E as expected (HTTPSv4 MITM averted) >- 2=2E2=2E2=2E as expected (HTTPSv6 MITM averted) > >* In cases 2=2E2=2E1=2E and 2=2E2=2E2=2E: > >- The UEFI console contains, respectively: > >> >>Start HTTP Boot over IPv4=2E=2E=2E=2E >> Station IP address is 192=2E168=2E124=2E106 >> >> URI: >https://192=2E168=2E124=2E2/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot=2E= iso >> >> Error: Could not retrieve NBP file size from HTTP server=2E >> >> Error: Unexpected network error=2E > >> >>Start HTTP Boot over IPv6=2E=2E=2E=2E >> Station IPv6 address is FD33:EB1B:9B36:0:0:0:0:C8 >> >> URI: >https://[fd33:eb1b:9b36::2]/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot=2E= iso >> >> Error: Could not retrieve NBP file size from HTTP server=2E >> >> Error: Unexpected network error=2E > >- The OVMF log contains (in both cases): > >> TlsDoHandshake SSL_HANDSHAKE_ERROR State=3D0x4 SSL_ERROR_SSL >> TlsDoHandshake ERROR 0x1416F086=3DL14:F16F:R86 > >- Decoding: > > - Library 0x14 -> ERR_LIB_SSL > - Function 0x16F -> SSL_F_TLS_PROCESS_SERVER_CERTIFICATE > - Reason 0x86 -> SSL_R_CERTIFICATE_VERIFY_FAILED > > - So this means that the ssl_verify_cert_chain() call fails in the > tls_process_server_certificate() function, in > "CryptoPkg/Library/OpensslLib/openssl/ssl/statem/statem_clnt=2Ec"=2E > > >Normally the above would be sufficient for me to give a "Tested-by" for >this patch set=2E > >But now I'm uncertain whether (a) my results contradict David's >analysis, or (b) I tested something that David's analysis doesn't >*apply* to=2E (IOW if my test plan doesn't actually verify "IPv6 >literals"=2E) > > >FWIW, the brackets in the IPv6 notation are stripped in >EfiHttpRequest() >[NetworkPkg/HttpDxe/HttpImpl=2Ec], using the "HostName" local variable=2E >(The stripping comes from earlier commit 7191827f90b4 >("NetworkPkg/HttpDxe: Strip square brackets in IPv6 expressed >HostName=2E", 2018-08-03)=2E) Later in EfiHttpRequest(), >"HttpInstance->RemoteHost" is assigned "HostName"=2E > >Further, in TlsConfigureSession() [NetworkPkg/HttpDxe/HttpsSupport=2Ec], >we set "HttpInstance->TlsConfigData=2EVerifyHost=2EHostName" to >"HttpInstance->RemoteHost"=2E This is done in patch#4=2E > >Also in patch#4, in the same function, we pass >"HttpInstance->TlsConfigData=2EVerifyHost" to SetSessionData(), from >patch#3=2E > >There we pass "TlsVerifyHost->HostName" to TlsSetVerifyHost(), which >resides in patch#2=2E > >At that point, we pass the hostname -- the IPv6 address, with the >brackets stripped -- to SSL_set1_host()=2E > >So, my take is that the comparison is done simply on the textual >representation (with the IPv6 brackets stripped), not the numerical >value=2E > >Is that bad? The textual comparison may certainly report a mismatch >when >the numerical values actually match (for an IPv4 example, "192=2E168=2E0= =2E1" >would not match "192=2E168=2E000=2E001")=2E But that errs in the safe >direction, >does it not? > >Thanks! >Laszlo --=20 Sent from my Android device with K-9 Mail=2E Please excuse my brevity=2E ------YMS4WWKV9XXMSRLHFO6KTCVQGIUBGY Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable Can you show result of 'openssl x509 -noout -text = -in xxxxxx=2Epem' on your certs please=2E

Would like to check if you= really have a cert for the hostname string "192=2E168=2E124=2E2" or to the= IP address=2E They are different things=2E


On 9 October 2019 21:24:34 BST, Laszlo Ersek <lersek@redhat=2Ecom= > wrote:
Hi All,

(multi-hour composition ahead=2E=2E= =2E)

On 10/09/19 09:53, David Woodhouse wrote:
On Tue, 2019-10-08 at 06:19 +0000, Wu, Jiax= in wrote:
Hi David,
I just realized you have the comments on Bugzilla 960:

"=2E=2E=2Egiven that testing is f= ailing and code inspection shows it
would never have been expected to wo= rk=2E"

Do you mean you didn't pass the verification if= URLs with IPv6
literals (https://[2001:8b0:10b:1236::1]/)? Can you also show me
where the = code inspection indicated it would never have been expected
to work? We= do pass the testing for the URLs with IPv6 if the CN or
SAN in certifi= cate has the corresponding IPv6 address (at least
working with openssl = 1=2E1=2E0)=2E

I have not tested this, but I started lo= oking when there was a message
on the edk2 list from someone who was re= porting that it didn't work
for IPv6 URIs, IIRC=2E

You are usin= g SSL_set1_host(), and I believe you're just passing in
the bare hostna= me part of the URI, be it "1=2E2=2E3=2E4" or
"[2001:8b0:10b::5]"=2E
=
That just adds it to the 'hosts' list in the X509_VERIFY_PARAM for the=
SSL connection=2E

In the check_hosts() function in openssl/cry= pto/x509/v509_vfy=2Ec, the
code simply iterates over the members of tha= t list, calling
X509_check_host() for each one=2E It never calls X509_c= heck_ip()=2E

If you look in openssl/crypto/x509/v3_utl=2Ec you can = see the
X509_check_host() really does only check hostnames=2E You'd nee= d to call
X509_check_ip_asc() to check hostnames=2E And something would= need to
have stripped the [] which surround an IPv6 literal=2E

= I can't see how this can work=2E Have you tested it since the report on the list that it wasn't working?

cf=2E https://github=2Ecom/openssl/openssl/pull= /9201 which is being
ignored by the OpenSSL developers =14 OpenSSL = really doesn't make
life easy for you here, which is a shame=2E

=
For the series patches= here, we are intending to support the host
name validation, I think we = can commit the series patches since we
pass the verification of IPV6 URL= , what do you think?

If it passes the verification of = IPv6 literals, then all my analysis
is broken and so was the report on = the list that prompted me to start
looking (or I'm misremembering that = report)=2E In that case, sure, go
ahead and commit=2E
<= br>Here's a summary of my setup=2E

* I've generated a brand new CA c= ertificate, and two HTTP server
certificates, signed by the CA=2E
<= br>* One HTTP server certificate is for Common Name =3D 192=2E168=2E124=2E2=

* The other HTTP server certificate is for Common Name =3D
fd3= 3:eb1b:9b36::2

* I have a "net-server" virtual machine that runs Apa= che on the above IP
addresses (TCP port 443)=2E

- This virtua= l machine also runs DHCP (v4) and DHCP (v6) daemons=2E

- The DHCP = servers send the following boot file names:

- "https://192=2E168= =2E124=2E2/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot=2Eiso" [IPv4] - "https://[fd33:eb1b:9b36::2]/RHEL-7=2E4-20170711=2E0-Server-x86_64-= boot=2Eiso" [IPv6]

* For sanity-checking the environment, I run the = following two commands
on the *host* (connecting to the "net-server" v= irtual machine):

- curl -I 'https://192=2E168=2E124=2E2/= RHEL-7=2E4-20170711=2E0-Server-x86_64-boot=2Eiso'
- curl --globoff -I = 'https://[fd33:eb1b:9b36::2]/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot=2Ei= so'

- The host is configured to trust the brand new test CA certif= icate
(see near the top)=2E

- When the certificates are ass= igned *correctly* to the IP addresses
in the Apache configuration, t= he above "curl" commands complete just
fine=2E If I add the "-v" opt= ion to "curl", it confirms the right
certificates are used, and it c= onfirms the test CA as issuer too=2E

- When the certificates are (= intentionally) *cross-assigned* to the IP
addresses in the Apache co= nfiguration, then both "curl" commands
break with the following erro= r message:

curl: (5= 1) Unable to communicate securely with peer: requested domain
name does = not match the server's certificate=2E

- If I add the = "-v" option, I also see

NSS error -12276 (SSL_ERROR_BAD_CERT_DOMAIN)

- A= s a side comment: Apache itself warns about the misconfig, in
"/var/= log/httpd/ssl_error_log":

=2E=2E=2E [ssl:warn] =2E=2E=2E AH01909: RSA certificate configured f= or =2E=2E=2E:443
does NOT include an ID which matches the server name

* I have a "net-client" virtual machine, running OVMF=2E<= br>
- The edk2 HTTPS/TLS client booting in this virtual machine is
= configured to trust the exact same set of CA certificates that the
= host trusts too=2E

- In other words, HTTPS boot in the "net-cli= ent" VM accepts server
certificates signed by the new test CA=2E
=
* The following is the test plan=2E

1=2E The patch set is *not* = applied (that is, OVMF is built at current
master, commit 976d0353a6c= e)=2E

1=2E Properly assigned certificates:

1=2E HTTPSv4= boot --> expect success (correct behavior, establishes
= baseline)

2=2E HTTPSv6 boot --> ex= pect success (correct behavior, establishes
= baseline)

2=2E Cross-assigned certificates:

= 1=2E HTTPSv4 boot --> expect success (for reproducing the bug)

= 2=2E HTTPSv6 boot --> expect success (for reproducing the bug)
2=2E With the patch set applied:

1=2E Properly assigned certifica= tes:

1=2E HTTPSv4 boot --> expect success (failure means a re= gression)

2=2E HTTPSv6 boot --> expect success (failure means= a regression)

2=2E Cross-assigned certificates:

1=2E H= TTPSv4 boot --> expect failure (for verifying the bugfix)

2= =2E HTTPSv6 boot --> expect failure (for verifying the bugfix)

* = Results:

- 1=2E1=2E1=2E as expected (HTTPSv4 baseline established)- 1=2E1=2E2=2E as expected (HTTPSv6 baseline established)
- 1=2E2=2E1= =2E as expected (HTTPSv4 MITM bug reproduced)
- 1=2E2=2E2=2E as expected= (HTTPSv6 MITM bug reproduced)
- 2=2E1=2E1=2E as expected (HTTPSv4 not r= egressed by series)
- 2=2E1=2E2=2E as expected (HTTPSv6 not regressed by= series)
- 2=2E2=2E1=2E as expected (HTTPSv4 MITM averted)
- 2=2E2=2E= 2=2E as expected (HTTPSv6 MITM averted)

* In cases 2=2E2=2E1=2E and = 2=2E2=2E2=2E:

- The UEFI console contains, respectively:

Start H= TTP Boot over IPv4=2E=2E=2E=2E
Station IP a= ddress is 192=2E168=2E124=2E106

URI: https://192=2E= 168=2E124=2E2/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot=2Eiso

= Error: Could not retrieve NBP file size from HTTP server=2E

Err= or: Unexpected network error=2E

=
Start HTTP Boot over IPv6= =2E=2E=2E=2E
Station IPv6 address is FD33:E= B1B:9B36:0:0:0:0:C8

URI: https://[fd33:eb1b:9b36::2= ]/RHEL-7=2E4-20170711=2E0-Server-x86_64-boot=2Eiso

Error: Cou= ld not retrieve NBP file size from HTTP server=2E

Error: Unexpect= ed network error=2E

- The OVMF log contains (in both ca= ses):

TlsDoHandshak= e SSL_HANDSHAKE_ERROR State=3D0x4 SSL_ERROR_SSL
TlsDoHandshake ERROR 0x1= 416F086=3DL14:F16F:R86

- Decoding:

- Library = 0x14 -> ERR_LIB_SSL
- Function 0x16F -> SSL_F_TLS_PROCESS_SERVE= R_CERTIFICATE
- Reason 0x86 -> SSL_R_CERTIFICATE_VERIFY_FAILED
- So this means that the ssl_verify_cert_chain() call fails in the<= br> tls_process_server_certificate() function, in
"CryptoPkg/Libr= ary/OpensslLib/openssl/ssl/statem/statem_clnt=2Ec"=2E


Normally t= he above would be sufficient for me to give a "Tested-by" for
this patch= set=2E

But now I'm uncertain whether (a) my results contradict Davi= d's
analysis, or (b) I tested something that David's analysis doesn't*apply* to=2E (IOW if my test plan doesn't actually verify "IPv6
litera= ls"=2E)


FWIW, the brackets in the IPv6 notation are stripped in = EfiHttpRequest()
[NetworkPkg/HttpDxe/HttpImpl=2Ec], using the "HostName"= local variable=2E
(The stripping comes from earlier commit 7191827f90b4=
("NetworkPkg/HttpDxe: Strip square brackets in IPv6 expressed
HostNa= me=2E", 2018-08-03)=2E) Later in EfiHttpRequest(),
"HttpInstance->Rem= oteHost" is assigned "HostName"=2E

Further, in TlsConfigureSession()= [NetworkPkg/HttpDxe/HttpsSupport=2Ec],
we set "HttpInstance->TlsConf= igData=2EVerifyHost=2EHostName" to
"HttpInstance->RemoteHost"=2E This= is done in patch#4=2E

Also in patch#4, in the same function, we pas= s
"HttpInstance->TlsConfigData=2EVerifyHost" to SetSessionData(), fro= m
patch#3=2E

There we pass "TlsVerifyHost->HostName" to TlsSet= VerifyHost(), which
resides in patch#2=2E

At that point, we pass = the hostname -- the IPv6 address, with the
brackets stripped -- to SSL_s= et1_host()=2E

So, my take is that the comparison is done simply on t= he textual
representation (with the IPv6 brackets stripped), not the num= erical
value=2E

Is that bad? The textual comparison may certainly= report a mismatch when
the numerical values actually match (for an IPv4= example, "192=2E168=2E0=2E1"
would not match "192=2E168=2E000=2E001")= =2E But that errs in the safe direction,
does it not?

Thanks!
= Laszlo

--
Sent from my Android device w= ith K-9 Mail=2E Please excuse my brevity=2E ------YMS4WWKV9XXMSRLHFO6KTCVQGIUBGY--