1 /**
  2  *  ---------
  3  * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
  4  * |#       #|  
  5  * |#       #|  Copyright (c) 1999-2008 CardContact Software & System Consulting
  6  * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
  7  *  --------- 
  8  *
  9  *  This file is part of OpenSCDP.
 10  *
 11  *  OpenSCDP is free software; you can redistribute it and/or modify
 12  *  it under the terms of the GNU General Public License version 2 as
 13  *  published by the Free Software Foundation.
 14  *
 15  *  OpenSCDP is distributed in the hope that it will be useful,
 16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18  *  GNU General Public License for more details.
 19  *
 20  *  You should have received a copy of the GNU General Public License
 21  *  along with OpenSCDP; if not, write to the Free Software
 22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 23  *
 24  * @fileoverview Connector implementing a web service interface for a 
 25  * Recovation Service using Restricted Identification as per TR-03129
 26  */
 27 
 28 
 29 
 30 /**
 31  * Creates a web service connector to access a revocation service as per TR-03129
 32  *
 33  * @class Class implementing a revocation service web service connector
 34  * @constructor
 35  * @param {String} url the web service endpoint
 36  * @param {Boolean} isMBS true if connection is made to an CVCA/MBS, otherwise connection is made to a DV
 37  */
 38 function RIConnection(url, isMBS) {
 39 	this.url = url;
 40 	this.soapcon = new SOAPConnection(SOAPConnection.SOAP11);
 41 	this.verbose = true;
 42 	this.lastError = null;
 43 	this.version = "1.1";
 44 	this.isMBS = isMBS;
 45 }
 46 
 47 
 48 
 49 /**
 50  * Sets the version of the WSDL to use
 51  *
 52  * @param {String} version the version to use
 53  */
 54 RIConnection.prototype.setVersion = function(version) {
 55 	this.version = version;
 56 }
 57 
 58 
 59 
 60 /**
 61  * Set the keystore used for HTTPS downloads
 62  *
 63  * @param {KeyStore} truststore the truststore for the HTTPS file download
 64  * @param {TrustStore} keystore the keystore for the HTTPS file download
 65  */
 66 RIConnection.prototype.setTrustAndKeystore = function(truststore, keystore, privateKeyPIN) {
 67 	this.truststore = truststore;
 68 	this.keystore = keystore;
 69 	this.privateKeyPIN = privateKeyPIN;
 70 }
 71 
 72 
 73 
 74 /**
 75  * Get the last error return code
 76  *
 77  * @returns the last error return code received or null if none defined
 78  * @type String
 79  */
 80 RIConnection.prototype.getLastError = function() {
 81 	return this.lastError;
 82 }
 83 
 84 
 85 
 86 /**
 87  * Close the connector and release allocated resources
 88  */
 89 RIConnection.prototype.close = function() {
 90 	this.soapcon.close();
 91 }
 92 
 93 
 94 
 95 /**
 96  * Get sector public key
 97  *
 98  * @returns the sector public key
 99  * @type ByteString
100  */
101 RIConnection.prototype.getSectorPublicKey = function(sectorID) {
102 
103 	this.lastError = null;
104 
105 	if (this.isMBS) {
106 		var ns = new Namespace("uri:EAC-PKI-CVCA-Protocol/" + this.version);
107 	} else {
108 		var ns = new Namespace("uri:EAC-PKI-DV-Protocol/" + this.version);
109 	}
110 
111 	var ns1 = new Namespace("uri:eacBT/" + this.version);
112 
113 	var request =
114 		<typ:GetSectorPublicKey xmlns:typ={ns}>
115 			<sectorID>{sectorID.toString(BASE64)}</sectorID>
116 		</typ:GetSectorPublicKey>;
117 
118 	if (this.verbose) {
119 		GPSystem.trace(request.toXMLString());
120 	}
121 
122 	try	 {
123 		var response = this.soapcon.call(this.url, request);
124 		if (this.verbose) {
125 			GPSystem.trace(response.toXMLString());
126 		}
127 	}
128 	catch(e) {
129 		GPSystem.trace("SOAP call to " + this.url + " failed : " + e);
130 		throw new GPError("RIConnection", GPError.DEVICE_ERROR, 0, "getSectorPublicKey failed with : " + e);
131 	}
132 
133 	if (!response.hasOwnProperty("Result")) {
134 		throw new GPError("RIConnection", GPError.DEVICE_ERROR, 0, "Returned SOAP message does not contain expected element Result");
135 	}
136 
137 	
138 }
139 
140 
141 
142 /**
143  * Obtain a complete blacklist list from the revocation service
144  *
145  * @returns the blacklist as CMS object
146  * @type ByteString
147  */
148 RIConnection.prototype.getCompleteBlackList = function() {
149 
150 	this.lastError = null;
151 
152 	if (this.isMBS) {
153 		var ns = new Namespace("uri:EAC-PKI-CVCA-Protocol/" + this.version);
154 	} else {
155 		var ns = new Namespace("uri:EAC-PKI-DV-Protocol/" + this.version);
156 	}
157 
158 	var ns1 = new Namespace("uri:eacBT/" + this.version);
159 
160 	var request = <typ:GetBlackList xmlns:typ={ns}>
161          <callbackIndicator>callback_not_possible</callbackIndicator>
162          <messageID>
163          </messageID>
164          <deltaIndicator>complete_list</deltaIndicator>
165          <deltaBase>
166          </deltaBase>
167     </typ:GetBlackList>;
168 
169 	if (this.verbose) {
170 		GPSystem.trace(request.toXMLString());
171 	}
172 
173 	try	 {
174 		var response = this.soapcon.call(this.url, request);
175 		if (this.verbose) {
176 			GPSystem.trace(response.toXMLString());
177 		}
178 	}
179 	catch(e) {
180 		GPSystem.trace("SOAP call to " + this.url + " failed : " + e);
181 		throw new GPError("RIConnection", GPError.DEVICE_ERROR, 0, "getBlackList failed with : " + e);
182 	}
183 
184 	if (!response.hasOwnProperty("Result")) {
185 		throw new GPError("RIConnection", GPError.DEVICE_ERROR, 0, "Returned SOAP message does not contain expected element Result");
186 	}
187 
188 	var xml = new XML(response.Result);
189 	
190 	var elementList = xml.elements();
191 	
192 	var size = elementList.length();
193 	assert(size == 2);
194 	
195 	var returnCode = elementList[0];
196 	print(returnCode.toString());
197 	assert(returnCode.toString().equals("ok_list_available"));
198 	
199 	var downloadUrl = elementList[1];
200 	print(downloadUrl);
201 	
202 	var xml = new XML(downloadUrl);
203 	var elementList = xml.elements();
204 	
205 	var conn = new URLConnection(elementList[0].toString());
206 	
207 	if (typeof(this.truststore) != "undefined") {
208 		conn.setTLSKeyStores(this.truststore, this.keystore, this.privateKeyPIN);
209 	}
210 
211 	var bl = conn.getAsByteString();
212 	
213 	return(bl);
214 }
215 
216 
217 
218 /**
219  * Obtain a complete blacklist list from the revocation service
220  *
221  * @returns the blacklist as CMS object
222  * @type ByteString
223  */
224 RIConnection.prototype.getDeltaBlackLists = function(deltaBase) {
225 
226 	this.lastError = null;
227 
228 	if (this.isMBS) {
229 		var ns = new Namespace("uri:EAC-PKI-CVCA-Protocol/" + this.version);
230 	} else {
231 		var ns = new Namespace("uri:EAC-PKI-DV-Protocol/" + this.version);
232 	}
233 
234 	var ns1 = new Namespace("uri:eacBT/" + this.version);
235 
236 	var request = <typ:GetBlackList xmlns:typ={ns} xmlns:ns1={ns1}>
237          <callbackIndicator>callback_not_possible</callbackIndicator>
238          <messageID>
239          </messageID>
240          <deltaIndicator>delta_list</deltaIndicator>
241          <deltaBase>
242 			<ns1:deltaBase>{deltaBase.toString()}</ns1:deltaBase>
243          </deltaBase>
244     </typ:GetBlackList>;
245 
246 	if (this.verbose) {
247 		GPSystem.trace(request.toXMLString());
248 	}
249 
250 	try	 {
251 		var response = this.soapcon.call(this.url, request);
252 		if (this.verbose) {
253 			GPSystem.trace(response.toXMLString());
254 		}
255 	}
256 	catch(e) {
257 		GPSystem.trace("SOAP call to " + this.url + " failed : " + e);
258 		throw new GPError("RIConnection", GPError.DEVICE_ERROR, 0, "getBlackList failed with : " + e);
259 	}
260 
261 	if (!response.hasOwnProperty("Result")) {
262 		throw new GPError("RIConnection", GPError.DEVICE_ERROR, 0, "Returned SOAP message does not contain expected element Result");
263 	}
264 
265 	var xml = new XML(response.Result);
266 	
267 	var elementList = xml.elements();
268 	
269 	var size = elementList.length();
270 	assert(size == 3);
271 	
272 	var returnCode = elementList[0];
273 	print(returnCode.toString());
274 	assert(returnCode.toString().equals("ok_list_available"));
275 	
276 	var addedItemsElement = elementList[1];
277 	var addedItemsList = addedItemsElement.elements();
278 	var addedItemsBytes = new ByteString(addedItemsList[0], BASE64);
279 	
280 	var removedItemsElement = elementList[2];
281 	var removedItemsList = removedItemsElement.elements();
282 	var removedItemsBytes = new ByteString(removedItemsList[0], BASE64);
283 	
284 	var bl = new Array(2);
285 	bl[0] = addedItemsBytes;
286 	bl[1] = removedItemsBytes;
287 	
288 	return(bl);
289 }
290 
291 
292 
293 RIConnection.test = function() {
294 	var ri = new RIConnection("https://localhost:8443/dvsd-local");
295 	var blacklist = ri.getCompleteBlackList();
296 	
297 	var deltaLists = ri.getDeltaBlackLists("9000");
298 }
299