1 /**
  2  *  ---------
  3  * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
  4  * |#       #|  
  5  * |#       #|  Copyright (c) 1999-2010 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 to a CVCA/DVCA for the
 25  * distribution of card verifiable certificates used for terminal authentication as defined in TR-03129
 26  */
 27 
 28 
 29 
 30 /**
 31  * Creates a web service connector to access services of a CVCA/DVCA as defined in TR-03129
 32  *
 33  * @class Class implementing a CVCA/DVCA web service connector
 34  * @constructor
 35  * @param {String} url the web service endpoint
 36  * @param {Boolean} isCVCA true if connection is made to CVCA instead of DVCA
 37  */
 38 function TAConnection(url, isCVCA) {
 39 	this.url = url;
 40 	this.soapcon = new SOAPConnection(SOAPConnection.SOAP11);
 41 	this.verbose = true;
 42 	this.lastReturnCode = null;
 43 	this.version = "1.1";
 44 	this.isCVCA = isCVCA;
 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 TAConnection.prototype.setVersion = function(version) {
 55 	this.version = version;
 56 }
 57 
 58 
 59 
 60 /**
 61  * Get the last error return code (Deprecated: Use getLastReturnCode() instead)
 62  *
 63  * @returns the last error return code received or null if none defined
 64  * @type String
 65  */
 66 TAConnection.prototype.getLastError = function() {
 67 	return this.lastReturnCode;
 68 }
 69 
 70 
 71 
 72 /**
 73  * Get the last return code
 74  *
 75  * @returns the last return code received or null if none defined
 76  * @type String
 77  */
 78 TAConnection.prototype.getLastReturnCode = function() {
 79 	return this.lastReturnCode;
 80 }
 81 
 82 
 83 
 84 /**
 85  * Gets the last request
 86  *
 87  * @returns the last request
 88  * @type XML
 89  */
 90 TAConnection.prototype.getLastRequest = function() {
 91 	return this.request;
 92 }
 93 
 94 
 95 
 96 /**
 97  * Gets the last response
 98  *
 99  * @returns the last response
100  * @type XML
101  */
102 TAConnection.prototype.getLastResponse = function() {
103 	return this.response;
104 }
105 
106 
107 
108 /**
109  * Close the connector and release allocated resources
110  */
111 TAConnection.prototype.close = function() {
112 	this.soapcon.close();
113 }
114 
115 
116 
117 /**
118  * Obtain a list of certificates from the CVCA or DVCA
119  *
120  * @param {String} messageID the messageID for asynchronous requests (optional)
121  * @param {String} responseURL the URL to which the asynchronous response is send (optional)
122  * @returns a lists of card verifiable certificates from the DVCA or null in case of error
123  * @type ByteString[]
124  */
125 TAConnection.prototype.getCACertificates = function(messageID, responseURL) {
126 
127 	this.lastReturnCode = null;
128 
129 	if (this.isCVCA) {
130 		var ns = new Namespace("uri:EAC-PKI-CVCA-Protocol/" + this.version);
131 	} else {
132 		var ns = new Namespace("uri:EAC-PKI-DV-Protocol/" + this.version);
133 	}
134 
135 	var ns1 = new Namespace("uri:eacBT/" + this.version);
136 
137 	var request =
138 		<ns:GetCACertificates xmlns:ns={ns} xmlns:ns1={ns1}>
139 			<callbackIndicator>callback_not_possible</callbackIndicator>
140 			<messageID>
141 			</messageID>
142 			<responseURL>
143 			</responseURL>
144 		</ns:GetCACertificates>;
145 
146 	if (typeof(messageID) != "undefined") {
147 		request.callbackIndicator = "callback_possible";
148 		request.messageID.ns1::messageID = messageID;
149 		request.responseURL.ns1::string = responseURL;
150 	}
151 
152 	if (this.verbose) {
153 		GPSystem.trace(request.toXMLString());
154 	}
155 
156 	this.request = request;
157 
158 	try	 {
159 		var response = this.soapcon.call(this.url, request);
160 		if (this.verbose) {
161 			GPSystem.trace(response.toXMLString());
162 		}
163 	}
164 	catch(e) {
165 		GPSystem.trace("SOAP call to " + this.url + " failed : " + e);
166 		throw new GPError("TAConnection", GPError.DEVICE_ERROR, 0, "getCACertificates failed with : " + e);
167 	}
168 	
169 	this.response = response;
170 
171 	var certlist = [];
172 
173 	this.lastReturnCode = response.Result.ns1::returnCode.toString();
174 
175 	if (this.lastReturnCode == "ok_cert_available") {
176 		for each (var c in response.Result.ns1::certificateSeq.ns1::certificate) {
177 			var cvc = new ByteString(c, BASE64);
178 			certlist.push(cvc);
179 			GPSystem.trace(cvc);
180 		}
181 	} else {
182 		return null;
183 	}
184 
185 	return certlist;
186 }
187 
188 
189 
190 /**
191  * Request a certificate from the parent CA using a web service
192  *
193  * @param {ByteString} certreq the certificate request
194  * @param {String} messageID the messageID for asynchronous requests (optional)
195  * @param {String} responseURL the URL to which the asynchronous response is send (optional)
196  * @returns the new certificates
197  * @type ByteString[]
198  */
199 TAConnection.prototype.requestCertificate = function(certreq, messageID, responseURL) {
200 
201 	this.lastReturnCode = null;
202 
203 	var soapConnection = new SOAPConnection();
204 
205 	if (this.isCVCA) {
206 		var ns = new Namespace("uri:EAC-PKI-CVCA-Protocol/" + this.version);
207 	} else {
208 		var ns = new Namespace("uri:EAC-PKI-DV-Protocol/" + this.version);
209 	}
210 
211 	var ns1 = new Namespace("uri:eacBT/" + this.version);
212 
213 	var request =
214 		<ns:RequestCertificate xmlns:ns={ns} xmlns:ns1={ns1}>
215 			<callbackIndicator>callback_not_possible</callbackIndicator>
216 			<messageID>
217 			</messageID>
218 			<responseURL>
219 			</responseURL>
220 			<certReq>{certreq.toString(BASE64)}</certReq>
221 		</ns:RequestCertificate>
222 
223 	if (typeof(messageID) != "undefined") {
224 		request.callbackIndicator = "callback_possible";
225 		request.messageID.ns1::messageID = messageID;
226 		request.responseURL.ns1::string = responseURL;
227 	}
228 
229 	if (this.verbose) {
230 		GPSystem.trace(request.toXMLString());
231 	}
232 
233 	this.request = request;
234 
235 	try	{
236 		var response = this.soapcon.call(this.url, request);
237 		if (this.verbose) {
238 			GPSystem.trace(response.toXMLString());
239 		}
240 	}
241 	catch(e) {
242 		GPSystem.trace("SOAP call to " + this.url + " failed : " + e);
243 		throw new GPError("TAConnection", GPError.DEVICE_ERROR, 0, "RequestCertificate failed with : " + e);
244 	}
245 	
246 	this.response = response;
247 
248 	var certlist = [];
249 
250 	this.lastReturnCode = response.Result.ns1::returnCode.toString();
251 	
252 	if (this.lastReturnCode.substr(0, 3) == "ok_") {
253 		GPSystem.trace("Received certificates from DVCA:");
254 		for each (var c in response.Result.ns1::certificateSeq.ns1::certificate) {
255 			var cvc = new ByteString(c, BASE64);
256 			certlist.push(cvc);
257 			GPSystem.trace(cvc);
258 		}
259 	} else {
260 		return null;
261 	}
262 
263 	return certlist;
264 }
265 
266 
267 
268 /**
269  * Request a certificate from the parent CA using a web service
270  *
271  * @param {ByteString} certreq the certificate request
272  * @param {String} foreignCAR the CAR of the foreign CVCA
273  * @param {String} messageID the messageID for asynchronous requests (optional)
274  * @param {String} responseURL the URL to which the asynchronous response is send (optional)
275  * @returns the new certificates
276  * @type ByteString[]
277  */
278 TAConnection.prototype.requestForeignCertificate = function(certreq, foreignCAR, messageID, responseURL) {
279 
280 	this.lastReturnCode = null;
281 
282 	var soapConnection = new SOAPConnection();
283 
284 	if (this.isCVCA) {
285 		var ns = new Namespace("uri:EAC-PKI-CVCA-Protocol/" + this.version);
286 	} else {
287 		var ns = new Namespace("uri:EAC-PKI-DV-Protocol/" + this.version);
288 	}
289 
290 	var ns1 = new Namespace("uri:eacBT/" + this.version);
291 
292 	var request =
293 		<ns:RequestForeignCertificate xmlns:ns={ns} xmlns:ns1={ns1}>
294 			<callbackIndicator>callback_not_possible</callbackIndicator>
295 			<messageID/>
296 			<responseURL/>
297 			<foreignCAR>{foreignCAR}</foreignCAR>
298 			<certReq>{certreq.toString(BASE64)}</certReq>
299 		</ns:RequestForeignCertificate>
300 
301 	if (typeof(messageID) != "undefined") {
302 		request.callbackIndicator = "callback_possible";
303 		request.messageID.ns1::messageID = messageID;
304 		request.responseURL.ns1::string = responseURL;
305 	}
306 	
307 	if (this.verbose) {
308 		GPSystem.trace(request.toXMLString());
309 	}
310 
311 	this.request = request;
312 
313 	try	{
314 		var response = this.soapcon.call(this.url, request);
315 		if (this.verbose) {
316 			GPSystem.trace(response.toXMLString());
317 		}
318 	}
319 	catch(e) {
320 		GPSystem.trace("SOAP call to " + this.url + " failed : " + e);
321 		throw new GPError("TAConnection", GPError.DEVICE_ERROR, 0, "RequestForeignCertificate failed with : " + e);
322 	}
323 	
324 	this.response = response;
325 
326 	var certlist = [];
327 
328 	this.lastReturnCode = response.Result.ns1::returnCode.toString();
329 
330 	if (this.lastReturnCode.substr(0, 3) == "ok_") {
331 		GPSystem.trace("Received certificates from DVCA:");
332 		for each (var c in response.Result.ns1::certificateSeq.ns1::certificate) {
333 			var cvc = new ByteString(c, BASE64);
334 			certlist.push(cvc);
335 			GPSystem.trace(cvc);
336 		}
337 	} else {
338 		return null;
339 	}
340 
341 	return certlist;
342 }
343 
344 
345 
346 /**
347  * Send a certificate to the DVCA
348  *
349  * @param {ByteString[]} certificates the list of certificates to post or null
350  * @param {String} messageID the messageID for asynchronous requests (optional)
351  * @param {String} statusInfo the statusInfo field of the message
352  * @type String
353  * @return the returnCode
354  */
355 TAConnection.prototype.sendCertificates = function(certificates, messageID, statusInfo) {
356 
357 	var soapConnection = new SOAPConnection();
358 
359 	if (this.isCVCA) {
360 		var ns = new Namespace("uri:EAC-PKI-DV-Protocol/" + this.version);
361 	} else {
362 		var ns = new Namespace("uri:EAC-PKI-TermContr-Protocol/" + this.version);
363 	}
364 
365 	var ns1 = new Namespace("uri:eacBT/" + this.version);
366 
367 	if (this.version == "1.0") {
368 		var request =
369 			<ns:SendCertificates xmlns:ns={ns} xmlns:ns1={ns1}>
370 				<messageID>{messageID}</messageID>
371 				<statusInfo>{statusInfo}</statusInfo>
372 				<certificateSeq>
373 				</certificateSeq>
374 			</ns:SendCertificates>;
375 	} else {
376 		var request =
377 			<ns:SendCertificates xmlns:ns={ns} xmlns:ns1={ns1}>
378 				<messageID>
379 					<ns1:messageID>{messageID}</ns1:messageID>
380 				</messageID>
381 				<statusInfo>{statusInfo}</statusInfo>
382 				<certificateSeq>
383 				</certificateSeq>
384 			</ns:SendCertificates>;
385 	}
386 
387 	var list = request.certificateSeq;
388 
389 	if (certificates) {
390 		for (var i = 0; i < certificates.length; i++) {
391 			var cvc = certificates[i];
392 			list.certificate += <ns1:certificate xmlns:ns1={ns1}>{cvc.toString(BASE64)}</ns1:certificate>
393 		}
394 	}
395 
396 	if (this.verbose) {
397 		GPSystem.trace(request.toXMLString());
398 	}
399 
400 	this.request = request;
401 
402 	try	{
403 		var response = this.soapcon.call(this.url, request);
404 		if (this.verbose) {
405 			GPSystem.trace(response.toXMLString());
406 		}
407 	}
408 	catch(e) {
409 		GPSystem.trace("SOAP call to " + this.url + " failed : " + e);
410 		throw new GPError("TAConnection", GPError.DEVICE_ERROR, 0, "SendCertificates failed with : " + e);
411 	}
412 
413 	this.response = response;
414 
415 	this.lastReturnCode = response.Result.ns1::returnCode.toString();
416 	return this.lastReturnCode;
417 }
418 
419 
420 
421 /**
422  * Convert a list of certificates in binary format to a list of CVC objects
423  *
424  * @param {ByteString[]} certlist the list of certificates
425  * @type CVC[]
426  * @return the list of certificate objects
427  */
428 TAConnection.toCVCList = function(certlist) {
429 	var certs = [];
430 	for each (var cvcbin in certlist) {
431 		certs.push(new CVC(cvcbin));
432 	}
433 	return certs;
434 }
435 
436 
437 
438 /**
439  * Convert a list of certificate objects into a list of certificates in binary format
440  *
441  * @param {CVC[]} certlist the list of certificate objects
442  * @type ByteString[]
443  * @return the list of certificates
444  */
445 TAConnection.fromCVCList = function(certlist) {
446 	var certs = [];
447 	for each (var cvc in certlist) {
448 		certs.push(cvc.getBytes());
449 	}
450 	return certs;
451 }
452 
453 
454 
455 TAConnection.test = function() {
456 	var c = new TAConnection("http://localhost:8080/se/dvca");
457 	c.verbose = true;
458 	var certlist = c.getCACertificates();
459 }
460