blob: 135d98e99f1a1d7cc05e0e090119f2242b6625f2 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.vending.licensing;
import android.util.Log;
import com.android.vending.licensing.LicenseCheckerCallback.ApplicationErrorCode;
import com.android.vending.licensing.Policy.LicenseResponse;
/**
* Contains data related to a licensing request and methods to verify
* and process the response.
*/
class LicenseValidator {
private static final String TAG = "LicenseValidator";
// Server response codes.
private static final int LICENSED = 0x0;
private static final int NOT_LICENSED = 0x1;
private static final int LICENSED_OLD_KEY = 0x2;
private static final int ERROR_NOT_MARKET_MANAGED = 0x3;
private static final int ERROR_INVALID_KEYS = 0x4;
private static final int ERROR_OVER_QUOTA = 0x5;
private static final int ERROR_CONTACTING_SERVER = 0x101;
private static final int ERROR_INVALID_PACKAGE_NAME = 0x102;
private static final int ERROR_NON_MATCHING_UID = 0x103;
private final Policy mPolicy;
private final LicenseCheckerCallback mCallback;
private final int mNonce;
private final String mPackageName;
private final String mVersionCode;
LicenseValidator(Policy policy, LicenseCheckerCallback callback, int nonce, String packageName,
String versionCode) {
mPolicy = policy;
mCallback = callback;
mNonce = nonce;
mPackageName = packageName;
mVersionCode = versionCode;
}
public LicenseCheckerCallback getCallback() {
return mCallback;
}
public int getNonce() {
return mNonce;
}
public String getPackageName() {
return mPackageName;
}
/**
* Verifies the response from server and calls appropriate callback method.
*
* @param responseCode server response code
* @param signedData signed data from server
* @param signature server signature
*/
public void verify(int responseCode, String signedData, String signature) {
// Parse and validate response.
// TODO(jyum): decode data with signature.
// TODO(jyum): verify timestamp is within reason. However, relying
// on device clock may lead to problems?
ResponseData data;
try {
data = ResponseData.parse(signedData);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Could not parse response.");
handleInvalidResponse();
return;
}
if (data.responseCode != responseCode) {
Log.e(TAG, "Response codes don't match.");
handleInvalidResponse();
return;
}
if (data.nonce != mNonce) {
Log.e(TAG, "Nonce doesn't match.");
handleInvalidResponse();
return;
}
if (!data.packageName.equals(mPackageName)) {
Log.e(TAG, "Package name doesn't match.");
handleInvalidResponse();
return;
}
if (!data.versionCode.equals(mVersionCode)) {
Log.e(TAG, "Version codes don't match.");
handleInvalidResponse();
return;
}
switch (responseCode) {
case LICENSED:
case LICENSED_OLD_KEY:
handleResponse(LicenseResponse.LICENSED);
break;
case NOT_LICENSED:
handleResponse(LicenseResponse.NOT_LICENSED);
break;
case ERROR_CONTACTING_SERVER:
handleResponse(LicenseResponse.CLIENT_RETRY);
break;
case ERROR_INVALID_KEYS:
case ERROR_OVER_QUOTA:
handleResponse(LicenseResponse.SERVER_RETRY);
break;
case ERROR_INVALID_PACKAGE_NAME:
handleApplicationError(ApplicationErrorCode.INVALID_PACKAGE_NAME);
break;
case ERROR_NON_MATCHING_UID:
handleApplicationError(ApplicationErrorCode.NON_MATCHING_UID);
break;
case ERROR_NOT_MARKET_MANAGED:
handleApplicationError(ApplicationErrorCode.NOT_MARKET_MANAGED);
break;
default:
Log.e(TAG, "Unknown response code for license check.");
handleInvalidResponse();
}
}
/**
* Confers with policy and calls appropriate callback method.
*
* @param response
*/
private void handleResponse(LicenseResponse response) {
if (mPolicy.allowAccess(response)) {
mCallback.allow();
} else {
mCallback.dontAllow();
}
}
private void handleApplicationError(ApplicationErrorCode code) {
mCallback.applicationError(code);
}
private void handleInvalidResponse() {
mCallback.dontAllow();
}
}