Add sshauthentication-api v1 support
This commit is contained in:
7
sshauthentication-api/src/main/AndroidManifest.xml
Normal file
7
sshauthentication-api/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
package="org.openintents.ssh.authentication">
|
||||
|
||||
<application/>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,6 @@
|
||||
// ISshAuthenticationService.aidl
|
||||
package org.openintents.ssh.authentication;
|
||||
|
||||
interface ISshAuthenticationService {
|
||||
Intent execute(in Intent intent);
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
* Copyright (C) 2017 Michael Perk
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
public class SshAuthenticationApi {
|
||||
private static final String TAG = "SshAuthenticationApi";
|
||||
|
||||
public static final String SERVICE_INTENT = "org.openintents.ssh.authentication.ISshAuthenticationService";
|
||||
|
||||
public static final String EXTRA_API_VERSION = "api_version";
|
||||
public static final int API_VERSION = 1;
|
||||
|
||||
public static final String EXTRA_RESULT_CODE = "result_code";
|
||||
public static final int RESULT_CODE_ERROR = 0;
|
||||
public static final int RESULT_CODE_SUCCESS = 1;
|
||||
public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = 2;
|
||||
|
||||
/**
|
||||
* ACTION_SIGN
|
||||
*
|
||||
* Sign a given challenge
|
||||
*
|
||||
* required extras:
|
||||
* String EXTRA_KEY_ID
|
||||
* byte[] EXTRA_CHALLENGE
|
||||
* int EXTRA_HASH_ALGORITHM
|
||||
*
|
||||
* returned extras:
|
||||
* byte[] EXTRA_SIGNATURE
|
||||
*/
|
||||
public static final String ACTION_SIGN = "org.openintents.ssh.action.SIGN";
|
||||
public static final String EXTRA_CHALLENGE = "challenge";
|
||||
public static final String EXTRA_HASH_ALGORITHM = "hash_algorithm";
|
||||
public static final String EXTRA_SIGNATURE = "signature";
|
||||
|
||||
/* hash algorithms used in signature generation */
|
||||
public static final int SHA1 = 0;
|
||||
public static final int SHA224 = 1;
|
||||
public static final int SHA256 = 2;
|
||||
public static final int SHA384 = 3;
|
||||
public static final int SHA512 = 4;
|
||||
public static final int RIPEMD160 = 5;
|
||||
|
||||
/**
|
||||
* ACTION_SELECT_KEY
|
||||
*
|
||||
* Select a key
|
||||
*
|
||||
* returned extras:
|
||||
* String EXTRA_KEY_ID
|
||||
* String EXTRA_KEY_DESCRIPTION
|
||||
*/
|
||||
public static final String ACTION_SELECT_KEY = "org.openintents.ssh.action.SELECT_KEY";
|
||||
public static final String EXTRA_KEY_DESCRIPTION = "key_description";
|
||||
|
||||
/**
|
||||
* ACTION_GET_PUBLIC_KEY
|
||||
*
|
||||
* Get the public key for a key
|
||||
*
|
||||
* returns the public key encoded according to the ASN.1 type
|
||||
* 'SubjectPublicKeyInfo' as defined in the X.509 standard,
|
||||
* see RFC5280, RFC3279 and draft-ietf-curdle-pkix
|
||||
* and their respective updates
|
||||
*
|
||||
* required extras:
|
||||
* String EXTRA_KEY_ID
|
||||
*
|
||||
* returned extras:
|
||||
* byte[] EXTRA_PUBLIC_KEY
|
||||
* int EXTRA_PUBLIC_KEY_ALGORITHM
|
||||
*/
|
||||
public static final String ACTION_GET_PUBLIC_KEY = "org.openintents.ssh.action.GET_PUBLIC_KEY";
|
||||
public static final String EXTRA_PUBLIC_KEY = "public_key";
|
||||
public static final String EXTRA_PUBLIC_KEY_ALGORITHM = "public_key_algorithm";
|
||||
|
||||
/* public key algorithms */
|
||||
public static final int RSA = 0;
|
||||
public static final int ECDSA = 1;
|
||||
public static final int EDDSA = 2;
|
||||
public static final int DSA = 3;
|
||||
|
||||
/**
|
||||
* ACTION_GET_SSH_PUBLIC_KEY
|
||||
*
|
||||
* Get the SSH public key for a key
|
||||
*
|
||||
* returns the public key in SSH public key format,
|
||||
* as described in RFC4253, RFC5656 and draft-ietf-curdle-ssh-ed25519
|
||||
* and their respective updates
|
||||
*
|
||||
* required extras:
|
||||
* String EXTRA_KEY_ID
|
||||
*
|
||||
* returned extras:
|
||||
* String EXTRA_SSH_PUBLIC_KEY
|
||||
*/
|
||||
public static final String ACTION_GET_SSH_PUBLIC_KEY = "org.openintents.ssh.action.GET_SSH_PUBLIC_KEY";
|
||||
public static final String EXTRA_SSH_PUBLIC_KEY = "ssh_public_key";
|
||||
|
||||
/**
|
||||
* Error result of type SshAuthenticationApiError
|
||||
*/
|
||||
public static final String EXTRA_ERROR = "error";
|
||||
|
||||
/**
|
||||
* Pending Intent requiring user interaction
|
||||
*/
|
||||
public static final String EXTRA_PENDING_INTENT = "intent";
|
||||
|
||||
/**
|
||||
* Key identifier
|
||||
*/
|
||||
public static final String EXTRA_KEY_ID = "key_id";
|
||||
|
||||
|
||||
private final ISshAuthenticationService mService;
|
||||
private final Context mContext;
|
||||
|
||||
|
||||
public SshAuthenticationApi(Context context, ISshAuthenticationService service) {
|
||||
mService = service;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public interface ISshAgentCallback {
|
||||
void onReturn(final Intent result);
|
||||
}
|
||||
|
||||
private class SshAgentAsyncTask extends AsyncTask<Void, Integer, Intent> {
|
||||
Intent data;
|
||||
ISshAgentCallback callback;
|
||||
|
||||
private SshAgentAsyncTask(Intent data, ISshAgentCallback callback) {
|
||||
this.data = data;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent doInBackground(Void... unused) {
|
||||
return executeApi(data);
|
||||
}
|
||||
|
||||
protected void onPostExecute(Intent result) {
|
||||
callback.onReturn(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
public void executeApiAsync(Intent data, ISshAgentCallback callback) {
|
||||
SshAgentAsyncTask task = new SshAgentAsyncTask(data, callback);
|
||||
|
||||
// don't serialize async tasks, always execute them in parallel
|
||||
// http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
|
||||
} else {
|
||||
task.execute((Void[]) null);
|
||||
}
|
||||
}
|
||||
|
||||
public Intent executeApi(Intent data) {
|
||||
try {
|
||||
// always send version from client
|
||||
data.putExtra(SshAuthenticationApi.EXTRA_API_VERSION, SshAuthenticationApi.API_VERSION);
|
||||
|
||||
Intent result;
|
||||
|
||||
// blocks until result is ready
|
||||
result = mService.execute(data);
|
||||
|
||||
// set class loader to current context to allow unparcelling of SshAuthenticationApiError
|
||||
// http://stackoverflow.com/a/3806769
|
||||
result.setExtrasClassLoader(mContext.getClassLoader());
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Exception in executeApi call", e);
|
||||
return createExceptionErrorResult(SshAuthenticationApiError.CLIENT_SIDE_ERROR,
|
||||
"Exception in executeApi call", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Intent createErrorResult(int errorCode, String errorMessage) {
|
||||
Log.e(TAG, errorMessage);
|
||||
Intent result = new Intent();
|
||||
result.putExtra(SshAuthenticationApi.EXTRA_ERROR, new SshAuthenticationApiError(errorCode, errorMessage));
|
||||
result.putExtra(SshAuthenticationApi.EXTRA_RESULT_CODE, SshAuthenticationApi.RESULT_CODE_ERROR);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Intent createExceptionErrorResult(int errorCode, String errorMessage, Exception e) {
|
||||
String message = errorMessage + " : " + e.getMessage();
|
||||
return createErrorResult(errorCode, message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class SshAuthenticationApiError implements Parcelable {
|
||||
|
||||
/**
|
||||
* Error codes
|
||||
*/
|
||||
/* values chosen for compatibility with openpgp-api */
|
||||
public static final int CLIENT_SIDE_ERROR = -1;
|
||||
public static final int GENERIC_ERROR = 0;
|
||||
public static final int INCOMPATIBLE_API_VERSIONS = 1;
|
||||
public static final int INTERNAL_ERROR = 2;
|
||||
|
||||
/* values chosen for no intersection with openpgp-api */
|
||||
public static final int UNKNOWN_ACTION = -128;
|
||||
public static final int NO_KEY_ID = -129;
|
||||
public static final int NO_SUCH_KEY = -130;
|
||||
public static final int NO_AUTH_KEY = -131;
|
||||
|
||||
/* values chosen to be invalid enumeration values in their respective domain */
|
||||
public static final int INVALID_ALGORITHM = -254;
|
||||
public static final int INVALID_HASH_ALGORITHM = -253;
|
||||
|
||||
|
||||
private int mError;
|
||||
private String mMessage;
|
||||
|
||||
|
||||
public SshAuthenticationApiError(int error, String message) {
|
||||
mError = error;
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
protected SshAuthenticationApiError(Parcel in) {
|
||||
mError = in.readInt();
|
||||
mMessage = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator<SshAuthenticationApiError> CREATOR = new Creator<SshAuthenticationApiError>() {
|
||||
@Override
|
||||
public SshAuthenticationApiError createFromParcel(Parcel in) {
|
||||
return new SshAuthenticationApiError(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SshAuthenticationApiError[] newArray(int size) {
|
||||
return new SshAuthenticationApiError[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int getError() {
|
||||
return mError;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mError);
|
||||
dest.writeString(mMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
* Copyright (C) 2017 Jonas Dippel
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class SshAuthenticationConnection {
|
||||
|
||||
private final Context mContext;
|
||||
private final String mTargetPackage;
|
||||
|
||||
private ISshAuthenticationService mSSHAgent;
|
||||
|
||||
/**
|
||||
* Callback for signaling connection events
|
||||
*/
|
||||
public interface OnBound {
|
||||
/**
|
||||
* Called when the connection is bound to the service
|
||||
*
|
||||
* @param sshAgent the bound remote service stub
|
||||
*/
|
||||
void onBound(ISshAuthenticationService sshAgent);
|
||||
|
||||
/**
|
||||
* Called when the connection is disconnected due to some error
|
||||
*/
|
||||
void onError();
|
||||
}
|
||||
|
||||
private OnBound mOnBoundListener;
|
||||
|
||||
/**
|
||||
* Construct an SshAuthenticationConnection instance with the desired attributes
|
||||
*
|
||||
* @param context the application context
|
||||
* @param targetPackage the package of the service to bind to
|
||||
*/
|
||||
public SshAuthenticationConnection(Context context, String targetPackage) {
|
||||
mContext = context;
|
||||
mTargetPackage = targetPackage;
|
||||
}
|
||||
|
||||
private final ServiceConnection mServiceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mSSHAgent = ISshAuthenticationService.Stub.asInterface(service);
|
||||
mOnBoundListener.onBound(mSSHAgent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mSSHAgent = null;
|
||||
mOnBoundListener.onError();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to the Service via a Connection
|
||||
*
|
||||
* @return false if service was not found or an error occured, else true
|
||||
*/
|
||||
public boolean connect(final OnBound onBoundListener) {
|
||||
mOnBoundListener = onBoundListener;
|
||||
if (mSSHAgent == null) {
|
||||
Intent intent = new Intent(SshAuthenticationApi.SERVICE_INTENT);
|
||||
intent.setPackage(mTargetPackage);
|
||||
return mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
} else {
|
||||
mOnBoundListener.onBound(mSSHAgent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the Connection is bound to a service
|
||||
*
|
||||
* @return whether the Connection is bound to a service
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return mSSHAgent != null;
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
mSSHAgent = null;
|
||||
mContext.unbindService(mServiceConnection);
|
||||
}
|
||||
|
||||
public ISshAuthenticationService getService() {
|
||||
return mSSHAgent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.request;
|
||||
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
|
||||
public class KeySelectionRequest extends Request {
|
||||
|
||||
@Override
|
||||
protected void getData(Intent intent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putData(Intent request) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAction() {
|
||||
return SshAuthenticationApi.ACTION_SELECT_KEY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.request;
|
||||
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
|
||||
public class PublicKeyRequest extends Request {
|
||||
|
||||
private String mKeyId;
|
||||
|
||||
public PublicKeyRequest(String keyId) {
|
||||
mKeyId = keyId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getData(Intent intent) {
|
||||
mKeyId = intent.getStringExtra(SshAuthenticationApi.EXTRA_KEY_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putData(Intent request) {
|
||||
request.putExtra(SshAuthenticationApi.EXTRA_KEY_ID, mKeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAction() {
|
||||
return SshAuthenticationApi.ACTION_GET_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
public String getKeyID() {
|
||||
return mKeyId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.request;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
public abstract class Request {
|
||||
|
||||
public Intent toIntent() {
|
||||
Intent request = new Intent();
|
||||
request.setAction(getAction());
|
||||
|
||||
putData(request);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private void populatefromIntent(Intent intent) {
|
||||
getData(intent);
|
||||
}
|
||||
|
||||
protected abstract void getData(Intent intent);
|
||||
|
||||
protected abstract void putData(Intent request);
|
||||
|
||||
protected abstract String getAction();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
* Copyright (C) 2017 Michael Perk
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.request;
|
||||
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApiError;
|
||||
|
||||
public class SigningRequest extends Request {
|
||||
|
||||
private byte[] mChallenge;
|
||||
private String mKeyIdentifier;
|
||||
private int mHashAlgorithm;
|
||||
|
||||
public SigningRequest(byte[] challenge, String keyIdentifier, int hashAlgorithm) {
|
||||
mHashAlgorithm = hashAlgorithm;
|
||||
mKeyIdentifier = keyIdentifier;
|
||||
mChallenge = challenge;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAction() {
|
||||
return SshAuthenticationApi.ACTION_SIGN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getData(Intent intent) {
|
||||
mHashAlgorithm = intent.getIntExtra(SshAuthenticationApi.EXTRA_HASH_ALGORITHM, SshAuthenticationApiError.INVALID_HASH_ALGORITHM);
|
||||
mKeyIdentifier = intent.getStringExtra(SshAuthenticationApi.EXTRA_KEY_ID);
|
||||
mChallenge = intent.getByteArrayExtra(SshAuthenticationApi.EXTRA_CHALLENGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putData(Intent request) {
|
||||
request.putExtra(SshAuthenticationApi.EXTRA_HASH_ALGORITHM, mHashAlgorithm);
|
||||
request.putExtra(SshAuthenticationApi.EXTRA_KEY_ID, mKeyIdentifier);
|
||||
request.putExtra(SshAuthenticationApi.EXTRA_CHALLENGE, mChallenge);
|
||||
}
|
||||
|
||||
public int getHashAlgorithm() {
|
||||
return mHashAlgorithm;
|
||||
}
|
||||
|
||||
public String getKeyIdentifier() {
|
||||
return mKeyIdentifier;
|
||||
}
|
||||
|
||||
public byte[] getChallenge() {
|
||||
return mChallenge;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.request;
|
||||
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
|
||||
public class SshPublicKeyRequest extends Request {
|
||||
|
||||
private String mKeyId;
|
||||
|
||||
public SshPublicKeyRequest(String keyId) {
|
||||
mKeyId = keyId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getData(Intent intent) {
|
||||
mKeyId = intent.getStringExtra(SshAuthenticationApi.EXTRA_KEY_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putData(Intent request) {
|
||||
request.putExtra(SshAuthenticationApi.EXTRA_KEY_ID, mKeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAction() {
|
||||
return SshAuthenticationApi.ACTION_GET_SSH_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
public String getKeyId() {
|
||||
return mKeyId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.response;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApiError;
|
||||
|
||||
public class KeySelectionResponse extends Response {
|
||||
|
||||
private String mKeyId;
|
||||
private String mKeyDescription;
|
||||
|
||||
public KeySelectionResponse(Intent data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public KeySelectionResponse(PendingIntent pendingIntent) {
|
||||
super(pendingIntent);
|
||||
}
|
||||
|
||||
public KeySelectionResponse(SshAuthenticationApiError error) {
|
||||
super(error);
|
||||
}
|
||||
|
||||
public KeySelectionResponse(String keyId, String keyDescription) {
|
||||
super();
|
||||
mKeyId = keyId;
|
||||
mKeyDescription = keyDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getResults(Intent intent) {
|
||||
mKeyId = intent.getStringExtra(SshAuthenticationApi.EXTRA_KEY_ID);
|
||||
mKeyDescription = intent.getStringExtra(SshAuthenticationApi.EXTRA_KEY_DESCRIPTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putResults(Intent intent) {
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_KEY_ID, mKeyId);
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_KEY_DESCRIPTION, mKeyDescription);
|
||||
}
|
||||
|
||||
public String getKeyId() {
|
||||
return mKeyId;
|
||||
}
|
||||
|
||||
public String getKeyDescription() {
|
||||
return mKeyDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.response;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApiError;
|
||||
|
||||
public class PublicKeyResponse extends Response {
|
||||
public static final int INVALID_ALGORITHM = SshAuthenticationApiError.INVALID_ALGORITHM;
|
||||
|
||||
private byte[] mEncodedPublicKey;
|
||||
private int mKeyAlgorithm;
|
||||
|
||||
public PublicKeyResponse(Intent data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public PublicKeyResponse(PendingIntent pendingIntent) {
|
||||
super(pendingIntent);
|
||||
}
|
||||
|
||||
public PublicKeyResponse(SshAuthenticationApiError error) {
|
||||
super(error);
|
||||
}
|
||||
|
||||
public PublicKeyResponse(byte[] encodedPublicKey,
|
||||
int keyAlgorithm) {
|
||||
super();
|
||||
mEncodedPublicKey = encodedPublicKey;
|
||||
mKeyAlgorithm = keyAlgorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getResults(Intent intent) {
|
||||
mEncodedPublicKey = intent.getByteArrayExtra(SshAuthenticationApi.EXTRA_PUBLIC_KEY);
|
||||
mKeyAlgorithm = intent.getIntExtra(SshAuthenticationApi.EXTRA_PUBLIC_KEY_ALGORITHM, INVALID_ALGORITHM);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putResults(Intent intent) {
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_PUBLIC_KEY, mEncodedPublicKey);
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_PUBLIC_KEY_ALGORITHM, mKeyAlgorithm);
|
||||
}
|
||||
|
||||
public byte[] getEncodedPublicKey() {
|
||||
return mEncodedPublicKey;
|
||||
}
|
||||
|
||||
public int getKeyAlgorithm() {
|
||||
return mKeyAlgorithm;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.response;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApiError;
|
||||
|
||||
public abstract class Response {
|
||||
public static final int RESULT_CODE_ERROR = SshAuthenticationApi.RESULT_CODE_ERROR;
|
||||
public static final int RESULT_CODE_SUCCESS = SshAuthenticationApi.RESULT_CODE_SUCCESS;
|
||||
public static final int RESULT_CODE_USER_INTERACTION_REQUIRED = SshAuthenticationApi.RESULT_CODE_USER_INTERACTION_REQUIRED;
|
||||
|
||||
protected int mResultCode;
|
||||
|
||||
protected PendingIntent mPendingIntent;
|
||||
|
||||
protected SshAuthenticationApiError mError;
|
||||
|
||||
protected Response() {
|
||||
mResultCode = RESULT_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
public Response(Intent data) {
|
||||
populateFromIntent(data);
|
||||
}
|
||||
|
||||
public Response(PendingIntent pendingIntent) {
|
||||
mPendingIntent = pendingIntent;
|
||||
mResultCode = RESULT_CODE_USER_INTERACTION_REQUIRED;
|
||||
}
|
||||
|
||||
public Response(SshAuthenticationApiError error) {
|
||||
mError = error;
|
||||
mResultCode = RESULT_CODE_ERROR;
|
||||
}
|
||||
|
||||
private void populateFromIntent(Intent intent) {
|
||||
int resultCode = intent.getIntExtra(SshAuthenticationApi.EXTRA_RESULT_CODE, SshAuthenticationApi.RESULT_CODE_ERROR);
|
||||
|
||||
switch (resultCode) {
|
||||
case SshAuthenticationApi.RESULT_CODE_SUCCESS:
|
||||
mResultCode = RESULT_CODE_SUCCESS;
|
||||
getResults(intent);
|
||||
break;
|
||||
case SshAuthenticationApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
mResultCode = RESULT_CODE_USER_INTERACTION_REQUIRED;
|
||||
mPendingIntent = intent.getParcelableExtra(SshAuthenticationApi.EXTRA_PENDING_INTENT);
|
||||
break;
|
||||
case SshAuthenticationApi.RESULT_CODE_ERROR:
|
||||
mResultCode = RESULT_CODE_ERROR;
|
||||
mError = intent.getParcelableExtra(SshAuthenticationApi.EXTRA_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public Intent toIntent() {
|
||||
Intent intent = new Intent();
|
||||
|
||||
switch (mResultCode) {
|
||||
case RESULT_CODE_SUCCESS:
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_RESULT_CODE, SshAuthenticationApi.RESULT_CODE_SUCCESS);
|
||||
putResults(intent);
|
||||
break;
|
||||
case RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_RESULT_CODE, SshAuthenticationApi.RESULT_CODE_USER_INTERACTION_REQUIRED);
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_PENDING_INTENT, mPendingIntent);
|
||||
break;
|
||||
case RESULT_CODE_ERROR:
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_RESULT_CODE, SshAuthenticationApi.RESULT_CODE_ERROR);
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_ERROR, mError);
|
||||
}
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public int getResultCode() {
|
||||
return mResultCode;
|
||||
}
|
||||
|
||||
public PendingIntent getPendingIntent() {
|
||||
return mPendingIntent;
|
||||
}
|
||||
|
||||
public SshAuthenticationApiError getError() {
|
||||
return mError;
|
||||
}
|
||||
|
||||
protected abstract void getResults(Intent intent);
|
||||
|
||||
protected abstract void putResults(Intent intent);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
* Copyright (C) 2017 Jonas Dippel, Michael Perk
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.response;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApiError;
|
||||
|
||||
public class SigningResponse extends Response {
|
||||
|
||||
private byte[] mSignature;
|
||||
|
||||
public SigningResponse(Intent data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public SigningResponse(PendingIntent pendingIntent) {
|
||||
super(pendingIntent);
|
||||
}
|
||||
|
||||
public SigningResponse(SshAuthenticationApiError error) {
|
||||
super(error);
|
||||
}
|
||||
|
||||
public SigningResponse(byte[] signature) {
|
||||
super();
|
||||
mSignature = signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getResults(Intent intent) {
|
||||
mSignature = intent.getByteArrayExtra(SshAuthenticationApi.EXTRA_SIGNATURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putResults(Intent intent) {
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_SIGNATURE, mSignature);
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
return mSignature;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.response;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApiError;
|
||||
|
||||
public class SshPublicKeyResponse extends Response {
|
||||
|
||||
private String mSshPublicKey;
|
||||
|
||||
public SshPublicKeyResponse(Intent data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public SshPublicKeyResponse(PendingIntent pendingIntent) {
|
||||
super(pendingIntent);
|
||||
}
|
||||
|
||||
public SshPublicKeyResponse(SshAuthenticationApiError error) {
|
||||
super(error);
|
||||
}
|
||||
|
||||
public SshPublicKeyResponse(String sshPublicKey) {
|
||||
super();
|
||||
mSshPublicKey = sshPublicKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getResults(Intent intent) {
|
||||
mSshPublicKey = intent.getStringExtra(SshAuthenticationApi.EXTRA_SSH_PUBLIC_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putResults(Intent intent) {
|
||||
intent.putExtra(SshAuthenticationApi.EXTRA_SSH_PUBLIC_KEY, mSshPublicKey);
|
||||
}
|
||||
|
||||
public String getSshPublicKey() {
|
||||
return mSshPublicKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Christian Hagau <ach@hagau.se>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openintents.ssh.authentication.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import org.openintents.ssh.authentication.SshAuthenticationApi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class SshAuthenticationApiUtils {
|
||||
public static List<String> getAgentProviders(Context context) {
|
||||
Intent intent = new Intent(SshAuthenticationApi.SERVICE_INTENT);
|
||||
List<ResolveInfo> resolvedInfo = context.getPackageManager().queryIntentServices(intent, 0);
|
||||
ArrayList<String> providers = new ArrayList<>();
|
||||
if (resolvedInfo != null) {
|
||||
for (ResolveInfo resolveInfoEntry : resolvedInfo) {
|
||||
providers.add(resolveInfoEntry.serviceInfo.packageName);
|
||||
}
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user