Commit 9354e2a5 authored by Samuel Tan's avatar Samuel Tan Committed by gitbuildkicker
Browse files

ANQPFactory: catch all potential parsing errors

The ANQP Element parsing code that parses untrusted data broadcasted
by APs is currently untested, and might contain errors that will
trigger exceptions that can crash the system service (e.g. null pointer
exceptions).

To contain this risk, catch all possible exceptions from the invoking
ANQP element parsing code from ANQPFactory, and throw them again
as ProtocolExceptions, which users of ANQPFactory already catch.

BUG: 30230534
Change-Id: Icaba02c0e6739d94482cf4a5e704b59f8d4105b4
(cherry picked from commit 6154eb07)
parent a2228a2e
...@@ -158,83 +158,99 @@ public class ANQPFactory { ...@@ -158,83 +158,99 @@ public class ANQPFactory {
public static ANQPElement buildElement(ByteBuffer payload, Constants.ANQPElementType infoID, public static ANQPElement buildElement(ByteBuffer payload, Constants.ANQPElementType infoID,
int length) throws ProtocolException { int length) throws ProtocolException {
ByteBuffer elementPayload = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN); try {
payload.position(payload.position() + length); ByteBuffer elementPayload = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
elementPayload.limit(elementPayload.position() + length); payload.position(payload.position() + length);
elementPayload.limit(elementPayload.position() + length);
switch (infoID) {
case ANQPCapabilityList: switch (infoID) {
return new CapabilityListElement(infoID, elementPayload); case ANQPCapabilityList:
case ANQPVenueName: return new CapabilityListElement(infoID, elementPayload);
return new VenueNameElement(infoID, elementPayload); case ANQPVenueName:
case ANQPEmergencyNumber: return new VenueNameElement(infoID, elementPayload);
return new EmergencyNumberElement(infoID, elementPayload); case ANQPEmergencyNumber:
case ANQPNwkAuthType: return new EmergencyNumberElement(infoID, elementPayload);
return new NetworkAuthenticationTypeElement(infoID, elementPayload); case ANQPNwkAuthType:
case ANQPRoamingConsortium: return new NetworkAuthenticationTypeElement(infoID, elementPayload);
return new RoamingConsortiumElement(infoID, elementPayload); case ANQPRoamingConsortium:
case ANQPIPAddrAvailability: return new RoamingConsortiumElement(infoID, elementPayload);
return new IPAddressTypeAvailabilityElement(infoID, elementPayload); case ANQPIPAddrAvailability:
case ANQPNAIRealm: return new IPAddressTypeAvailabilityElement(infoID, elementPayload);
return new NAIRealmElement(infoID, elementPayload); case ANQPNAIRealm:
case ANQP3GPPNetwork: return new NAIRealmElement(infoID, elementPayload);
return new ThreeGPPNetworkElement(infoID, elementPayload); case ANQP3GPPNetwork:
case ANQPGeoLoc: return new ThreeGPPNetworkElement(infoID, elementPayload);
return new GEOLocationElement(infoID, elementPayload); case ANQPGeoLoc:
case ANQPCivicLoc: return new GEOLocationElement(infoID, elementPayload);
return new CivicLocationElement(infoID, elementPayload); case ANQPCivicLoc:
case ANQPLocURI: return new CivicLocationElement(infoID, elementPayload);
return new GenericStringElement(infoID, elementPayload); case ANQPLocURI:
case ANQPDomName: return new GenericStringElement(infoID, elementPayload);
return new DomainNameElement(infoID, elementPayload); case ANQPDomName:
case ANQPEmergencyAlert: return new DomainNameElement(infoID, elementPayload);
return new GenericStringElement(infoID, elementPayload); case ANQPEmergencyAlert:
case ANQPTDLSCap: return new GenericStringElement(infoID, elementPayload);
return new GenericBlobElement(infoID, elementPayload); case ANQPTDLSCap:
case ANQPEmergencyNAI:
return new GenericStringElement(infoID, elementPayload);
case ANQPNeighborReport:
return new GenericBlobElement(infoID, elementPayload);
case ANQPVendorSpec:
if (elementPayload.remaining() > 5) {
int oi = elementPayload.getInt();
if (oi != Constants.HS20_PREFIX) {
return null;
}
int subType = elementPayload.get() & Constants.BYTE_MASK;
Constants.ANQPElementType hs20ID = Constants.mapHS20Element(subType);
if (hs20ID == null) {
throw new ProtocolException("Bad HS20 info ID: " + subType);
}
elementPayload.get(); // Skip the reserved octet
return buildHS20Element(hs20ID, elementPayload);
} else {
return new GenericBlobElement(infoID, elementPayload); return new GenericBlobElement(infoID, elementPayload);
} case ANQPEmergencyNAI:
default: return new GenericStringElement(infoID, elementPayload);
throw new ProtocolException("Unknown element ID: " + infoID); case ANQPNeighborReport:
return new GenericBlobElement(infoID, elementPayload);
case ANQPVendorSpec:
if (elementPayload.remaining() > 5) {
int oi = elementPayload.getInt();
if (oi != Constants.HS20_PREFIX) {
return null;
}
int subType = elementPayload.get() & Constants.BYTE_MASK;
Constants.ANQPElementType hs20ID = Constants.mapHS20Element(subType);
if (hs20ID == null) {
throw new ProtocolException("Bad HS20 info ID: " + subType);
}
elementPayload.get(); // Skip the reserved octet
return buildHS20Element(hs20ID, elementPayload);
} else {
return new GenericBlobElement(infoID, elementPayload);
}
default:
throw new ProtocolException("Unknown element ID: " + infoID);
}
} catch (ProtocolException e) {
throw e;
} catch (Exception e) {
// TODO: remove this catch-all for exceptions, once the element parsing code
// has been thoroughly unit tested. b/30562650
throw new ProtocolException("Unknown parsing error", e);
} }
} }
public static ANQPElement buildHS20Element(Constants.ANQPElementType infoID, public static ANQPElement buildHS20Element(Constants.ANQPElementType infoID,
ByteBuffer payload) throws ProtocolException { ByteBuffer payload) throws ProtocolException {
switch (infoID) { try {
case HSCapabilityList: switch (infoID) {
return new HSCapabilityListElement(infoID, payload); case HSCapabilityList:
case HSFriendlyName: return new HSCapabilityListElement(infoID, payload);
return new HSFriendlyNameElement(infoID, payload); case HSFriendlyName:
case HSWANMetrics: return new HSFriendlyNameElement(infoID, payload);
return new HSWanMetricsElement(infoID, payload); case HSWANMetrics:
case HSConnCapability: return new HSWanMetricsElement(infoID, payload);
return new HSConnectionCapabilityElement(infoID, payload); case HSConnCapability:
case HSOperatingclass: return new HSConnectionCapabilityElement(infoID, payload);
return new GenericBlobElement(infoID, payload); case HSOperatingclass:
case HSOSUProviders: return new GenericBlobElement(infoID, payload);
return new HSOsuProvidersElement(infoID, payload); case HSOSUProviders:
case HSIconFile: return new HSOsuProvidersElement(infoID, payload);
return new HSIconFileElement(infoID, payload); case HSIconFile:
default: return new HSIconFileElement(infoID, payload);
return null; default:
return null;
}
} catch (ProtocolException e) {
throw e;
} catch (Exception e) {
// TODO: remove this catch-all for exceptions, once the element parsing code
// has been thoroughly unit tested. b/30562650
throw new ProtocolException("Unknown parsing error", e);
} }
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment