aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2008-11-01 06:21:56 +0000
committerKenny Root <kenny@the-b.org>2008-11-01 06:21:56 +0000
commit2dfa7ae033d953efb670bcc0d51e50603cf1b49a (patch)
treea096276c8735d8a6a822052e3eda75680ca6a44c
parentcff44b0992db32038e630144a34fc2869f81738e (diff)
downloadconnectbot-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.xml103
-rw-r--r--res/values/strings.xml9
-rw-r--r--src/org/connectbot/PubkeyListActivity.java77
-rw-r--r--src/org/connectbot/util/PubkeyDatabase.java52
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;
+ }
+
}