package com.spec.extender.updater; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import com.spec.extender.CONST; import com.spec.extender.exception.ExtenderException; import com.spec.extender.util._debug; public abstract class BaseUpdater implements Updater { protected abstract List<String> updateHeaders(List<String> headers, String requestBody); protected abstract String updateBody(List<String> headers, String requestBody); @Override public UpdaterPayload doUpdate(UpdaterPayload updaterPayload){ List<String> headers = updaterPayload.getHeaders(); String requestBody = updaterPayload.getRequestBody(); List<String> updatedHeaders = updateHeaders(headers, requestBody); String updatedBody = updateBody(headers, requestBody); return new UpdaterPayload(updatedHeaders, updatedBody); } @Override public String toString() { return "\n\tclass name: " + getClass().getName() + "\n\tservice base url: " + getServiceBaseURL() + "; \n\tclient id: " + getClientID() + "; \n\thmac key: " + getHmacKey() + "; \n\tsignature place holder: " + getSignaturePlaceholder(); } String replaceSigUsingPlaceholder(String signaturePlaceholder, String hmacDigest) { int placeholderIndex = signaturePlaceholder .indexOf(CONST.SIGNATURE_PLACEHOLDER_CHAR); String subStrInfront = signaturePlaceholder.substring(0, placeholderIndex); StringBuffer udpatedAuthHeaderBuffer = new StringBuffer(subStrInfront + hmacDigest); // _debug.println("signaturePlaceholder length: " + // signaturePlaceholder.length()); // _debug.println("placeholderIndex index: " + placeholderIndex); if (placeholderIndex < signaturePlaceholder.length() - 1) { String subStrAfter = signaturePlaceholder.substring( placeholderIndex + 1, signaturePlaceholder.length()); udpatedAuthHeaderBuffer.append(subStrAfter); } return udpatedAuthHeaderBuffer.toString(); } /** * If original value doens't exit, headers list doesn't change. * * @param headers * @param originalValue * @param updatedValue * @return */ protected List<String> updateAnHeader(List<String> headers, String originalValue, String updatedValue) { Iterator<String> headerIter = headers.iterator(); String[] headerArray = new String[headers.size()]; int i = 0; while (headerIter.hasNext()) { String nextHeader = headerIter.next(); if (nextHeader.startsWith(originalValue)) { nextHeader = updatedValue; } headerArray[i++] = nextHeader; } return Arrays.asList(headerArray); } /** * Sample AuthZ header: Authorization: hmac-v1 * client:UOhSQGFQNF1zxPP/MJNwc+Kk6kY= * * @param hmacSignature * @param headers * @return */ protected List<String> updateHMACHeader(List<String> headers, String hmacSignature, String signaturePlaceholder) { String udpatedAuthHeader = replaceSigUsingPlaceholder(signaturePlaceholder, hmacSignature); String signatureHeader = signaturePlaceholder.substring(0, signaturePlaceholder.indexOf(":")); // _debug.println("remove hardcoded signagure header name."); return updateAnHeader(headers, signatureHeader, udpatedAuthHeader); } /** * Burp request URL contains protocol (i.e., http/https). This method remove * the protocol and get the clean url. * * @param requestURL * @return private String retrieveURLFromBurpRequestURL(String requestURL) { if (requestURL.startsWith("https://")) return requestURL.substring(8); if (requestURL.startsWith("http://")) return requestURL.substring(7); throw new ExtenderException("Unknown protocol name."); } */ protected String retrieveHeader(List<String> headers, String HeaderName) { return getHeaderMap(headers).get(HeaderName); } protected String retrieveCaseInsensitiveHeader(List<String> headers, String HeaderName) { return retrieveCaseInsensitiveHeaderMap(headers).get(HeaderName.toLowerCase()); } protected String retrieveAuthHeader(List<String> headers) { return retrieveHeader(headers, CONST.AuthHeaderName); } /** * All keys are in lower case. * * @param headers * @return */ protected HashMap<String, String> retrieveCaseInsensitiveHeaderMap( List<String> headers) { HashMap<String, String> headerMap = new HashMap<String, String>(); for (String header : headers) { int sepIndex = header.indexOf(":"); if (sepIndex < 0) { headerMap.put(header.toLowerCase(), header.toLowerCase()); } else { // debug("sepIndex: " + sepIndex); String headerName = header.substring(0, sepIndex).trim(); String headerValue = header.substring(sepIndex + 1, header.length()).trim(); // debug(headerName + "|" + headerValue + "\n"); headerMap.put(headerName.toLowerCase(), headerValue); } } return headerMap; } protected HashMap<String, String> getHeaderMap(List<String> headers) { HashMap<String, String> headerMap = new HashMap<String, String>(); Iterator<String> headerIter = headers.iterator(); while (headerIter.hasNext()) { String header = headerIter.next(); // debug(header); int sepIndex = header.indexOf(":"); if (sepIndex < 0) { headerMap.put(header, ""); } else { // debug("sepIndex: " + sepIndex); String headerName = header.substring(0, sepIndex).trim(); String headerValue = header.substring(sepIndex + 1, header.length()).trim(); // debug(headerName + "|" + headerValue + "\n"); headerMap.put(headerName, headerValue); } } return headerMap; } protected String[] getRequestMethodUrlProtocol(String requestHeader) { String[] methodUrlProtocol = new String[3]; StringTokenizer tokenizer = new StringTokenizer(requestHeader); int i = 0; while (tokenizer.hasMoreTokens()) { methodUrlProtocol[i++] = tokenizer.nextToken(); } // debug(Arrays.toString(methodUrlProtocol)); return methodUrlProtocol; } protected String[] getRequestMethodBaseUrlQueryString(String requestHeader){ String[] mup = getRequestMethodUrlProtocol(requestHeader); _debug.println(mup[2]); String path = mup[1]; int queryIndex = path.indexOf('?'); String baseUrl = null; String queryString = null; if (queryIndex > 0){ baseUrl = path.substring(0, queryIndex); queryString = path.substring(queryIndex+1, path.length()); }else{ baseUrl = path; queryString = ""; } String[] mbq = {mup[0], baseUrl, queryString}; return mbq; } protected void addHeader(List<String> headers, String newHeader) { headers.add(newHeader); } }