14efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver/*
24efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * Copyright (C) 2013 The Android Open Source Project
34efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver *
44efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * Licensed under the Apache License, Version 2.0 (the "License");
54efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * you may not use this file except in compliance with the License.
64efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * You may obtain a copy of the License at
74efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver *
84efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver *      http://www.apache.org/licenses/LICENSE-2.0
94efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver *
104efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * Unless required by applicable law or agreed to in writing, software
114efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * distributed under the License is distributed on an "AS IS" BASIS,
124efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * See the License for the specific language governing permissions and
144efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver * limitations under the License.
154efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver */
164efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
174efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruverpackage com.android.server.firewall;
184efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
19f5323fee2a7deaf264ed10fbe3d9c69055987e55Ben Gruverimport android.content.ComponentName;
204efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruverimport android.content.Intent;
214efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruverimport android.net.Uri;
224efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruverimport org.xmlpull.v1.XmlPullParser;
234efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruverimport org.xmlpull.v1.XmlPullParserException;
244efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
254efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruverimport java.io.IOException;
264efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
274efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruverclass PortFilter implements Filter {
284efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    private static final String ATTR_EQUALS = "equals";
294efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    private static final String ATTR_MIN = "min";
304efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    private static final String ATTR_MAX = "max";
314efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
324efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    private static final int NO_BOUND = -1;
334efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
344efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    // both bounds are inclusive
354efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    private final int mLowerBound;
364efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    private final int mUpperBound;
374efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
384efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    private PortFilter(int lowerBound, int upperBound) {
394efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        mLowerBound = lowerBound;
404efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        mUpperBound = upperBound;
414efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    }
424efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
434efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    @Override
44f5323fee2a7deaf264ed10fbe3d9c69055987e55Ben Gruver    public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent,
4549660c7c24f24c3394233e3bbf94c96281e8c408Ben Gruver            int callerUid, int callerPid, String resolvedType, int receivingUid) {
464efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        int port = -1;
474efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        Uri uri = intent.getData();
484efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        if (uri != null) {
494efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            port = uri.getPort();
504efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        }
514efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        return port != -1 &&
524efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                (mLowerBound == NO_BOUND || mLowerBound <= port) &&
534efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                (mUpperBound == NO_BOUND || mUpperBound >= port);
544efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    }
554efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
564efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    public static final FilterFactory FACTORY = new FilterFactory("port") {
574efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        @Override
584efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        public Filter newFilter(XmlPullParser parser)
594efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                throws IOException, XmlPullParserException {
604efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            int lowerBound = NO_BOUND;
614efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            int upperBound = NO_BOUND;
624efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
634efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            String equalsValue = parser.getAttributeValue(null, ATTR_EQUALS);
644efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            if (equalsValue != null) {
654efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                int value;
664efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                try {
674efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    value = Integer.parseInt(equalsValue);
684efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                } catch (NumberFormatException ex) {
694efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    throw new XmlPullParserException("Invalid port value: " + equalsValue,
704efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                            parser, null);
714efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                }
724efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                lowerBound = value;
734efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                upperBound = value;
744efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            }
754efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
764efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            String lowerBoundString = parser.getAttributeValue(null, ATTR_MIN);
774efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            String upperBoundString = parser.getAttributeValue(null, ATTR_MAX);
784efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            if (lowerBoundString != null || upperBoundString != null) {
794efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                if (equalsValue != null) {
804efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    throw new XmlPullParserException(
814efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                            "Port filter cannot use both equals and range filtering",
824efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                            parser, null);
834efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                }
844efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
854efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                if (lowerBoundString != null) {
864efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    try {
874efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                        lowerBound = Integer.parseInt(lowerBoundString);
884efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    } catch (NumberFormatException ex) {
894efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                        throw new XmlPullParserException(
904efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                                "Invalid minimum port value: " + lowerBoundString,
914efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                                parser, null);
924efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    }
934efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                }
944efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
954efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                if (upperBoundString != null) {
964efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    try {
974efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                        upperBound = Integer.parseInt(upperBoundString);
984efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    } catch (NumberFormatException ex) {
994efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                        throw new XmlPullParserException(
1004efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                                "Invalid maximum port value: " + upperBoundString,
1014efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                                parser, null);
1024efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                    }
1034efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver                }
1044efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            }
1054efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver
1064efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            // an empty port filter is explicitly allowed, and checks for the existence of a port
1074efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver            return new PortFilter(lowerBound, upperBound);
1084efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver        }
1094efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver    };
1104efe9403afb0ba3b83fa647eb82e4f90d29f131bBen Gruver}
111