1 /*
2 * SSHTools - Java SSH2 API
3 *
4 * Copyright (C) 2002-2003 Lee David Painter and Contributors.
5 *
6 * Contributions made by:
7 *
8 * Brett Smith
9 * Richard Pernavas
10 * Erwin Bolwidt
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26 package com.sshtools.daemon.configuration;
27
28 import com.sshtools.j2ssh.configuration.ExtensionAlgorithm;
29
30 import org.xml.sax.Attributes;
31 import org.xml.sax.SAXException;
32 import org.xml.sax.helpers.DefaultHandler;
33
34 import java.io.IOException;
35 import java.io.InputStream;
36
37 import java.util.ArrayList;
38 import java.util.Iterator;
39 import java.util.List;
40
41 import javax.xml.parsers.ParserConfigurationException;
42 import javax.xml.parsers.SAXParser;
43 import javax.xml.parsers.SAXParserFactory;
44
45
46 /**
47 *
48 *
49 * @author $author$
50 * @version $Revision: 1.12 $
51 */
52 public class SshAPIConfiguration extends DefaultHandler
53 implements com.sshtools.j2ssh.configuration.SshAPIConfiguration {
54 private String defaultCipher = null;
55 private String defaultMac = null;
56 private String defaultCompression = null;
57 private String defaultPublicKey = null;
58 private String defaultKeyExchange = null;
59 private List cipherExtensions = new ArrayList();
60 private List macExtensions = new ArrayList();
61 private List compressionExtensions = new ArrayList();
62 private List pkExtensions = new ArrayList();
63 private List kexExtensions = new ArrayList();
64 private List authExtensions = new ArrayList();
65 private List pkFormats = new ArrayList();
66 private List prvFormats = new ArrayList();
67 private String defaultPublicFormat = null;
68 private String defaultPrivateFormat = null;
69 private String currentElement = null;
70 private String parentElement = null;
71 private List currentList = null;
72 private ExtensionAlgorithm currentExt = null;
73
74 /**
75 * Creates a new SshAPIConfiguration object.
76 *
77 * @param in
78 *
79 * @throws SAXException
80 * @throws ParserConfigurationException
81 * @throws IOException
82 */
83 public SshAPIConfiguration(InputStream in)
84 throws SAXException, ParserConfigurationException, IOException {
85 reload(in);
86 }
87
88 /**
89 *
90 *
91 * @param in
92 *
93 * @throws SAXException
94 * @throws ParserConfigurationException
95 * @throws IOException
96 */
97 public void reload(InputStream in)
98 throws SAXException, ParserConfigurationException, IOException {
99 defaultCipher = null;
100 defaultMac = null;
101 defaultCompression = null;
102 defaultKeyExchange = null;
103 defaultPublicKey = null;
104 defaultPublicFormat = null;
105 defaultPrivateFormat = null;
106 cipherExtensions.clear();
107 macExtensions.clear();
108 compressionExtensions.clear();
109 pkExtensions.clear();
110 kexExtensions.clear();
111 authExtensions.clear();
112 pkFormats.clear();
113 prvFormats.clear();
114
115 SAXParserFactory saxFactory = SAXParserFactory.newInstance();
116 SAXParser saxParser = saxFactory.newSAXParser();
117 saxParser.parse(in, this);
118 }
119
120 /**
121 *
122 *
123 * @param ch
124 * @param start
125 * @param length
126 *
127 * @throws SAXException
128 */
129 public void characters(char[] ch, int start, int length)
130 throws SAXException {
131 String value = new String(ch, start, length);
132
133 if (currentElement != null) {
134 if (currentElement.equals("AlgorithmName")) {
135 if (currentExt != null) {
136 currentExt.setAlgorithmName(value);
137 } else {
138 throw new SAXException("Unexpected AlgorithmName element!");
139 }
140
141 return;
142 }
143
144 if (currentElement.equals("ImplementationClass")) {
145 if (currentExt != null) {
146 currentExt.setImplementationClass(value);
147 } else {
148 throw new SAXException(
149 "Unexpected ImplementationClass element!");
150 }
151
152 return;
153 }
154
155 if (currentElement.equals("DefaultAlgorithm")) {
156 if (parentElement.equals("CipherConfiguration")) {
157 defaultCipher = value;
158 } else if (parentElement.equals("MacConfiguration")) {
159 defaultMac = value;
160 } else if (parentElement.equals("CompressionConfiguration")) {
161 defaultCompression = value;
162 } else if (parentElement.equals("PublicKeyConfiguration")) {
163 defaultPublicKey = value;
164 } else if (parentElement.equals("KeyExchangeConfiguration")) {
165 defaultKeyExchange = value;
166 } else {
167 throw new SAXException(
168 "Unexpected parent elemenet for DefaultAlgorithm element");
169 }
170 }
171
172 if (currentElement.equals("DefaultPublicFormat")) {
173 defaultPublicFormat = value;
174 }
175
176 if (currentElement.equals("DefaultPrivateFormat")) {
177 defaultPrivateFormat = value;
178 }
179 }
180 }
181
182 /**
183 *
184 *
185 * @param uri
186 * @param localName
187 * @param qname
188 *
189 * @throws SAXException
190 */
191 public void endElement(String uri, String localName, String qname)
192 throws SAXException {
193 if (currentElement != null) {
194 if (!currentElement.equals(qname)) {
195 throw new SAXException("Unexpected end element found " + qname);
196 } else if (currentElement.equals("SshAPIConfiguration")) {
197 currentElement = null;
198 } else if (currentElement.equals("CipherConfiguration") ||
199 currentElement.equals("MacConfiguration") ||
200 currentElement.equals("PublicKeyConfiguration") ||
201 currentElement.equals("CompressionConfiguration") ||
202 currentElement.equals("KeyExchangeConfiguration") ||
203 currentElement.equals("AuthenticationConfiguration")) {
204 currentList = null;
205 currentElement = "SshAPIConfiguration";
206 } else if (currentElement.equals("ExtensionAlgorithm")) {
207 if (currentExt == null) {
208 throw new SAXException(
209 "Critical error, null extension algortihm");
210 }
211
212 if ((currentExt.getAlgorithmName() == null) ||
213 (currentExt.getImplementationClass() == null)) {
214 throw new SAXException(
215 "Unexpected end of ExtensionAlgorithm Element");
216 }
217
218 currentList.add(currentExt);
219 currentExt = null;
220 currentElement = parentElement;
221 } else if (currentElement.equals("DefaultAlgorithm") ||
222 currentElement.equals("DefaultPublicFormat") ||
223 currentElement.equals("DefaultPrivateFormat") ||
224 currentElement.equals("PublicKeyFormat") ||
225 currentElement.equals("PrivateKeyFormat")) {
226 currentElement = parentElement;
227 } else if (currentElement.equals("AlgorithmName")) {
228 currentElement = "ExtensionAlgorithm";
229 } else if (currentElement.equals("ImplementationClass")) {
230 currentElement = "ExtensionAlgorithm";
231 } else {
232 throw new SAXException("Unexpected end element " + qname);
233 }
234 }
235 }
236
237 /**
238 *
239 *
240 * @param uri
241 * @param localName
242 * @param qname
243 * @param attrs
244 *
245 * @throws SAXException
246 */
247 public void startElement(String uri, String localName, String qname,
248 Attributes attrs) throws SAXException {
249 if (currentElement == null) {
250 if (!qname.equals("SshAPIConfiguration")) {
251 throw new SAXException("Unexpected root element " + qname);
252 }
253 } else {
254 if (currentElement.equals("SshAPIConfiguration")) {
255 if (!qname.equals("CipherConfiguration") &&
256 !qname.equals("MacConfiguration") &&
257 !qname.equals("CompressionConfiguration") &&
258 !qname.equals("PublicKeyConfiguration") &&
259 !qname.equals("AuthenticationConfiguration") &&
260 !qname.equals("KeyExchangeConfiguration")) {
261 throw new SAXException("Unexpected <" + qname +
262 "> element after SshAPIConfiguration");
263 }
264 } else if (currentElement.equals("CipherConfiguration")) {
265 if (qname.equals("ExtensionAlgorithm")) {
266 currentList = cipherExtensions;
267 parentElement = currentElement;
268 currentExt = new ExtensionAlgorithm();
269 } else if (qname.equals("DefaultAlgorithm")) {
270 parentElement = currentElement;
271 } else {
272 throw new SAXException("Unexpected element <" + qname +
273 "> found after CipherConfiguration");
274 }
275 } else if (currentElement.equals("MacConfiguration")) {
276 if (qname.equals("ExtensionAlgorithm")) {
277 currentList = macExtensions;
278 parentElement = currentElement;
279 currentExt = new ExtensionAlgorithm();
280 } else if (qname.equals("DefaultAlgorithm")) {
281 parentElement = currentElement;
282 } else {
283 throw new SAXException("Unexpected element <" + qname +
284 "> found after CipherConfiguration");
285 }
286 } else if (currentElement.equals("CompressionConfiguration")) {
287 if (qname.equals("ExtensionAlgorithm")) {
288 currentList = compressionExtensions;
289 parentElement = currentElement;
290 currentExt = new ExtensionAlgorithm();
291 } else if (qname.equals("DefaultAlgorithm")) {
292 parentElement = currentElement;
293 } else {
294 throw new SAXException("Unexpected element <" + qname +
295 "> found after CompressionConfiguration");
296 }
297 } else if (currentElement.equals("PublicKeyConfiguration")) {
298 if (qname.equals("ExtensionAlgorithm")) {
299 currentList = pkExtensions;
300 parentElement = currentElement;
301 currentExt = new ExtensionAlgorithm();
302 } else if (qname.equals("DefaultAlgorithm")) {
303 parentElement = currentElement;
304 } else if (qname.equals("PublicKeyFormat")) {
305 String cls = attrs.getValue("ImplementationClass");
306
307 if (cls == null) {
308 throw new SAXException(
309 "<PublicKeyFormat> element requries the ImplementationClass attribute");
310 }
311
312 pkFormats.add(cls);
313 } else if (qname.equals("PrivateKeyFormat")) {
314 String cls = attrs.getValue("ImplementationClass");
315
316 if (cls == null) {
317 throw new SAXException(
318 "<PrivateKeyFormat> element requries the ImplementationClass attribute");
319 }
320
321 prvFormats.add(cls);
322 } else if (qname.equals("DefaultPublicFormat")) {
323 parentElement = currentElement;
324 } else if (qname.equals("DefaultPrivateFormat")) {
325 parentElement = currentElement;
326 } else {
327 throw new SAXException("Unexpected element <" + qname +
328 "> found after PublicKeyConfiguration");
329 }
330 } else if (currentElement.equals("AuthenticationConfiguration")) {
331 if (qname.equals("ExtensionAlgorithm")) {
332 currentList = authExtensions;
333 parentElement = currentElement;
334 currentExt = new ExtensionAlgorithm();
335 } else {
336 throw new SAXException("Unexpected element <" + qname +
337 "> found after AuthenticationConfiguration");
338 }
339 } else if (currentElement.equals("KeyExchangeConfiguration")) {
340 if (qname.equals("ExtensionAlgorithm")) {
341 currentList = kexExtensions;
342 parentElement = currentElement;
343 currentExt = new ExtensionAlgorithm();
344 } else if (qname.equals("DefaultAlgorithm")) {
345 parentElement = currentElement;
346 } else {
347 throw new SAXException("Unexpected element <" + qname +
348 "> found after KeyExchangeConfiguration");
349 }
350 } else if ((currentElement.equals("ExtensionAlgorithm") &&
351 qname.equals("AlgorithmName")) ||
352 (currentElement.equals("ExtensionAlgorithm") &&
353 qname.equals("ImplementationClass"))) {
354 } else {
355 throw new SAXException("Unexpected element " + qname);
356 }
357 }
358
359 currentElement = qname;
360 }
361
362 /**
363 *
364 *
365 * @return
366 */
367 public List getCompressionExtensions() {
368 return compressionExtensions;
369 }
370
371 /**
372 *
373 *
374 * @return
375 */
376 public List getCipherExtensions() {
377 return cipherExtensions;
378 }
379
380 /**
381 *
382 *
383 * @return
384 */
385 public List getMacExtensions() {
386 return macExtensions;
387 }
388
389 /**
390 *
391 *
392 * @return
393 */
394 public List getAuthenticationExtensions() {
395 return authExtensions;
396 }
397
398 /**
399 *
400 *
401 * @return
402 */
403 public List getPublicKeyExtensions() {
404 return pkExtensions;
405 }
406
407 /**
408 *
409 *
410 * @return
411 */
412 public List getKeyExchangeExtensions() {
413 return kexExtensions;
414 }
415
416 /**
417 *
418 *
419 * @return
420 */
421 public String getDefaultCipher() {
422 return defaultCipher;
423 }
424
425 /**
426 *
427 *
428 * @return
429 */
430 public String getDefaultMac() {
431 return defaultMac;
432 }
433
434 /**
435 *
436 *
437 * @return
438 */
439 public String getDefaultCompression() {
440 return defaultCompression;
441 }
442
443 /**
444 *
445 *
446 * @return
447 */
448 public String getDefaultPublicKey() {
449 return defaultPublicKey;
450 }
451
452 /**
453 *
454 *
455 * @return
456 */
457 public String getDefaultKeyExchange() {
458 return defaultKeyExchange;
459 }
460
461 /**
462 *
463 *
464 * @return
465 */
466 public String getDefaultPublicKeyFormat() {
467 return defaultPublicFormat;
468 }
469
470 /**
471 *
472 *
473 * @return
474 */
475 public String getDefaultPrivateKeyFormat() {
476 return defaultPrivateFormat;
477 }
478
479 /**
480 *
481 *
482 * @return
483 */
484 public List getPublicKeyFormats() {
485 return pkFormats;
486 }
487
488 /**
489 *
490 *
491 * @return
492 */
493 public List getPrivateKeyFormats() {
494 return prvFormats;
495 }
496
497 /**
498 *
499 *
500 * @return
501 */
502 public String toString() {
503 String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
504 xml += "<!-- Sshtools J2SSH Configuration file -->\n";
505 xml += "<SshAPIConfiguration>\n";
506 xml += " <!-- The Cipher configuration, add or overide default cipher implementations -->\n";
507 xml += " <CipherConfiguration>\n";
508
509 Iterator it = cipherExtensions.iterator();
510 ExtensionAlgorithm ext;
511
512 while (it.hasNext()) {
513 ext = (ExtensionAlgorithm) it.next();
514 xml += " <ExtensionAlgorithm>\n";
515 xml += (" <AlgorithmName>" + ext.getAlgorithmName() +
516 "</AlgorithmName>\n");
517 xml += (" <ImplementationClass>" +
518 ext.getImplementationClass() + "</ImplementationClass>\n");
519 xml += " </ExtensionAlgorithm>\n";
520 }
521
522 xml += (" <DefaultAlgorithm>" + defaultCipher +
523 "</DefaultAlgorithm>\n");
524 xml += " </CipherConfiguration>\n";
525 xml += " <!-- The Mac configuration, add or overide default mac implementations -->\n";
526 xml += " <MacConfiguration>\n";
527 it = macExtensions.iterator();
528
529 while (it.hasNext()) {
530 ext = (ExtensionAlgorithm) it.next();
531 xml += " <ExtensionAlgorithm>\n";
532 xml += (" <AlgorithmName>" + ext.getAlgorithmName() +
533 "</AlgorithmName>\n");
534 xml += (" <ImplementationClass>" +
535 ext.getImplementationClass() + "</ImplementationClass>\n");
536 xml += " </ExtensionAlgorithm>\n";
537 }
538
539 xml += (" <DefaultAlgorithm>" + defaultMac +
540 "</DefaultAlgorithm>\n");
541 xml += " </MacConfiguration>\n";
542 xml += " <!-- The Compression configuration, add or overide default compression implementations -->\n";
543 xml += " <CompressionConfiguration>\n";
544 it = compressionExtensions.iterator();
545
546 while (it.hasNext()) {
547 ext = (ExtensionAlgorithm) it.next();
548 xml += " <ExtensionAlgorithm>\n";
549 xml += (" <AlgorithmName>" + ext.getAlgorithmName() +
550 "</AlgorithmName>\n");
551 xml += (" <ImplementationClass>" +
552 ext.getImplementationClass() + "</ImplementationClass>\n");
553 xml += " </ExtensionAlgorithm>\n";
554 }
555
556 xml += (" <DefaultAlgorithm>" + defaultCompression +
557 "</DefaultAlgorithm>\n");
558 xml += " </CompressionConfiguration>\n";
559 xml += " <!-- The Public Key configuration, add or overide default public key implementations -->\n";
560 xml += " <PublicKeyConfiguration>\n";
561 it = pkExtensions.iterator();
562
563 while (it.hasNext()) {
564 ext = (ExtensionAlgorithm) it.next();
565 xml += " <ExtensionAlgorithm>\n";
566 xml += (" <AlgorithmName>" + ext.getAlgorithmName() +
567 "</AlgorithmName>\n");
568 xml += (" <ImplementationClass>" +
569 ext.getImplementationClass() + "</ImplementationClass>\n");
570 xml += " </ExtensionAlgorithm>\n";
571 }
572
573 xml += (" <DefaultAlgorithm>" + defaultPublicKey +
574 "</DefaultAlgorithm>\n");
575 it = pkFormats.iterator();
576
577 String cls;
578
579 while (it.hasNext()) {
580 cls = (String) it.next();
581 xml += (" <PublicKeyFormat ImplementationClass=\"" + cls +
582 "\"/>\n");
583 }
584
585 it = prvFormats.iterator();
586
587 while (it.hasNext()) {
588 cls = (String) it.next();
589 xml += (" <PrivateKeyFormat ImplementationClass=\"" + cls +
590 "\"/>\n");
591 }
592
593 xml += (" <DefaultPublicFormat>" + defaultPublicFormat +
594 "</DefaultPublicFormat>\n");
595 xml += (" <DefaultPrivateFormat>" + defaultPrivateFormat +
596 "</DefaultPrivateFormat>\n");
597 xml += " </PublicKeyConfiguration>\n";
598 xml += " <!-- The Key Exchange configuration, add or overide default key exchange implementations -->\n";
599 xml += " <KeyExchangeConfiguration>\n";
600 it = kexExtensions.iterator();
601
602 while (it.hasNext()) {
603 ext = (ExtensionAlgorithm) it.next();
604 xml += " <ExtensionAlgorithm>\n";
605 xml += (" <AlgorithmName>" + ext.getAlgorithmName() +
606 "</AlgorithmName>\n");
607 xml += (" <ImplementationClass>" +
608 ext.getImplementationClass() + "</ImplementationClass>\n");
609 xml += " </ExtensionAlgorithm>\n";
610 }
611
612 xml += (" <DefaultAlgorithm>" + defaultKeyExchange +
613 "</DefaultAlgorithm>\n");
614 xml += " </KeyExchangeConfiguration>\n";
615 xml += " <!-- The Authentication configuration, add or overide default authentication implementations -->\n";
616 xml += " <AuthenticationConfiguration>\n";
617 it = authExtensions.iterator();
618
619 while (it.hasNext()) {
620 ext = (ExtensionAlgorithm) it.next();
621 xml += " <ExtensionAlgorithm>\n";
622 xml += (" <AlgorithmName>" + ext.getAlgorithmName() +
623 "</AlgorithmName>\n");
624 xml += (" <ImplementationClass>" +
625 ext.getImplementationClass() + "</ImplementationClass>\n");
626 xml += " </ExtensionAlgorithm>\n";
627 }
628
629 xml += " </AuthenticationConfiguration>\n";
630 xml += "</SshAPIConfiguration>";
631
632 return xml;
633 }
634 }