diff options
author | Kenny Root <kenny@the-b.org> | 2008-11-01 06:21:56 +0000 |
---|---|---|
committer | Kenny Root <kenny@the-b.org> | 2008-11-01 06:21:56 +0000 |
commit | 2dfa7ae033d953efb670bcc0d51e50603cf1b49a (patch) | |
tree | a096276c8735d8a6a822052e3eda75680ca6a44c | |
parent | cff44b0992db32038e630144a34fc2869f81738e (diff) | |
download | connectbot-2dfa7ae033d953efb670bcc0d51e50603cf1b49a.tar.gz connectbot-2dfa7ae033d953efb670bcc0d51e50603cf1b49a.tar.bz2 connectbot-2dfa7ae033d953efb670bcc0d51e50603cf1b49a.zip |
* Allow users to change password for pubkey entries.
-rw-r--r-- | res/layout/dia_changepassword.xml | 103 | ||||
-rw-r--r-- | res/values/strings.xml | 9 | ||||
-rw-r--r-- | src/org/connectbot/PubkeyListActivity.java | 77 | ||||
-rw-r--r-- | src/org/connectbot/util/PubkeyDatabase.java | 52 |
4 files changed, 231 insertions, 10 deletions
diff --git a/res/layout/dia_changepassword.xml b/res/layout/dia_changepassword.xml new file mode 100644 index 0000000..2487b79 --- /dev/null +++ b/res/layout/dia_changepassword.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ConnectBot: simple, powerful, open-source SSH client for Android + Copyright (C) 2007-2008 Kenny Root, Jeffrey Sharkey + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingLeft="10dip" + android:paddingRight="10dip" + > + + <TableLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + > + + <TableRow android:id="@+id/old_password_prompt"> + <TextView + android:text="@string/prompt_old_password" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <EditText + android:id="@+id/old_password" + android:layout_width="200dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:password="true" + /> + </TableRow> + + <TableRow> + <TextView + android:text="@string/prompt_password" + android:paddingRight="10dip" + android:gravity="right|center_vertical" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <EditText + android:id="@+id/password1" + android:layout_width="200dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:password="true" + /> + </TableRow> + + <TableRow> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="right" + > + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/prompt_password" + android:paddingRight="10dip" + android:gravity="right|bottom" + android:textAppearance="?android:attr/textAppearanceMedium" + /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/prompt_again" + android:paddingRight="10dip" + android:gravity="right|top" + android:textAppearance="?android:attr/textAppearanceSmall" + /> + </LinearLayout> + + <EditText + android:id="@+id/password2" + android:layout_width="200dip" + android:layout_height="wrap_content" + android:singleLine="true" + android:password="true" + /> + </TableRow> + + </TableLayout> +</LinearLayout>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index bae495a..6f08626 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -29,6 +29,15 @@ <string name="pubkey_copy_clipboard">Copy to clipboard for OpenSSH</string> <string name="pubkey_list_empty">Press "Menu" to create public keys.</string> <string name="pubkey_unknown_format">Unknown format</string> + <string name="pubkey_change_password">Change Psassword</string> + + <string name="prompt_old_password">Old password:</string> + <string name="prompt_password">Password:</string> + <string name="prompt_again">(again)</string> + + <string name="alert_passwords_do_not_match_msg">Passwords do not match!</string> + <string name="alert_wrong_password_msg">Wrong password!</string> + <string name="alert_key_corrupted_msg">Private key appears corrupt!</string> <string name="button_ok">Ok</string> <string name="button_add">Add</string> diff --git a/src/org/connectbot/PubkeyListActivity.java b/src/org/connectbot/PubkeyListActivity.java index c05d024..3330572 100644 --- a/src/org/connectbot/PubkeyListActivity.java +++ b/src/org/connectbot/PubkeyListActivity.java @@ -25,6 +25,7 @@ import org.connectbot.util.PubkeyDatabase; import org.connectbot.util.PubkeyUtils; import android.app.AlertDialog; +import android.app.Dialog; import android.app.ListActivity; import android.content.Context; import android.content.DialogInterface; @@ -44,9 +45,11 @@ import android.view.ViewGroup; import android.view.MenuItem.OnMenuItemClickListener; import android.widget.AdapterView; import android.widget.CursorAdapter; +import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; +import android.widget.TableRow; import android.widget.TextView; public class PubkeyListActivity extends ListActivity implements EventListener { @@ -58,6 +61,10 @@ public class PubkeyListActivity extends ListActivity implements EventListener { protected int COL_ID, COL_NICKNAME, COL_TYPE, COL_PRIVATE, COL_PUBLIC, COL_ENCRYPTED, COL_STARTUP; protected ClipboardManager clipboard; + + protected LayoutInflater inflater = null; + + protected Dialog changePasswordDialog; @Override public void onStart() { @@ -89,6 +96,8 @@ public class PubkeyListActivity extends ListActivity implements EventListener { this.COL_STARTUP = pubkeys.getColumnIndexOrThrow(PubkeyDatabase.FIELD_PUBKEY_STARTUP); this.clipboard = (ClipboardManager)this.getSystemService(CLIPBOARD_SERVICE); + + this.inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @@ -116,9 +125,11 @@ public class PubkeyListActivity extends ListActivity implements EventListener { final String nickname = cursor.getString(COL_NICKNAME); menu.setHeaderTitle(nickname); + final int id = cursor.getInt(COL_ID); final byte[] pubkeyEncoded = cursor.getBlob(COL_PUBLIC); final String keyType = cursor.getString(COL_TYPE); + final int encrypted = cursor.getInt(COL_ENCRYPTED); MenuItem delete = menu.add(R.string.pubkey_delete); delete.setOnMenuItemClickListener(new OnMenuItemClickListener() { @@ -141,14 +152,10 @@ public class PubkeyListActivity extends ListActivity implements EventListener { MenuItem copyToClipboard = menu.add(R.string.pubkey_copy_clipboard); copyToClipboard.setOnMenuItemClickListener(new OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { - try { - Log.d(TAG, "Trying to decode public key format: " + keyType); - + try { PublicKey pk = PubkeyUtils.decodePublic(pubkeyEncoded, keyType); String openSSHPubkey = new String(PubkeyUtils.convertToOpenSSHFormat(pk)); - - Log.d(TAG, "OpenSSH format: " + openSSHPubkey); - + clipboard.setText(openSSHPubkey); } catch (Exception e) { e.printStackTrace(); @@ -156,6 +163,52 @@ public class PubkeyListActivity extends ListActivity implements EventListener { return true; } }); + + MenuItem changePassword = menu.add(R.string.pubkey_change_password); + changePassword.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + final View changePasswordView = inflater.inflate(R.layout.dia_changepassword, null, false); + ((TableRow)changePasswordView.findViewById(R.id.old_password_prompt)) + .setVisibility(encrypted != 0 ? View.VISIBLE : View.GONE); + new AlertDialog.Builder(PubkeyListActivity.this) + .setView(changePasswordView) + .setPositiveButton(R.string.button_change, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String oldPassword = ((EditText)changePasswordView.findViewById(R.id.old_password)).getText().toString(); + String password1 = ((EditText)changePasswordView.findViewById(R.id.password1)).getText().toString(); + String password2 = ((EditText)changePasswordView.findViewById(R.id.password2)).getText().toString(); + + if (!password1.equals(password2)) { + new AlertDialog.Builder(PubkeyListActivity.this) + .setMessage(R.string.alert_passwords_do_not_match_msg) + .setPositiveButton(android.R.string.ok, null) + .create().show(); + return; + } + + try { + if (!pubkeydb.changePassword(id, oldPassword, password1)) + new AlertDialog.Builder(PubkeyListActivity.this) + .setMessage(R.string.alert_wrong_password_msg) + .setPositiveButton(android.R.string.ok, null) + .create().show(); + else + updateHandler.sendEmptyMessage(-1); + } catch (Exception e) { + Log.e(TAG, "Could not change private key password"); + e.printStackTrace(); + new AlertDialog.Builder(PubkeyListActivity.this) + .setMessage(R.string.alert_key_corrupted_msg) + .setPositiveButton(android.R.string.ok, null) + .create().show(); + } + } + }) + .setNegativeButton(android.R.string.cancel, null).create().show(); + + return true; + } + }); } public Handler updateHandler = new Handler() { @@ -166,14 +219,18 @@ public class PubkeyListActivity extends ListActivity implements EventListener { }; protected void updateCursor() { - if (this.pubkeys != null) { + /* + if (this.pubkeys != null) pubkeys.requery(); - return; - } + */ + // refresh cursor because of possible sorting change + if(this.pubkeys != null) + this.pubkeys.close(); + if(this.pubkeydb == null) return; this.pubkeys = this.pubkeydb.allPubkeys(); this.setListAdapter(new PubkeyCursorAdapter(this, this.pubkeys)); - this.startManagingCursor(pubkeys); + //this.startManagingCursor(pubkeys); } class PubkeyCursorAdapter extends CursorAdapter { diff --git a/src/org/connectbot/util/PubkeyDatabase.java b/src/org/connectbot/util/PubkeyDatabase.java index 8cfebe9..83b2f66 100644 --- a/src/org/connectbot/util/PubkeyDatabase.java +++ b/src/org/connectbot/util/PubkeyDatabase.java @@ -18,6 +18,15 @@ package org.connectbot.util; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.spec.InvalidKeySpecException; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + import android.content.ContentValues; import android.content.Context; import android.database.Cursor; @@ -107,4 +116,47 @@ public class PubkeyDatabase extends SQLiteOpenHelper { null, null, null, null, null); } + public Cursor getPubkey(long id) { + SQLiteDatabase db = this.getReadableDatabase(); + return db.query(TABLE_PUBKEYS, new String[] { "_id", + FIELD_PUBKEY_NICKNAME, FIELD_PUBKEY_TYPE, FIELD_PUBKEY_PRIVATE, + FIELD_PUBKEY_PUBLIC, FIELD_PUBKEY_ENCRYPTED, FIELD_PUBKEY_STARTUP }, + "_id = ?", new String[] { String.valueOf(id) }, + null, null, null); + } + + public boolean changePassword(long id, String oldPassword, String newPassword) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException { + SQLiteDatabase db = this.getWritableDatabase(); + + Cursor c = db.query(TABLE_PUBKEYS, new String[] { FIELD_PUBKEY_TYPE, + FIELD_PUBKEY_PRIVATE, FIELD_PUBKEY_ENCRYPTED }, + "_id = ?", new String[] { String.valueOf(id) }, + null, null, null); + + if (!c.moveToFirst()) + return false; + + String keyType = c.getString(0); + byte[] encPriv = c.getBlob(1); + c.close(); + + PrivateKey priv; + try { + priv = PubkeyUtils.decodePrivate(encPriv, keyType, oldPassword); + } catch (InvalidKeyException e) { + return false; + } catch (BadPaddingException e) { + return false; + } catch (InvalidKeySpecException e) { + return false; + } + + ContentValues values = new ContentValues(); + values.put(FIELD_PUBKEY_PRIVATE, PubkeyUtils.getEncodedPrivate(priv, newPassword)); + values.put(FIELD_PUBKEY_ENCRYPTED, newPassword.length() > 0 ? 1 : 0); + db.update(TABLE_PUBKEYS, values, "_id = ?", new String[] { String.valueOf(id) }); + + return true; + } + } |