19ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk/**
29ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Copyright (c) 2013, The Android Open Source Project
39ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
49ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
59ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * you may not use this file except in compliance with the License.
69ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * You may obtain a copy of the License at
79ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
89ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *     http://www.apache.org/licenses/LICENSE-2.0
99ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Unless required by applicable law or agreed to in writing, software
119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * See the License for the specific language governing permissions and
149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * limitations under the License.
159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk */
169ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkpackage com.android.pacprocessor;
179ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
189ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.app.Service;
199ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.content.Intent;
209ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.os.Binder;
219ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.os.IBinder;
229ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.os.Process;
239ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.os.RemoteException;
249ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.util.Log;
259ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
269ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport com.android.net.IProxyService;
279ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
287a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monkimport java.net.MalformedURLException;
297a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monkimport java.net.URL;
307a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk
319ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkpublic class PacService extends Service {
329ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    private static final String TAG = "PacService";
339ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
349ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    private PacNative mPacNative;
359ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    private ProxyServiceStub mStub;
369ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
379ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    @Override
389ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    public void onCreate() {
399ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        super.onCreate();
409ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        if (mPacNative == null) {
419ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative = new PacNative();
429ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mStub = new ProxyServiceStub(mPacNative);
439ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
449ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
459ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
469ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    @Override
479ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    public void onDestroy() {
489ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        super.onDestroy();
499ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        if (mPacNative != null) {
509ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative.stopPacSupport();
519ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative = null;
529ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mStub = null;
539ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
549ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
559ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
569ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    @Override
579ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    public IBinder onBind(Intent intent) {
589ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        if (mPacNative == null) {
599ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative = new PacNative();
609ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mStub = new ProxyServiceStub(mPacNative);
619ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
629ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return mStub;
639ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
649ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
659ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    private static class ProxyServiceStub extends IProxyService.Stub {
669ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        private final PacNative mPacNative;
679ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
689ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        public ProxyServiceStub(PacNative pacNative) {
699ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative = pacNative;
709ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
719ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
729ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        @Override
739ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        public String resolvePacFile(String host, String url) throws RemoteException {
747a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk            try {
7544c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                if (host == null) {
7644c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                    throw new IllegalArgumentException("The host must not be null");
7744c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                }
7844c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                if (url == null) {
7944c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                    throw new IllegalArgumentException("The URL must not be null");
8044c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                }
817a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk                // Check for characters that could be used for an injection attack.
827a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk                new URL(url);
837a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk                for (char c : host.toCharArray()) {
847a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk                    if (!Character.isLetterOrDigit(c) && (c != '.') && (c != '-')) {
8544c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                        throw new IllegalArgumentException("Invalid host was passed");
867a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk                    }
877a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk                }
887a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk                return mPacNative.makeProxyRequest(url, host);
897a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk            } catch (MalformedURLException e) {
9044c02590374bda5928669be0d14110b12c271461Andrei Kapishnikov                throw new IllegalArgumentException("Invalid URL was passed");
917a6af1c09306fa833d11f5ffd100eff7b1a35a4cJason Monk            }
929ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
939ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
949ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        @Override
959ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        public void setPacFile(String script) throws RemoteException {
969ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
979ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                Log.e(TAG, "Only system user is allowed to call setPacFile");
989ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                throw new SecurityException();
999ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            }
1009ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative.setCurrentProxyScript(script);
1019ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
1029ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1039ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        @Override
1049ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        public void startPacSystem() throws RemoteException {
1059ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
1069ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                Log.e(TAG, "Only system user is allowed to call startPacSystem");
1079ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                throw new SecurityException();
1089ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            }
1099ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative.startPacSupport();
1109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
1119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        @Override
1139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        public void stopPacSystem() throws RemoteException {
1149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
1159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                Log.e(TAG, "Only system user is allowed to call stopPacSystem");
1169ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                throw new SecurityException();
1179ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            }
1189ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mPacNative.stopPacSupport();
1199ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
1209ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
1219ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
122