/** * A DIME request is really a SOAP request that we are dealing with, and so its authentication is * the SOAP authentication approach. Since Axis2 does not handle DIME messages we deal with them * here. * * @param request * @param response */ private void processDimeRequest(HttpServletRequest request, HttpServletResponse response) { S3PutObjectRequest putRequest = null; S3PutObjectResponse putResponse = null; int bytesRead = 0; S3Engine engine = new S3Engine(); try { logRequest(request); MultiPartDimeInputStream ds = new MultiPartDimeInputStream(request.getInputStream()); // -> the first stream MUST be the SOAP party if (ds.nextInputStream()) { // logger.debug( "DIME msg [" + ds.getStreamType() + "," + ds.getStreamTypeFormat() + "," + // ds.getStreamId() + "]" ); byte[] buffer = new byte[8192]; bytesRead = ds.read(buffer, 0, 8192); // logger.debug( "DIME SOAP Bytes read: " + bytesRead ); ByteArrayInputStream bis = new ByteArrayInputStream(buffer, 0, bytesRead); putRequest = toEnginePutObjectRequest(bis); } // -> we only need to support a DIME message with two bodyparts if (null != putRequest && ds.nextInputStream()) { InputStream is = ds.getInputStream(); putRequest.setData(is); } // -> need to do SOAP level auth here, on failure return the SOAP fault StringBuffer xml = new StringBuffer(); String AWSAccessKey = putRequest.getAccessKey(); UserInfo info = ServiceProvider.getInstance().getUserInfo(AWSAccessKey); try { S3SoapAuth.verifySignature( putRequest.getSignature(), "PutObject", putRequest.getRawTimestamp(), AWSAccessKey, info.getSecretKey()); } catch (AxisFault e) { String reason = e.toString(); int start = reason.indexOf(".AxisFault:"); if (-1 != start) reason = reason.substring(start + 11); xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); xml.append( "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" >\n"); xml.append("<soap:Body>\n"); xml.append("<soap:Fault>\n"); xml.append("<faultcode>").append(e.getFaultCode().toString()).append("</faultcode>\n"); xml.append("<faultstring>").append(reason).append("</faultstring>\n"); xml.append("</soap:Fault>\n"); xml.append("</soap:Body></soap:Envelope>"); endResponse(response, xml.toString()); return; } // -> PutObject S3 Bucket Policy would be done in the engine.handleRequest() call UserContext.current() .initContext(AWSAccessKey, info.getSecretKey(), AWSAccessKey, "S3 DIME request", request); putResponse = engine.handleRequest(putRequest); xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); xml.append( "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:tns=\"http://s3.amazonaws.com/doc/2006-03-01/\">"); xml.append("<soap:Body>"); xml.append("<tns:PutObjectResponse>"); xml.append("<tns:PutObjectResponse>"); xml.append("<tns:ETag>\"").append(putResponse.getETag()).append("\"</tns:ETag>"); xml.append("<tns:LastModified>") .append(DatatypeConverter.printDateTime(putResponse.getLastModified())) .append("</tns:LastModified>"); xml.append("</tns:PutObjectResponse></tns:PutObjectResponse>"); xml.append("</soap:Body></soap:Envelope>"); endResponse(response, xml.toString()); } catch (PermissionDeniedException e) { logger.error("Unexpected exception " + e.getMessage(), e); response.setStatus(403); endResponse(response, "Access denied"); } catch (Throwable e) { logger.error("Unexpected exception " + e.getMessage(), e); } finally { } }
/** * POST requests do not get authenticated on entry. The associated access key and signature * headers are embedded in the message not encoded as HTTP headers. */ private void processRequest( HttpServletRequest request, HttpServletResponse response, String method) { Transaction txn = Transaction.open("cloudbridge", Transaction.AWSAPI_DB, true); try { logRequest(request); // Our extensions to the S3 REST API for simple management actions // are conveyed with Request parameter "Action". // The present extensions are either to set up the user credentials // (see the cloud-bridge-register script for more detail) or // to report our version of this capability. // -> unauthenticated calls, should still be done over HTTPS String cloudAction = request.getParameter("Action"); if (!isS3APIEnabled) { throw new RuntimeException("Amazon S3 API is disabled."); } if (null != cloudAction) { if (cloudAction.equalsIgnoreCase("SetUserKeys")) { setUserKeys(request, response); return; } if (cloudAction.equalsIgnoreCase("SetCertificate")) // At present a noop return; if (cloudAction.equalsIgnoreCase("CloudS3Version")) { cloudS3Version(request, response); return; } } txn.start(); // -> authenticated calls if (!((method.equalsIgnoreCase("POST") && !(request.getQueryString().equalsIgnoreCase("delete"))))) { S3AuthParams params = extractRequestHeaders(request); authenticateRequest(request, params); } ServletAction action = routeRequest(request); if (action != null) { action.execute(request, response); } else { response.setStatus(404); endResponse(response, "File not found"); } txn.close(); } catch (InvalidBucketName e) { logger.error("Unexpected exception " + e.getMessage(), e); response.setStatus(400); endResponse(response, "Invalid Bucket Name - " + e.toString()); } catch (PermissionDeniedException e) { logger.error("Unexpected exception " + e.getMessage(), e); response.setStatus(403); endResponse(response, "Access denied - " + e.toString()); } catch (Throwable e) { logger.error("Unexpected exception " + e.getMessage(), e); response.setStatus(404); endResponse(response, "Bad request"); } finally { try { response.flushBuffer(); } catch (IOException e) { logger.error("Unexpected exception " + e.getMessage(), e); } } }