Commits

Stephen Smalley committed cd01e73

SEAndroid Manager.

  • Participants

Comments (0)

Files changed (14)

+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_JAVA_LIBRARIES := bouncycastle
+LOCAL_STATIC_JAVA_LIBRARIES := guava
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SEAndroidManager
+LOCAL_CERTIFICATE := platform
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+include $(BUILD_PACKAGE)
+
+# Use the folloing include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))

AndroidManifest.xml

+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.seandroid_manager"
+    android:versionCode="1"
+    android:versionName="1.0"
+    coreApp="true"
+    android:sharedUserId="android.uid.system">
+
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
+    <!-- SEAndroid Manager -->
+
+    <application android:label="@string/app_name">
+
+        <activity android:name="SEAndroidManager"
+            android:label="@string/activity_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <receiver android:name="RestoreSettings" android:exported="false">
+            <intent-filter android:priority="1">
+                <action android:name="android.intent.action.BOOT_COMPLETED"/>
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="SaveSettings" android:exported="false">
+            <intent-filter android:priority="1">
+                <action android:name="android.intent.action.ACTION_SHUTDOWN"/>
+                <action android:name="android.intent.action.REBOOT"/>
+            </intent-filter>
+        </receiver>
+
+    </application>
+
+</manifest> 
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+# Keep all Fragments in this package, which are used by reflection.
+-keep class com.android.seandroid_manager.*Fragment*
+-keep class com.android.senadroid_manager.*Settings*

project.properties

+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-13

res/layout/selinux_manage_booleans.xml

+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/list_container"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+	     
+    <ListView android:id="@android:id/list"
+	    android:layout_width="match_parent"
+	    android:layout_height="match_parent"
+	    android:drawSelectorOnTop="false"
+	    android:scrollbarStyle="@*android:integer/preference_fragment_scrollbarStyle" />
+
+    <TextView android:id="@android:id/empty"
+	    android:layout_width="match_parent"
+	    android:layout_height="match_parent"
+	    android:text="@string/selinux_no_booleans"/>
+
+</LinearLayout>

res/layout/selinux_manage_booleans_item.xml

+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:gravity="center_vertical">
+
+    <TextView android:id="@+id/text"
+	    android:layout_width="wrap_content"
+	    android:layout_height="wrap_content"
+	    android:layout_weight="1" />
+
+    <CheckBox android:id="@+id/checkbox"
+        android:layout_width="wrap_content"
+	    android:layout_height="wrap_content"
+	    android:layout_gravity="right"
+	    android:focusable="false" />
+
+</LinearLayout>

res/values/strings.xml

+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">SEAndroidManager</string>
+    <string name="activity_name">SEAndroidManager</string>
+    <string name="app_label">SEAndroid Manager</string>
+    <string name="app_label_launcher">SEAndroid Manager</string>
+    <string name="selinux_enforcing_fragment_title">Change SELinux Enforcing Mode</string>
+    <string name="selinux_boolean_fragment_title">Manage SELinux Booleans</string>
+    <string name="selinux_not_enabled">SELinux is not enabled</string>
+    <string name="selinux_status">SELinux status</string>
+    <string name="selinux_title">SELinux</string>
+    <string name="selinux_set_enforcing">SELinux Enforcing Mode</string>
+    <string name="selinux_set_enforcing_summary">Toggle SELinux Enforcing Mode</string>
+    <string name="selinux_manage_booleans">SELinux Booleans</string>
+    <string name="selinux_manage_booleans_summary">Manage SELinux Booleans</string>
+    <string name="selinux_no_booleans">No Booleans</string>
+</resources>

res/xml/seandroid_manager_headers.xml

+<?xml version="1.0" encoding="utf-8"?>
+<preference-headers
+    xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <header
+        android:fragment="com.android.seandroid_manager.SEAndroidManager$SELinuxEnforcingFragment"
+        android:title="@string/selinux_enforcing_fragment_title">
+    </header>
+
+    <header
+        android:fragment="com.android.seandroid_manager.SEAndroidManager$SELinuxBooleanFragment"
+        android:title="@string/selinux_boolean_fragment_title">
+    </header>
+
+</preference-headers>

res/xml/selinux_enforcing_fragment.xml

+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen 
+    xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <CheckBoxPreference 
+        android:key="selinux_enforcing"
+        android:title="@string/selinux_set_enforcing"
+        android:summary="@string/selinux_set_enforcing_summary"/>
+	
+</PreferenceScreen>

res/xml/selinux_not_enabled.xml

+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/selinux_not_enabled" >
+</PreferenceScreen>

src/com/android/seandroid_manager/RestoreSettings.java

+package com.android.seandroid_manager;
+
+import android.content.ContentResolver;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SELinux;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.HashMap;
+
+public class RestoreSettings extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (SELinux.isSELinuxEnabled()) {
+            Log.d("SEAndroidManager", "Restoring the SELinux settings");
+
+            ContentResolver mContentResolver = context.getContentResolver();
+
+            // Restore SELinux enforcing mode
+            final String enforcing = Settings.Secure.getString(mContentResolver,
+                                                               Settings.Secure.SELINUX_ENFORCING);
+            if (enforcing != null) {
+                SELinux.setSELinuxEnforce(enforcing.contentEquals("1") ? true : false);
+            }
+       
+            // Restore SELinux boolean settings
+            final String booleanList = Settings.Secure.getString(mContentResolver,
+                                                                 Settings.Secure.SELINUX_BOOLEANS);
+            if (booleanList != null) {
+                HashMap<String, Boolean>  mBooleanValueMap = new HashMap<String, Boolean>();
+                String[] booleanValues = booleanList.split(",");
+                for (String value : booleanValues) {
+                    final int delimiter = value.indexOf(':');
+                    if (delimiter > 0) {
+                        String n = value.substring(0, delimiter);
+                        Boolean v = value.substring(delimiter + 1).contentEquals("1") ? true : false;
+                        mBooleanValueMap.put(n, v);
+                    }
+                }
+                String[] mNames = SELinux.getBooleanNames();
+                for (String n : mNames) {
+                    if (mBooleanValueMap.containsKey(n)) {
+                        SELinux.setBooleanValue(n, mBooleanValueMap.get(n));
+                    }
+                }
+            }
+        }
+    }
+}

src/com/android/seandroid_manager/SEAndroidManager.java

+package com.android.seandroid_manager;
+
+import android.app.ListFragment;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.SELinux;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import java.util.List;
+
+public class SEAndroidManager extends PreferenceActivity {
+    @Override
+    public void onBuildHeaders(List<Header> target) {
+        loadHeadersFromResource(R.xml.seandroid_manager_headers, target);
+    }
+
+    public static class SELinuxEnforcingFragment extends PreferenceFragment {
+
+        private static final String KEY_SELINUX_ENFORCING = "selinux_enforcing";
+
+        private CheckBoxPreference mSELinuxToggleEnforce;
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            addPreferencesFromResource(R.xml.selinux_enforcing_fragment);
+            mSELinuxToggleEnforce = (CheckBoxPreference) getPreferenceScreen().findPreference(KEY_SELINUX_ENFORCING);
+            mSELinuxToggleEnforce.setChecked(SELinux.isSELinuxEnforced());
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+
+            if (mSELinuxToggleEnforce != null) {
+                mSELinuxToggleEnforce.setChecked(SELinux.isSELinuxEnforced());
+            }
+        }
+
+        @Override
+        public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+            final String key = preference.getKey();
+            if (preference == mSELinuxToggleEnforce) {
+                SELinux.setSELinuxEnforce(!SELinux.isSELinuxEnforced());
+                mSELinuxToggleEnforce.setChecked(SELinux.isSELinuxEnforced());
+            }
+            return true;
+        }
+    }
+
+    public static class SELinuxBooleanFragment extends ListFragment {
+
+        private static final String PREF_FILE = "seandroid_settings";
+        private SharedPreferences mPrefs;
+        private myBooleanAdapter mAdapter;
+
+        private class myBooleanAdapter extends ArrayAdapter<String> {
+            private final LayoutInflater mInflater;
+            private String[] mBooleans;
+
+            public myBooleanAdapter(Context context, int textViewResourceId, String[] items) {
+                super(context, textViewResourceId, items);
+                mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                mBooleans = items;
+            }
+
+            @Override
+            public View getView(int position, View convertView, ViewGroup parent) {
+                final ViewHolder holder;
+                if (convertView  == null) {
+                    convertView = mInflater.inflate(R.layout.selinux_manage_booleans_item, parent, 
+                                                    false);
+                    holder = new ViewHolder();
+                    holder.tx = (TextView) convertView.findViewById(R.id.text);
+                    holder.cb = (CheckBox) convertView.findViewById(R.id.checkbox);
+                    convertView.setTag(holder);
+                } else {
+                    holder = (ViewHolder) convertView.getTag();
+                }
+
+                String name = mBooleans[position];
+                holder.tx.setText(name);
+                holder.cb.setChecked(SELinux.getBooleanValue(name));
+                holder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+                        @Override
+                        public void onCheckedChanged(CompoundButton buttonView,
+                                                     boolean isChecked) {
+                            String name = (String)holder.tx.getText();
+                            SELinux.setBooleanValue(name, isChecked);
+                            holder.cb.setChecked(SELinux.getBooleanValue(name));
+                        }
+                    });
+                return convertView;
+            }
+
+            class ViewHolder {
+                TextView tx;
+                CheckBox cb;
+            }
+        }
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            mAdapter = new myBooleanAdapter(getActivity(), R.layout.selinux_manage_booleans, 
+                                            SELinux.getBooleanNames());
+            setListAdapter(mAdapter);
+        }
+    }
+}

src/com/android/seandroid_manager/SaveSettings.java

+package com.android.seandroid_manager;
+
+import android.content.ContentResolver;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SELinux;
+import android.provider.Settings;
+import android.util.Log;
+
+public class SaveSettings extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (SELinux.isSELinuxEnabled()) {
+            Log.d("SEAndroidManager", "Saving the SELinux settings");
+
+            ContentResolver mContentResolver = context.getContentResolver();
+
+            // Save SELinux enforcing mode
+            String enforcing = SELinux.isSELinuxEnforced() ? "1" : "0";
+            Settings.Secure.putString(mContentResolver, Settings.Secure.SELINUX_ENFORCING, 
+                                      enforcing);
+
+            // Save SELinux boolean settings
+            String[] mNames = SELinux.getBooleanNames();
+            StringBuilder newBooleanList = new StringBuilder();
+            boolean first = true;
+            for (String n : mNames) {
+                if (first) {
+                    first = false;
+                } else {
+                    newBooleanList.append(",");
+                } 
+                newBooleanList.append(n);
+                newBooleanList.append(":");
+                newBooleanList.append(SELinux.getBooleanValue(n) ? 1 : 0);
+            }
+            Settings.Secure.putString(mContentResolver, Settings.Secure.SELINUX_BOOLEANS, 
+                                      newBooleanList.toString());
+        }
+    }
+}