View Javadoc

1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.documentoperation.web;
17  
18  import java.sql.Connection;
19  import java.sql.PreparedStatement;
20  import java.sql.ResultSet;
21  import java.sql.SQLException;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import javax.crypto.Cipher;
26  import javax.crypto.KeyGenerator;
27  import javax.crypto.SecretKey;
28  import javax.crypto.SecretKeyFactory;
29  import javax.crypto.spec.DESKeySpec;
30  import javax.servlet.http.HttpServletRequest;
31  import javax.servlet.http.HttpServletResponse;
32  import javax.sql.DataSource;
33  
34  import org.apache.commons.codec.binary.Base64;
35  import org.apache.commons.lang.StringUtils;
36  import org.apache.log4j.Logger;
37  import org.apache.struts.action.ActionForm;
38  import org.apache.struts.action.ActionForward;
39  import org.apache.struts.action.ActionMapping;
40  import org.kuali.rice.core.api.config.property.ConfigContext;
41  import org.kuali.rice.kew.service.KEWServiceLocator;
42  import org.kuali.rice.kew.web.KewKualiAction;
43  import org.kuali.rice.kim.api.KimConstants;
44  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
45  import org.kuali.rice.krad.exception.AuthorizationException;
46  import org.kuali.rice.krad.util.GlobalVariables;
47  import org.kuali.rice.krad.util.KRADConstants;
48  import org.kuali.rice.krad.util.KRADUtils;
49  import org.springframework.dao.DataAccessException;
50  import org.springframework.jdbc.core.JdbcTemplate;
51  import org.springframework.jdbc.core.PreparedStatementCallback;
52  import org.springframework.jdbc.core.PreparedStatementCreator;
53  
54  public class DocumentContentOperationAction extends KewKualiAction {
55  
56  	private final static String ALGORITHM = "DES/ECB/PKCS5Padding";
57  	private final static String CHARSET = "UTF-8";
58      private static Logger LOG = Logger.getLogger(DocumentContentOperationAction.class);
59  
60      public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
61  		return mapping.findForward("basic");
62  	}
63  
64  	public ActionForward encryptContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
65  		if(checkPermissions()) {
66  			DocumentContentOperationForm docContentOperationForm = (DocumentContentOperationForm)form;
67  			String formDocumentId = docContentOperationForm.getDocumentId();
68  			String[] documentIds = formDocumentId.split(",");
69  			String encryptionKey = docContentOperationForm.getKey();
70  			for(String documentId : documentIds) {
71  				String docContent = getDocumentContent(documentId);
72  				String encryptedDocContent = encrypt(encryptionKey, docContent);
73  				saveDocumentContent(documentId, encryptedDocContent);
74  			}
75  		}
76  		return mapping.findForward("basic");
77  	}
78  
79  	public ActionForward decryptContent(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
80  		if(checkPermissions()) {
81  			DocumentContentOperationForm docContentOperationForm = (DocumentContentOperationForm)form;
82  			String formDocumentId = docContentOperationForm.getDocumentId();
83  			String[] documentIds = formDocumentId.split(",");
84  			String encryptionKey = docContentOperationForm.getKey();
85  			for(String documentId : documentIds) {
86  				String docContent = getDocumentContent(documentId);
87  				String decryptedDocContent = decrypt(encryptionKey, docContent);
88  				saveDocumentContent(documentId, decryptedDocContent);
89  			}
90  		}
91  		return mapping.findForward("basic");
92  	}
93  
94  	private boolean checkPermissions() {
95  		String principalId = GlobalVariables.getUserSession().getPrincipalId();
96  		Map<String, String> permissionDetails = KRADUtils.getNamespaceAndActionClass(this.getClass());
97  
98          boolean canUseScreen = KimApiServiceLocator.getPermissionService().isAuthorizedByTemplate(principalId,
99      			KRADConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.USE_SCREEN, permissionDetails,
100 		    		new HashMap<String, String>());
101 	    if(canUseScreen && !ConfigContext.getCurrentContextConfig().isProductionEnvironment()) {
102 		    return true;
103 	    } else {
104 		    throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalName(), "encrypt or decrypt content", this.getClass().getSimpleName());
105 	    }
106 	}
107 
108 	private String getDocumentContent(final String documentId) {
109 		final DataSource dataSource = KEWServiceLocator.getDataSource();
110 		JdbcTemplate template = new JdbcTemplate(dataSource);
111 		String docContent = template.execute(
112 				new PreparedStatementCreator() {
113 					public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
114 						String sql = "SELECT doc_cntnt_txt FROM krew_doc_hdr_cntnt_t WHERE doc_hdr_id = ?";
115 						PreparedStatement statement = connection.prepareStatement(sql);
116 						return statement;
117 					}
118 				},
119 				new PreparedStatementCallback<String>() {
120 					public String doInPreparedStatement(PreparedStatement statement) throws SQLException, DataAccessException {
121 						String docContent = "";
122 						statement.setString(1, documentId);
123 						ResultSet rs = statement.executeQuery();
124 						try {
125 							while(rs.next()) {
126 								docContent = rs.getString("doc_cntnt_txt");
127 							}
128 						} finally {
129 							if(rs != null) {
130 								rs.close();
131 							}
132 						}
133 						return docContent;
134 					}
135 				});
136 		return docContent;
137 	}
138 
139 	private void saveDocumentContent(final String documentId, final String docContent) {
140 		if(StringUtils.isBlank(documentId) || StringUtils.isBlank(docContent)) {
141             LOG.info("The document Id or the doc content was blank");
142 			return;
143 		}
144 		final DataSource dataSource = KEWServiceLocator.getDataSource();
145 		JdbcTemplate template = new JdbcTemplate(dataSource);
146 		template.execute(
147 				new PreparedStatementCreator() {
148 					public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
149 						String sql = "UPDATE krew_doc_hdr_cntnt_t SET doc_cntnt_txt = ? WHERE doc_hdr_id = ?";
150 						PreparedStatement statement = connection.prepareStatement(sql);
151 						return statement;
152 					}
153 				},
154 				new PreparedStatementCallback<String>() {
155 					public String doInPreparedStatement(PreparedStatement statement) throws SQLException, DataAccessException {
156 						statement.setString(1, docContent);
157 						statement.setString(2, documentId);
158 						ResultSet rs = statement.executeQuery();
159 						if(rs != null) {
160 							rs.close();
161 						}
162 						return "";
163 					}
164 				});
165 	}
166 
167 	private SecretKey getSecretKey(String encryptionKey) throws Exception {
168 		KeyGenerator keygen = KeyGenerator.getInstance("DES");
169 		SecretKey desKey = keygen.generateKey();
170 
171 		// Create the cipher
172 		Cipher cipher = Cipher.getInstance(ALGORITHM);
173 		cipher.init((Cipher.UNWRAP_MODE), desKey);
174 
175 		byte[] bytes = Base64.decodeBase64(encryptionKey.getBytes());
176 
177 		SecretKeyFactory desFactory = SecretKeyFactory.getInstance("DES");
178 
179 		DESKeySpec keyspec = new DESKeySpec(bytes);
180 		desKey = desFactory.generateSecret(keyspec);
181 		// Create the cipher
182 		cipher.init((Cipher.WRAP_MODE), desKey);
183 		return desKey;
184 	}
185 
186 	private String encrypt(String encryptionKey, String value) throws Exception {
187 		if (StringUtils.isBlank(value)) {
188             LOG.info("The value was was blank, returning an empty string");
189             return "";
190 		}
191 
192 		// Initialize the cipher for encryption
193 		Cipher cipher = Cipher.getInstance(ALGORITHM);
194 		cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(encryptionKey));
195 
196 		try {
197 			// Our cleartext
198 			byte[] cleartext = value.toString().getBytes(CHARSET);
199 
200 			// Encrypt the cleartext
201 			byte[] ciphertext = cipher.doFinal(cleartext);
202 
203 			return new String(Base64.encodeBase64(ciphertext), CHARSET);
204 		} catch (Exception e) {
205 			throw new RuntimeException(e);
206 		}
207 	}
208 
209 	private String decrypt(String encryptionKey, String value) throws Exception {
210         if (StringUtils.isBlank(value)) {
211             LOG.info("The value was was blank, returning an empty string");
212             return "";
213         }
214 		// Initialize the same cipher for decryption
215 		Cipher cipher = Cipher.getInstance(ALGORITHM);
216 		cipher.init(Cipher.DECRYPT_MODE, getSecretKey(encryptionKey));
217 
218 		// un-Base64 encode the encrypted data
219 		byte[] encryptedData = Base64.decodeBase64(value.getBytes(CHARSET));
220 
221 		// Decrypt the ciphertext
222 		byte[] cleartext1 = cipher.doFinal(encryptedData);
223 		return new String(cleartext1, CHARSET);
224 	}
225 }