diff --git a/app/src/main/java/lu/circl/mispbump/activities/ExchangeActivity.java b/app/src/main/java/lu/circl/mispbump/activities/ExchangeActivity.java index d98e42f..c23d67d 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/ExchangeActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/ExchangeActivity.java @@ -118,7 +118,7 @@ public class ExchangeActivity extends AppCompatActivity { SyncInformation syncInformation = new SyncInformation(); syncInformation.organisation = preferenceManager.getUserOrganisation().toSyncOrganisation(); syncInformation.syncUserAuthkey = new RandomString(40).nextString(); - syncInformation.baseUrl = preferenceManager.getServerUrl(); + syncInformation.baseUrl = preferenceManager.getUserCredentials().first; syncInformation.syncUserPassword = new RandomString(16).nextString(); syncInformation.syncUserEmail = preferenceManager.getUserInfo().email; return syncInformation; @@ -289,7 +289,7 @@ public class ExchangeActivity extends AppCompatActivity { final List uploadInformationList = preferenceManager.getUploadInformationList(); for (final UploadInformation ui : uploadInformationList) { - if (ui.getRemote().organisation.uuid.equals(remoteSyncInfo.organisation.uuid)) { + if (ui.getRemote().organisation.getUuid().equals(remoteSyncInfo.organisation.getUuid())) { DialogManager.syncAlreadyExistsDialog(ui.getRemote(), remoteSyncInfo, ExchangeActivity.this, new DialogManager.IDialogFeedback() { @Override public void positive() { diff --git a/app/src/main/java/lu/circl/mispbump/activities/LoginActivity.java b/app/src/main/java/lu/circl/mispbump/activities/LoginActivity.java index 0ad59a1..73ac76a 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/LoginActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/LoginActivity.java @@ -3,13 +3,6 @@ package lu.circl.mispbump.activities; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import androidx.constraintlayout.widget.ConstraintLayout; -import com.google.android.material.snackbar.Snackbar; -import com.google.android.material.textfield.TextInputLayout; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; - import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; @@ -17,25 +10,30 @@ import android.view.View; import android.widget.Button; import android.widget.ProgressBar; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.google.android.material.snackbar.Snackbar; +import com.google.android.material.textfield.TextInputLayout; + import java.util.Objects; import lu.circl.mispbump.R; import lu.circl.mispbump.auxiliary.DialogManager; -import lu.circl.mispbump.auxiliary.PreferenceManager; import lu.circl.mispbump.auxiliary.MispRestClient; +import lu.circl.mispbump.auxiliary.PreferenceManager; import lu.circl.mispbump.models.restModels.Organisation; +import lu.circl.mispbump.models.restModels.Role; import lu.circl.mispbump.models.restModels.User; -/** - * This activity is shown when the current device has no misp user and organisation associated with it. - * It takes care of downloading all information necessary for a sync with other misp instances. - */ public class LoginActivity extends AppCompatActivity { private PreferenceManager preferenceManager; private ConstraintLayout constraintLayout; - private TextInputLayout serverAutomationKey; + private TextInputLayout serverAuthkey; private TextInputLayout serverUrl; private ProgressBar progressBar; @@ -64,7 +62,6 @@ public class LoginActivity extends AppCompatActivity { return true; } - // invoke superclass to handle unrecognized item (eg. homeAsUp) return super.onOptionsItemSelected(item); } @@ -72,7 +69,6 @@ public class LoginActivity extends AppCompatActivity { private void initializeViews() { constraintLayout = findViewById(R.id.rootLayout); - // populate Toolbar (Actionbar) Toolbar myToolbar = findViewById(R.id.appbar); setSupportActionBar(myToolbar); ActionBar ab = getSupportActionBar(); @@ -82,26 +78,26 @@ public class LoginActivity extends AppCompatActivity { } Button downloadInfoButton = findViewById(R.id.login_download_button); - downloadInfoButton.setOnClickListener(onClickDownload); + downloadInfoButton.setOnClickListener(onLogin); serverUrl = findViewById(R.id.login_server_url); - serverAutomationKey = findViewById(R.id.login_automation_key); + serverAuthkey = findViewById(R.id.login_automation_key); progressBar = findViewById(R.id.login_progressbar); } /** - * Is called when the user clicks on the login button. + * Called when the user clicks on the login button. */ - private View.OnClickListener onClickDownload = new View.OnClickListener() { + private View.OnClickListener onLogin = new View.OnClickListener() { @Override public void onClick(View v) { final String url = Objects.requireNonNull(serverUrl.getEditText()).getText().toString(); - final String authkey = Objects.requireNonNull(serverAutomationKey.getEditText()).getText().toString(); + final String authkey = Objects.requireNonNull(serverAuthkey.getEditText()).getText().toString(); boolean error = false; serverUrl.setError(null); - serverAutomationKey.setError(null); + serverAuthkey.setError(null); if (!isValidUrl(url)) { error = true; @@ -110,7 +106,7 @@ public class LoginActivity extends AppCompatActivity { if (!isValidAutomationKey(authkey)) { error = true; - serverAutomationKey.setError("Invalid automation key"); + serverAuthkey.setError("Invalid automation key"); } if (error) { @@ -126,25 +122,44 @@ public class LoginActivity extends AppCompatActivity { mispRestClient.isAvailable(new MispRestClient.AvailableCallback() { @Override public void available() { - mispRestClient.getMyUser(new MispRestClient.UserCallback() { + mispRestClient.getRoles(new MispRestClient.AllRolesCallback() { @Override - public void success(final User user) { - preferenceManager.setUserInfo(user); - mispRestClient.getOrganisation(user.org_id, new MispRestClient.OrganisationCallback() { + public void success(final Role[] roles) { + preferenceManager.setRoles(roles); + + mispRestClient.getMyUser(new MispRestClient.UserCallback() { @Override - public void success(Organisation organisation) { - preferenceManager.setUserOrgInfo(organisation); + public void success(final User user) { + preferenceManager.setUserInfo(user); + for (Role role : roles) { + if (role.getId().equals(user.role_id)) { + if (!role.getPermAdmin()) { + progressBar.setVisibility(View.GONE); + Snackbar.make(constraintLayout, "No admin is associated with this authkey.", Snackbar.LENGTH_LONG).show(); + return; + } + } + } - // save authkey - preferenceManager.setAutomationKey(authkey); + mispRestClient.getOrganisation(user.org_id, new MispRestClient.OrganisationCallback() { + @Override + public void success(Organisation organisation) { + preferenceManager.setUserOrgInfo(organisation); + preferenceManager.setUserCredentials(url, authkey); - // save url - preferenceManager.setServerUrl(url); + progressBar.setVisibility(View.GONE); - progressBar.setVisibility(View.GONE); - Intent home = new Intent(getApplicationContext(), HomeActivity.class); - startActivity(home); - finish(); + Intent home = new Intent(getApplicationContext(), HomeActivity.class); + startActivity(home); + finish(); + } + + @Override + public void failure(String error) { + progressBar.setVisibility(View.GONE); + Snackbar.make(constraintLayout, error, Snackbar.LENGTH_LONG).show(); + } + }); } @Override @@ -166,8 +181,7 @@ public class LoginActivity extends AppCompatActivity { @Override public void unavailable(String error) { progressBar.setVisibility(View.GONE); - Snackbar sb = Snackbar.make(constraintLayout, error, Snackbar.LENGTH_LONG); - sb.show(); + Snackbar.make(constraintLayout, error, Snackbar.LENGTH_LONG).show(); } }); } diff --git a/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java b/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java index 2543a37..9ad5cce 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/ProfileActivity.java @@ -17,6 +17,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.util.Pair; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; @@ -29,6 +30,7 @@ import lu.circl.mispbump.auxiliary.PreferenceManager; import lu.circl.mispbump.auxiliary.TileDrawable; import lu.circl.mispbump.customViews.MaterialPreferenceText; import lu.circl.mispbump.models.restModels.Organisation; +import lu.circl.mispbump.models.restModels.Role; import lu.circl.mispbump.models.restModels.User; import lu.circl.mispbump.security.KeyStoreWrapper; @@ -47,7 +49,8 @@ public class ProfileActivity extends AppCompatActivity { setContentView(R.layout.activity_profile); preferenceManager = PreferenceManager.getInstance(this); - mispRestClient = MispRestClient.getInstance(preferenceManager.getServerUrl(), preferenceManager.getAuthKey()); + Pair credentials = preferenceManager.getUserCredentials(); + mispRestClient = MispRestClient.getInstance(credentials.first, credentials.second); init(); populateInformationViews(); @@ -79,23 +82,23 @@ public class ProfileActivity extends AppCompatActivity { Organisation organisation = preferenceManager.getUserOrganisation(); TextView name = findViewById(R.id.orgName); - name.setText(organisation.name); + name.setText(organisation.getName()); final MaterialPreferenceText uuid = findViewById(R.id.uuid); - uuid.setSubtitle(organisation.uuid); + uuid.setSubtitle(organisation.getUuid()); MaterialPreferenceText nationality = findViewById(R.id.nationality); - nationality.setSubtitle(organisation.nationality); + nationality.setSubtitle(organisation.getNationality()); MaterialPreferenceText sector = findViewById(R.id.sector); - if (organisation.sector == null) { + if (organisation.getSector() == null) { sector.setVisibility(View.GONE); } else { - sector.setSubtitle(organisation.sector); + sector.setSubtitle(organisation.getSector()); } MaterialPreferenceText description = findViewById(R.id.description); - description.setSubtitle(organisation.description); + description.setSubtitle(organisation.getDescription()); } @Override @@ -131,14 +134,22 @@ public class ProfileActivity extends AppCompatActivity { } public void updateProfile() { -// progressBar.setVisibility(View.VISIBLE); + mispRestClient.getRoles(new MispRestClient.AllRolesCallback() { + @Override + public void success(Role[] roles) { + preferenceManager.setRoles(roles); + } + + @Override + public void failure(String error) { + Snackbar.make(rootLayout, error, Snackbar.LENGTH_LONG).show(); + } + }); mispRestClient.getMyUser(new MispRestClient.UserCallback() { @Override public void success(final User user) { - preferenceManager.setUserInfo(user); - mispRestClient.getOrganisation(user.org_id, new MispRestClient.OrganisationCallback() { @Override public void success(Organisation organisation) { @@ -178,8 +189,7 @@ public class ProfileActivity extends AppCompatActivity { builder.setPositiveButton("Delete & Logout", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - PreferenceManager prefs = PreferenceManager.getInstance(ProfileActivity.this); - prefs.clearAllData(); + preferenceManager.clearAllData(); KeyStoreWrapper.deleteAllStoredKeys(); Intent login = new Intent(getApplicationContext(), LoginActivity.class); diff --git a/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java b/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java index f09df57..3345c3d 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/StartUpActivity.java @@ -2,12 +2,10 @@ package lu.circl.mispbump.activities; import android.content.Intent; import android.os.Bundle; -import android.util.Log; import androidx.appcompat.app.AppCompatActivity; import lu.circl.mispbump.auxiliary.PreferenceManager; -import lu.circl.mispbump.models.restModels.User; /** * Starts either the login or home activity. @@ -32,7 +30,6 @@ public class StartUpActivity extends AppCompatActivity { private boolean isUserLoggedIn() { PreferenceManager preferenceManager = PreferenceManager.getInstance(this); - User user = preferenceManager.getUserInfo(); - return user != null; + return preferenceManager.getUserCredentials() != null && preferenceManager.getUserInfo() != null; } } diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java index 02e9796..b7b1550 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/UploadActivity.java @@ -9,6 +9,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.util.Pair; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -99,7 +100,8 @@ public class UploadActivity extends AppCompatActivity { setContentView(R.layout.activity_upload); preferenceManager = PreferenceManager.getInstance(UploadActivity.this); - restClient = MispRestClient.getInstance(preferenceManager.getServerUrl(), preferenceManager.getAuthKey()); + Pair credentials = preferenceManager.getUserCredentials(); + restClient = MispRestClient.getInstance(credentials.first, credentials.second); parseExtra(); initViews(); @@ -212,7 +214,7 @@ public class UploadActivity extends AppCompatActivity { private User generateSyncUser(Organisation organisation) { User syncUser = new User(); - syncUser.org_id = organisation.id; + syncUser.org_id = organisation.getId(); syncUser.role_id = User.ROLE_SYNC_USER; syncUser.email = uploadInformation.getRemote().syncUserEmail; syncUser.password = uploadInformation.getRemote().syncUserPassword; @@ -224,9 +226,9 @@ public class UploadActivity extends AppCompatActivity { private Server generateSyncServer() { Server server = new Server(); - server.name = uploadInformation.getRemote().organisation.name + "'s Sync Server"; + server.name = uploadInformation.getRemote().organisation.getName() + "'s Sync Server"; server.url = uploadInformation.getRemote().baseUrl; - server.remote_org_id = uploadInformation.getRemote().organisation.id; + server.remote_org_id = uploadInformation.getRemote().organisation.getId(); server.authkey = uploadInformation.getLocal().syncUserAuthkey; server.pull = uploadInformation.isPull(); server.push = uploadInformation.isPush(); @@ -256,11 +258,11 @@ public class UploadActivity extends AppCompatActivity { private void organisationAdded(Organisation organisation) { if (organisation != null) { setUploadActionState(orgAction, UploadAction.UploadState.DONE, null); - uploadInformation.getRemote().organisation.id = organisation.id; + uploadInformation.getRemote().organisation.setId(organisation.getId()); restClient.addUser(generateSyncUser(organisation), userCallback); } else { // search by UUID because the error does not give the actual ID - restClient.getOrganisation(uploadInformation.getRemote().organisation.uuid, new MispRestClient.OrganisationCallback() { + restClient.getOrganisation(uploadInformation.getRemote().organisation.getUuid(), new MispRestClient.OrganisationCallback() { @Override public void success(Organisation organisation) { organisationAdded(organisation); diff --git a/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java index 80fc022..14e5062 100644 --- a/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java +++ b/app/src/main/java/lu/circl/mispbump/activities/UploadInfoActivity.java @@ -127,7 +127,7 @@ public class UploadInfoActivity extends AppCompatActivity { assert ab != null; TextView toolbarTitle = findViewById(R.id.toolbarTitle); - toolbarTitle.setText(uploadInformation.getRemote().organisation.name); + toolbarTitle.setText(uploadInformation.getRemote().organisation.getName()); ab.setHomeAsUpIndicator(R.drawable.ic_close); diff --git a/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java b/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java index 7dadcb7..2978dc6 100644 --- a/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java +++ b/app/src/main/java/lu/circl/mispbump/adapters/UploadInfoAdapter.java @@ -45,7 +45,7 @@ public class UploadInfoAdapter extends RecyclerView.Adapter> call = mispRestInterface.getRoles(); + call.enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + + if (!response.isSuccessful()) { + callback.failure(extractError(response)); + return; + } + + List mispRoles = response.body(); + assert mispRoles != null; + + Role[] roles = new Role[mispRoles.size()]; + + for (int i = 0; i < roles.length; i++) { + roles[i] = mispRoles.get(i).role; + } + + callback.success(roles); + } + + @Override + public void onFailure(Call> call, Throwable t) { + callback.failure(extractError(t)); + } + }); + } + /** * Fetches information about the user that is associated with saved auth key. @@ -338,7 +366,7 @@ public class MispRestClient { if (response.body() != null) { callback.success(response.body().organisation); } else { - callback.failure("Response body was nul"); + callback.failure("Response was empty"); } } } @@ -355,7 +383,7 @@ public class MispRestClient { @Override public void success(Organisation[] organisations) { for (Organisation organisation : organisations) { - if (organisation.uuid.equals(uuid)) { + if (organisation.getUuid().equals(uuid)) { callback.success(organisation); return; } @@ -378,7 +406,6 @@ public class MispRestClient { @Override public void onResponse(@NonNull Call> call, @NonNull Response> response) { if (!response.isSuccessful()) { - // TODO handle return; } @@ -431,10 +458,6 @@ public class MispRestClient { // --- server routes --- - public void getServer() { - - } - /** * Get all servers on MISP instance. * @@ -518,40 +541,19 @@ public class MispRestClient { // forbidden case 403: - try { - assert response.errorBody() != null; - JSONObject jsonError = new JSONObject(response.errorBody().string()); - - String name = jsonError.getString("name") + "\n"; - - if (name.startsWith("Authentication failed")) { - return "Authentication failed"; - } - - String reasons = ""; - JSONObject errorReasons = jsonError.getJSONObject("errors"); - - Iterator errorKeys = errorReasons.keys(); - - while (errorKeys.hasNext()) { - reasons = reasons.concat(errorReasons.getString(errorKeys.next()) + "\n"); - } - - return name + reasons; - } catch (JSONException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return "Could not parse (403) error"; + return "Authentification failed"; // not found case 404: return "Not found"; - } - return "Unknown error"; + // No permission (method not allowed) + case 405: + return "No admin permission"; + + default: + return response.message(); + } } /** @@ -574,6 +576,12 @@ public class MispRestClient { return "Server is not available (no route to host)"; } + try { + throw new Exception(t); + } catch (Exception e) { + e.printStackTrace(); + } + return t.getMessage(); } @@ -620,4 +628,10 @@ public class MispRestClient { void failure(String error); } + + public interface AllRolesCallback { + void success(Role[] roles); + + void failure(String error); + } } \ No newline at end of file diff --git a/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java b/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java index 65f4541..ae2064f 100644 --- a/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java +++ b/app/src/main/java/lu/circl/mispbump/auxiliary/PreferenceManager.java @@ -2,7 +2,8 @@ package lu.circl.mispbump.auxiliary; import android.content.Context; import android.content.SharedPreferences; -import android.util.Log; + +import androidx.core.util.Pair; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; @@ -21,24 +22,22 @@ import javax.crypto.NoSuchPaddingException; import lu.circl.mispbump.models.UploadInformation; import lu.circl.mispbump.models.restModels.Organisation; +import lu.circl.mispbump.models.restModels.Role; import lu.circl.mispbump.models.restModels.User; import lu.circl.mispbump.security.KeyStoreWrapper; public class PreferenceManager { - private static final String TAG = "PreferenceManager"; - private static final String PREFERENCES_FILE = "user_settings"; - private static final String SAVE_CREDENTIALS = "save_credentials"; - private static final String SERVER_URL = "server_url"; - private static final String AUTOMATION_KEY = "user_automation"; - + private static final String USER_CREDENTIALS = "user_credentials"; private static final String USER_INFOS = "user_infos"; private static final String USER_ORG_INFOS = "user_org_infos"; private static final String UPLOAD_INFO = "upload_info"; + private static final String MISP_ROLES = "misp_roles"; + private SharedPreferences preferences; private static PreferenceManager instance; @@ -61,6 +60,38 @@ public class PreferenceManager { } + /** + * Save downloaded MISP roles on device. + * + * @param roles {@link Role} + */ + public void setRoles(Role[] roles) { + SharedPreferences.Editor editor = preferences.edit(); + editor.putString(MISP_ROLES, new Gson().toJson(roles)); + editor.apply(); + } + + /** + * Gets downloaded and saved MISP roles if available. + *

+ * Roles are downloaded on login and updated with each profile update. + * + * @return {@link Role}[] or null + */ + public Role[] getRoles() { + Type type = new TypeToken() { + }.getType(); + String rolesString = preferences.getString(MISP_ROLES, ""); + + assert rolesString != null; + if (rolesString.isEmpty()) { + return null; + } else { + return new Gson().fromJson(rolesString, type); + } + } + + /** * Saves user infos from "users/view/me" (encrypted) * @@ -180,147 +211,34 @@ public class PreferenceManager { } - /** - * Encrypts the automation key and stores it in preferences. - * - * @param automationKey key entered in {@link lu.circl.mispbump.activities.LoginActivity} - */ - public void setAutomationKey(String automationKey) { + public void setUserCredentials(String url, String authkey) { try { - KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.AUTOMATION_ALIAS); + KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.USER_CREDENTIALS_ALIAS); SharedPreferences.Editor editor = preferences.edit(); - editor.putString(AUTOMATION_KEY, keyStoreWrapper.encrypt(automationKey)); + editor.putString(USER_CREDENTIALS, keyStoreWrapper.encrypt(new Gson().toJson(new Pair<>(url, authkey)))); editor.apply(); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { + } catch (NoSuchAlgorithmException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException e) { e.printStackTrace(); } } - /** - * Decrypts the stored automation key and returns it. - * - * @return decrypted automation key associated with the current user. If no user exists an empty - * String is returned. - */ - public String getAuthKey() { - - if (!preferences.contains(AUTOMATION_KEY)) { - return ""; - } - - try { - KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.AUTOMATION_ALIAS); - return keyStoreWrapper.decrypt(preferences.getString(AUTOMATION_KEY, "")); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (InvalidAlgorithmParameterException e) { - e.printStackTrace(); - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - } - - return ""; - } - - /** - * Delete the key to decrypt this entry and the entry itself. - */ - public void clearAutomationKey() { - // remove the key from KeyStore - KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.AUTOMATION_ALIAS); - keyStoreWrapper.deleteStoredKey(); - - SharedPreferences.Editor editor = preferences.edit(); - editor.remove(AUTOMATION_KEY); - editor.apply(); - } - - - /** - * Encrypts the server url and stores it in preferences. - * - * @param serverUrl url of the corresponding misp instance - */ - public void setServerUrl(String serverUrl) { - try { - - KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.SERVER_URL_ALIAS); - SharedPreferences.Editor editor = preferences.edit(); - editor.putString(SERVER_URL, keyStoreWrapper.encrypt(serverUrl)); - editor.apply(); - - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { - e.printStackTrace(); - } - } - - /** - * Decrypts the stored server url and returns it - * - * @return decrypted misp instance url - */ - public String getServerUrl() { - - if (!preferences.contains(SERVER_URL)) { + public Pair getUserCredentials() { + if (!preferences.contains(USER_CREDENTIALS)) { return null; } try { - KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.SERVER_URL_ALIAS); - return keyStoreWrapper.decrypt(preferences.getString(SERVER_URL, null)); - - } catch (NoSuchPaddingException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (InvalidAlgorithmParameterException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (BadPaddingException e) { - e.printStackTrace(); - } catch (IllegalBlockSizeException e) { + KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.USER_CREDENTIALS_ALIAS); + Type type = new TypeToken>() {}.getType(); + String serializedCreds = keyStoreWrapper.decrypt(preferences.getString(USER_CREDENTIALS, "")); + return new Gson().fromJson(serializedCreds, type); + } catch (InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } - /** - * Delete the key to decrypt this entry and the entry itself. - */ - public void clearServerUrl() { - // remove the key from KeyStore - KeyStoreWrapper keyStoreWrapper = new KeyStoreWrapper(KeyStoreWrapper.SERVER_URL_ALIAS); - keyStoreWrapper.deleteStoredKey(); - - SharedPreferences.Editor editor = preferences.edit(); - editor.remove(SERVER_URL); - editor.apply(); - } - private List cachedUploadInformationList; @@ -328,7 +246,8 @@ public class PreferenceManager { KeyStoreWrapper ksw = new KeyStoreWrapper(KeyStoreWrapper.UPLOAD_INFORMATION_ALIAS); String storedUploadInfoString = preferences.getString(UPLOAD_INFO, null); - Type type = new TypeToken>() {}.getType(); + Type type = new TypeToken>() { + }.getType(); if (storedUploadInfoString == null || storedUploadInfoString.isEmpty()) { cachedUploadInformationList = new ArrayList<>(); @@ -430,26 +349,13 @@ public class PreferenceManager { } - /** - * Set if credentials (authkey & server url) should be saved locally. - * - * @param save enable or disable - * @deprecated currently not used because automation key is needed to do requests to your misp instance. - * If this should be an option in future: misp automation key would be needed on each sync process. - */ - public void setSaveCredentials(boolean save) { - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean(SAVE_CREDENTIALS, save); - editor.apply(); - } - - public boolean getSaveCredentials() { - return preferences.getBoolean(SAVE_CREDENTIALS, false); - } - - public void clearAllData() { SharedPreferences.Editor editor = preferences.edit(); + +// clearServerUrl(); +// clearAutomationKey(); + clearUploadInformation(); + editor.clear(); editor.apply(); } diff --git a/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java b/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java index b3fd1b9..e349e81 100644 --- a/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java +++ b/app/src/main/java/lu/circl/mispbump/interfaces/MispRestInterface.java @@ -3,6 +3,7 @@ package lu.circl.mispbump.interfaces; import java.util.List; import lu.circl.mispbump.models.restModels.MispOrganisation; +import lu.circl.mispbump.models.restModels.MispRole; import lu.circl.mispbump.models.restModels.MispServer; import lu.circl.mispbump.models.restModels.MispUser; import lu.circl.mispbump.models.restModels.Organisation; @@ -25,6 +26,9 @@ public interface MispRestInterface { @GET("servers/getPyMISPVersion") Call pyMispVersion(); + @GET("admin/roles") + Call> getRoles(); + // user routes @GET("users/view/me") diff --git a/app/src/main/java/lu/circl/mispbump/models/restModels/MispRole.java b/app/src/main/java/lu/circl/mispbump/models/restModels/MispRole.java new file mode 100644 index 0000000..74ea347 --- /dev/null +++ b/app/src/main/java/lu/circl/mispbump/models/restModels/MispRole.java @@ -0,0 +1,10 @@ +package lu.circl.mispbump.models.restModels; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class MispRole { + @SerializedName("Role") + @Expose + public Role role; +} diff --git a/app/src/main/java/lu/circl/mispbump/models/restModels/Organisation.java b/app/src/main/java/lu/circl/mispbump/models/restModels/Organisation.java index acfdb37..a20f1e7 100644 --- a/app/src/main/java/lu/circl/mispbump/models/restModels/Organisation.java +++ b/app/src/main/java/lu/circl/mispbump/models/restModels/Organisation.java @@ -5,20 +5,20 @@ package lu.circl.mispbump.models.restModels; */ public class Organisation { - public Integer id; - public String name; - public String date_created; - public String date_modified; - public String type; - public String nationality; - public String sector; - public String contacts; - public String description; - public Boolean local; - public String uuid; - public String restricted_to_domain; - public String created_by; - public Integer user_count; + private Integer id; + private String name; + private String date_created; + private String date_modified; + private String type; + private String nationality; + private String sector; + private String contacts; + private String description; + private Boolean local; + private String uuid; + private String[] restricted_to_domain; + private String created_by; + private Integer user_count; public Organisation() { } @@ -46,6 +46,119 @@ public class Organisation { return organisation; } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDate_created() { + return date_created; + } + + public void setDate_created(String date_created) { + this.date_created = date_created; + } + + public String getDate_modified() { + return date_modified; + } + + public void setDate_modified(String date_modified) { + this.date_modified = date_modified; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getNationality() { + return nationality; + } + + public void setNationality(String nationality) { + this.nationality = nationality; + } + + public String getSector() { + return sector; + } + + public void setSector(String sector) { + this.sector = sector; + } + + public String getContacts() { + return contacts; + } + + public void setContacts(String contacts) { + this.contacts = contacts; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getLocal() { + return local; + } + + public void setLocal(Boolean local) { + this.local = local; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String[] getRestricted_to_domain() { + return restricted_to_domain; + } + + public void setRestricted_to_domain(String[] restricted_to_domain) { + this.restricted_to_domain = restricted_to_domain; + } + + public String getCreated_by() { + return created_by; + } + + public void setCreated_by(String created_by) { + this.created_by = created_by; + } + + public Integer getUser_count() { + return user_count; + } + + public void setUser_count(Integer user_count) { + this.user_count = user_count; + } + @Override public String toString() { return "Organisation{" + diff --git a/app/src/main/java/lu/circl/mispbump/models/restModels/Role.java b/app/src/main/java/lu/circl/mispbump/models/restModels/Role.java new file mode 100644 index 0000000..f016561 --- /dev/null +++ b/app/src/main/java/lu/circl/mispbump/models/restModels/Role.java @@ -0,0 +1,296 @@ +package lu.circl.mispbump.models.restModels; + +import com.google.gson.annotations.SerializedName; + +public class Role { + @SerializedName("id") + private Integer id; + @SerializedName("name") + private String name; + @SerializedName("created") + private String created; + @SerializedName("modified") + private String modified; + @SerializedName("perm_add") + private Boolean permAdd; + @SerializedName("perm_modify") + private Boolean permModify; + @SerializedName("perm_modify_org") + private Boolean permModifyOrg; + @SerializedName("perm_publish") + private Boolean permPublish; + @SerializedName("perm_delegate") + private Boolean permDelegate; + @SerializedName("perm_sync") + private Boolean permSync; + @SerializedName("perm_admin") + private Boolean permAdmin; + @SerializedName("perm_audit") + private Boolean permAudit; + @SerializedName("perm_auth") + private Boolean permAuth; + @SerializedName("perm_site_admin") + private Boolean permSiteAdmin; + @SerializedName("perm_regexp_access") + private Boolean permRegexpAccess; + @SerializedName("perm_tagger") + private Boolean permTagger; + @SerializedName("perm_template") + private Boolean permTemplate; + @SerializedName("perm_sharing_group") + private Boolean permSharingGroup; + @SerializedName("perm_tag_editor") + private Boolean permTagEditor; + @SerializedName("perm_sighting") + private Boolean permSighting; + @SerializedName("perm_object_template") + private Boolean permObjectTemplate; + @SerializedName("default_role") + private Boolean defaultRole; + @SerializedName("memory_limit") + private String memoryLimit; + @SerializedName("max_execution_time") + private String maxExecutionTime; + @SerializedName("restricted_to_site_admin") + private Boolean restrictedToSiteAdmin; + @SerializedName("perm_publish_zmq") + private Boolean permPublishZmq; + @SerializedName("perm_publish_kafka") + private Boolean permPublishKafka; + @SerializedName("permission") + private String permission; + @SerializedName("permission_description") + private String permissionDescription; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCreated() { + return created; + } + + public void setCreated(String created) { + this.created = created; + } + + public String getModified() { + return modified; + } + + public void setModified(String modified) { + this.modified = modified; + } + + public Boolean getPermAdd() { + return permAdd; + } + + public void setPermAdd(Boolean permAdd) { + this.permAdd = permAdd; + } + + public Boolean getPermModify() { + return permModify; + } + + public void setPermModify(Boolean permModify) { + this.permModify = permModify; + } + + public Boolean getPermModifyOrg() { + return permModifyOrg; + } + + public void setPermModifyOrg(Boolean permModifyOrg) { + this.permModifyOrg = permModifyOrg; + } + + public Boolean getPermPublish() { + return permPublish; + } + + public void setPermPublish(Boolean permPublish) { + this.permPublish = permPublish; + } + + public Boolean getPermDelegate() { + return permDelegate; + } + + public void setPermDelegate(Boolean permDelegate) { + this.permDelegate = permDelegate; + } + + public Boolean getPermSync() { + return permSync; + } + + public void setPermSync(Boolean permSync) { + this.permSync = permSync; + } + + public Boolean getPermAdmin() { + return permAdmin; + } + + public void setPermAdmin(Boolean permAdmin) { + this.permAdmin = permAdmin; + } + + public Boolean getPermAudit() { + return permAudit; + } + + public void setPermAudit(Boolean permAudit) { + this.permAudit = permAudit; + } + + public Boolean getPermAuth() { + return permAuth; + } + + public void setPermAuth(Boolean permAuth) { + this.permAuth = permAuth; + } + + public Boolean getPermSiteAdmin() { + return permSiteAdmin; + } + + public void setPermSiteAdmin(Boolean permSiteAdmin) { + this.permSiteAdmin = permSiteAdmin; + } + + public Boolean getPermRegexpAccess() { + return permRegexpAccess; + } + + public void setPermRegexpAccess(Boolean permRegexpAccess) { + this.permRegexpAccess = permRegexpAccess; + } + + public Boolean getPermTagger() { + return permTagger; + } + + public void setPermTagger(Boolean permTagger) { + this.permTagger = permTagger; + } + + public Boolean getPermTemplate() { + return permTemplate; + } + + public void setPermTemplate(Boolean permTemplate) { + this.permTemplate = permTemplate; + } + + public Boolean getPermSharingGroup() { + return permSharingGroup; + } + + public void setPermSharingGroup(Boolean permSharingGroup) { + this.permSharingGroup = permSharingGroup; + } + + public Boolean getPermTagEditor() { + return permTagEditor; + } + + public void setPermTagEditor(Boolean permTagEditor) { + this.permTagEditor = permTagEditor; + } + + public Boolean getPermSighting() { + return permSighting; + } + + public void setPermSighting(Boolean permSighting) { + this.permSighting = permSighting; + } + + public Boolean getPermObjectTemplate() { + return permObjectTemplate; + } + + public void setPermObjectTemplate(Boolean permObjectTemplate) { + this.permObjectTemplate = permObjectTemplate; + } + + public Boolean getDefaultRole() { + return defaultRole; + } + + public void setDefaultRole(Boolean defaultRole) { + this.defaultRole = defaultRole; + } + + public String getMemoryLimit() { + return memoryLimit; + } + + public void setMemoryLimit(String memoryLimit) { + this.memoryLimit = memoryLimit; + } + + public String getMaxExecutionTime() { + return maxExecutionTime; + } + + public void setMaxExecutionTime(String maxExecutionTime) { + this.maxExecutionTime = maxExecutionTime; + } + + public Boolean getRestrictedToSiteAdmin() { + return restrictedToSiteAdmin; + } + + public void setRestrictedToSiteAdmin(Boolean restrictedToSiteAdmin) { + this.restrictedToSiteAdmin = restrictedToSiteAdmin; + } + + public Boolean getPermPublishZmq() { + return permPublishZmq; + } + + public void setPermPublishZmq(Boolean permPublishZmq) { + this.permPublishZmq = permPublishZmq; + } + + public Boolean getPermPublishKafka() { + return permPublishKafka; + } + + public void setPermPublishKafka(Boolean permPublishKafka) { + this.permPublishKafka = permPublishKafka; + } + + public String getPermission() { + return permission; + } + + public void setPermission(String permission) { + this.permission = permission; + } + + public String getPermissionDescription() { + return permissionDescription; + } + + public void setPermissionDescription(String permissionDescription) { + this.permissionDescription = permissionDescription; + } +} diff --git a/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java b/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java index 4d2677a..e9a40af 100644 --- a/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java +++ b/app/src/main/java/lu/circl/mispbump/security/KeyStoreWrapper.java @@ -29,8 +29,7 @@ public class KeyStoreWrapper { public static final String USER_INFO_ALIAS = "ALIAS_USER_INFO"; public static final String USER_ORGANISATION_INFO_ALIAS = "ALIAS_USER_ORGANISATION_INFO"; - public static final String AUTOMATION_ALIAS = "ALIAS_AUTOMATION_KEY"; - public static final String SERVER_URL_ALIAS = "ALIAS_SERVER_URL"; + public static final String USER_CREDENTIALS_ALIAS = "ALIAS_USER_CREDENTIALS"; public static final String UPLOAD_INFORMATION_ALIAS = "ALIAS_UPLOAD_INFORMATION"; private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";