Coverage Report - wjhk.jupload2.upload.helper.InteractiveTrustManager
 
Classes in this File Line Coverage Branch Coverage Complexity
InteractiveTrustManager
0 %
0/301
0 %
0/113
9,6
 
 1  
 //
 2  
 // $Id: InteractiveTrustManager.java 918 2010-01-08 22:21:44Z etienne_sf $
 3  
 //
 4  
 // jupload - A file upload applet.
 5  
 //
 6  
 // Copyright 2007 The JUpload Team
 7  
 //
 8  
 // Created: 30.05.2007
 9  
 // Creator: felfert
 10  
 // Last modified: $Date: 2010-01-08 23:21:44 +0100 (ven., 08 janv. 2010) $
 11  
 //
 12  
 // This program is free software; you can redistribute it and/or modify
 13  
 // it under the terms of the GNU General Public License as published by
 14  
 // the Free Software Foundation; either version 2 of the License, or
 15  
 // (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., 675 Mass Ave, Cambridge, MA 02139, USA.
 25  
 
 26  
 package wjhk.jupload2.upload.helper;
 27  
 
 28  
 import java.awt.BorderLayout;
 29  
 import java.io.File;
 30  
 import java.io.FileInputStream;
 31  
 import java.io.FileOutputStream;
 32  
 import java.io.IOException;
 33  
 import java.security.KeyStore;
 34  
 import java.security.KeyStoreException;
 35  
 import java.security.MessageDigest;
 36  
 import java.security.NoSuchAlgorithmException;
 37  
 import java.security.UnrecoverableKeyException;
 38  
 import java.security.cert.CertificateException;
 39  
 import java.security.cert.CertificateExpiredException;
 40  
 import java.security.cert.CertificateNotYetValidException;
 41  
 import java.security.cert.X509Certificate;
 42  
 import java.util.Iterator;
 43  
 import java.util.StringTokenizer;
 44  
 import java.util.Vector;
 45  
 
 46  
 import javax.crypto.BadPaddingException;
 47  
 import javax.net.ssl.KeyManager;
 48  
 import javax.net.ssl.KeyManagerFactory;
 49  
 import javax.net.ssl.TrustManager;
 50  
 import javax.net.ssl.TrustManagerFactory;
 51  
 import javax.net.ssl.X509TrustManager;
 52  
 import javax.security.auth.callback.Callback;
 53  
 import javax.security.auth.callback.CallbackHandler;
 54  
 import javax.security.auth.callback.PasswordCallback;
 55  
 import javax.security.auth.callback.UnsupportedCallbackException;
 56  
 import javax.swing.BorderFactory;
 57  
 import javax.swing.JButton;
 58  
 import javax.swing.JEditorPane;
 59  
 import javax.swing.JLabel;
 60  
 import javax.swing.JOptionPane;
 61  
 import javax.swing.JPanel;
 62  
 import javax.swing.JPasswordField;
 63  
 
 64  
 import wjhk.jupload2.policies.UploadPolicy;
 65  
 
 66  
 /**
 67  
  * An implementation of {@link javax.net.ssl.X509TrustManager} which can operate
 68  
  * in different modes. If mode is {@link #NONE}, then any server certificate is
 69  
  * accepted and no certificate-based client authentication is performed. If mode
 70  
  * is SERVER, then server certificates are verified and if verification is
 71  
  * unsuccessful, a dialog is presented to the user, which allows accepting a
 72  
  * certificate temporarily or permanently. If mode is CLIENT, then
 73  
  * certificate-based client authentication is performed. Finally, there is a
 74  
  * mode STRICT, which combines both SERVER and CLIENT modes.
 75  
  * 
 76  
  * @author felfert
 77  
  */
 78  
 public class InteractiveTrustManager implements X509TrustManager,
 79  
         CallbackHandler {
 80  
 
 81  
     /**
 82  
      * Mode for accepting any certificate.
 83  
      */
 84  
     public final static int NONE = 0;
 85  
 
 86  
     /**
 87  
      * Mode for verifying server certificate chains.
 88  
      */
 89  
     public final static int SERVER = 1;
 90  
 
 91  
     /**
 92  
      * Mode for using client certificates.
 93  
      */
 94  
     public final static int CLIENT = 2;
 95  
 
 96  
     /**
 97  
      * Mode for performing both client authentication and server cert
 98  
      * verification.
 99  
      */
 100  
     public final static int STRICT = SERVER + CLIENT;
 101  
 
 102  
     private UploadPolicy uploadPolicy;
 103  
 
 104  0
     private int mode = STRICT;
 105  
 
 106  
     private String hostname;
 107  
 
 108  
     private final static String TS = ".truststore";
 109  
 
 110  
     private final static String TSKEY = "javax.net.ssl.trustStore";
 111  
 
 112  0
     private final static String USERTS = System.getProperty("user.home")
 113  
             + File.separator + TS;
 114  
 
 115  
     /**
 116  
      * Absolute path of the truststore to use.
 117  
      */
 118  0
     private String tsname = null;
 119  
 
 120  0
     private String tspasswd = null;
 121  
 
 122  0
     private TrustManagerFactory tmf = null;
 123  
 
 124  0
     private KeyManagerFactory kmf = null;
 125  
 
 126  
     /**
 127  
      * The truststore for validation of server certificates
 128  
      */
 129  0
     private KeyStore ts = null;
 130  
 
 131  
     /**
 132  
      * The keystore for client certificates.
 133  
      */
 134  0
     private KeyStore ks = null;
 135  
 
 136  
     private String getPassword(String storename) {
 137  0
         JPasswordField pwf = new JPasswordField(16);
 138  0
         JLabel l = new JLabel(this.uploadPolicy.getLocalizedString(
 139  
                 "itm_prompt_pass", storename));
 140  0
         l.setLabelFor(pwf);
 141  0
         JPanel p = new JPanel(new BorderLayout(10, 0));
 142  0
         p.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
 143  0
         p.add(l, BorderLayout.LINE_START);
 144  0
         p.add(pwf, BorderLayout.LINE_END);
 145  0
         int res = JOptionPane.showConfirmDialog(null, p, this.uploadPolicy
 146  0
                 .getLocalizedString("itm_title_pass", storename),
 147  
                 JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
 148  0
         if (res == JOptionPane.OK_OPTION)
 149  0
             return new String(pwf.getPassword());
 150  0
         return null;
 151  
     }
 152  
 
 153  
     /**
 154  
      * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
 155  
      */
 156  
     public void handle(Callback[] callbacks)
 157  
             throws UnsupportedCallbackException {
 158  
 
 159  0
         for (int i = 0; i < callbacks.length; i++) {
 160  0
             if (callbacks[i] instanceof PasswordCallback) {
 161  
                 // prompt the user for sensitive information
 162  0
                 PasswordCallback pc = (PasswordCallback) callbacks[i];
 163  0
                 String pw = getPassword(pc.getPrompt());
 164  0
                 pc.setPassword((pw == null) ? null : pw.toCharArray());
 165  0
                 pw = null;
 166  0
             } else {
 167  0
                 throw new UnsupportedCallbackException(callbacks[i],
 168  
                         "Unrecognized Callback");
 169  
             }
 170  
         }
 171  0
     }
 172  
 
 173  
     /**
 174  
      * Create a new instance.
 175  
      * 
 176  
      * @param p The UploadPolicy to use for this instance.
 177  
      * @param hostname
 178  
      * @param passwd An optional password for the truststore.
 179  
      * @throws NoSuchAlgorithmException
 180  
      * @throws KeyStoreException
 181  
      * @throws CertificateException
 182  
      * @throws IllegalArgumentException
 183  
      * @throws UnrecoverableKeyException
 184  
      */
 185  
     public InteractiveTrustManager(UploadPolicy p, String hostname,
 186  
             String passwd) throws NoSuchAlgorithmException, KeyStoreException,
 187  
             CertificateException, IllegalArgumentException,
 188  0
             UnrecoverableKeyException {
 189  0
         this.mode = p.getSslVerifyCert();
 190  0
         this.uploadPolicy = p;
 191  0
         if ((this.mode & SERVER) != 0) {
 192  0
             if (null == passwd)
 193  
                 // The default password as distributed by Sun.
 194  0
                 passwd = "changeit";
 195  0
             this.tsname = System.getProperty(TSKEY);
 196  0
             if (null == this.tsname) {
 197  
                 // The default system-wide truststore
 198  0
                 this.tsname = System.getProperty("java.home") + File.separator
 199  
                         + "lib" + File.separator + "security" + File.separator
 200  
                         + "cacerts";
 201  
                 // If the a user-specific truststore exists, it has precedence.
 202  0
                 if (new File(USERTS).exists())
 203  0
                     this.tsname = USERTS;
 204  
             }
 205  0
             if (null == hostname || hostname.length() == 0)
 206  0
                 throw new IllegalArgumentException(
 207  
                         "hostname may not be null or empty.");
 208  0
             this.hostname = hostname;
 209  
             // Initialize the keystore only once, so that we can
 210  
             // reuse it during the session
 211  0
             if (null == this.ts) {
 212  0
                 this.ts = KeyStore.getInstance(KeyStore.getDefaultType());
 213  
                 while (true) {
 214  
                     try {
 215  0
                         FileInputStream is = new FileInputStream(this.tsname);
 216  0
                         this.ts.load(is, passwd.toCharArray());
 217  0
                         is.close();
 218  
                         // need it later for eventual storing.
 219  0
                         this.tspasswd = passwd;
 220  0
                         break;
 221  0
                     } catch (IOException e) {
 222  0
                         if (e
 223  0
                                 .getMessage()
 224  0
                                 .equals(
 225  
                                         "Keystore was tampered with, or password was incorrect")) {
 226  0
                             passwd = getPassword(this.uploadPolicy
 227  0
                                     .getLocalizedString("itm_tstore"));
 228  0
                             if (null != passwd)
 229  0
                                 continue;
 230  
                         }
 231  0
                         throw new KeyStoreException("Could not load truststore");
 232  
                     }
 233  
                 }
 234  
             }
 235  0
             this.tmf = TrustManagerFactory.getInstance(TrustManagerFactory
 236  0
                     .getDefaultAlgorithm());
 237  0
             this.tmf.init(this.ts);
 238  
         }
 239  0
         if ((this.mode & CLIENT) != 0) {
 240  0
             String ksname = System.getProperty("javax.net.ssl.keyStore");
 241  0
             if (null == ksname)
 242  0
                 ksname = System.getProperty("user.home") + File.separator
 243  
                         + ".keystore";
 244  0
             String cpass = "changeit";
 245  0
             File f = new File(ksname);
 246  0
             if (!(f.exists() && f.isFile()))
 247  0
                 throw new KeyStoreException("Keystore " + ksname
 248  
                         + " does not exist.");
 249  0
             if (null == this.kmf) {
 250  0
                 String kstype = ksname.toLowerCase().endsWith(".p12") ? "PKCS12"
 251  0
                         : KeyStore.getDefaultType();
 252  0
                 this.ks = KeyStore.getInstance(kstype);
 253  
                 while (true) {
 254  
                     try {
 255  0
                         FileInputStream is = new FileInputStream(ksname);
 256  0
                         this.ks.load(is, cpass.toCharArray());
 257  0
                         is.close();
 258  0
                         break;
 259  0
                     } catch (IOException e) {
 260  0
                         if ((e.getCause() instanceof BadPaddingException)
 261  0
                                 || (e.getMessage()
 262  0
                                         .equals("Keystore was tampered with, or password was incorrect"))) {
 263  0
                             cpass = getPassword("Keystore");
 264  0
                             if (null != cpass)
 265  0
                                 continue;
 266  
                         }
 267  0
                         throw new KeyStoreException("Could not load keystore: "
 268  0
                                 + e.getMessage());
 269  
                     }
 270  
                 }
 271  0
                 this.kmf = KeyManagerFactory.getInstance(KeyManagerFactory
 272  0
                         .getDefaultAlgorithm());
 273  0
                 this.kmf.init(this.ks, cpass.toCharArray());
 274  
             }
 275  
         }
 276  
 
 277  0
     }
 278  
 
 279  
     /**
 280  
      * Retrieve key managers.
 281  
      * 
 282  
      * @return The current array of key managers.
 283  
      */
 284  
     public KeyManager[] getKeyManagers() {
 285  0
         return ((this.mode & CLIENT) == 0) ? null : this.kmf.getKeyManagers();
 286  
     }
 287  
 
 288  
     /**
 289  
      * Retrieve trust managers.
 290  
      * 
 291  
      * @return The current array of trust managers
 292  
      */
 293  
     public X509TrustManager[] getTrustManagers() {
 294  0
         return new X509TrustManager[] {
 295  
             this
 296  
         };
 297  
     }
 298  
 
 299  
     /**
 300  
      * As this class is used on the client side only, The implementation of this
 301  
      * method does nothing.
 302  
      * 
 303  
      * @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[],
 304  
      *      java.lang.String)
 305  
      */
 306  
     public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
 307  
         // Nothing to do.
 308  0
     }
 309  
 
 310  
     /**
 311  
      * Format a DN. This method formats a DN (Distinguished Name) string as
 312  
      * returned from {@link javax.security.auth.x500.X500Principal#getName()} to
 313  
      * HTML table columns.
 314  
      * 
 315  
      * @param dn The DN to format.
 316  
      * @param cn An optional CN (Common Name) to match against the CN in the DN.
 317  
      *            If this parameter is non null and the CN, encoded in the DN
 318  
      *            does not match the CN specified, it is considered an error and
 319  
      *            the CN is printed accordingly (red).
 320  
      * @param reason A vector of error-strings. If the CN-comparison fails, an
 321  
      *            explanation is added to this vector.
 322  
      * @return A string, containing the HTML code rendering the given DN in a
 323  
      *         table.
 324  
      */
 325  
     private String formatDN(String dn, String cn, Vector<String> reason) {
 326  0
         StringBuffer ret = new StringBuffer();
 327  0
         StringTokenizer t = new StringTokenizer(dn, ",");
 328  0
         while (t.hasMoreTokens()) {
 329  0
             String tok = t.nextToken();
 330  0
             while (tok.endsWith("\\"))
 331  0
                 tok += t.nextToken();
 332  0
             String kv[] = tok.split("=", 2);
 333  0
             if (kv.length == 2) {
 334  0
                 if (kv[0].equals("C"))
 335  0
                     ret.append("<tr><td>").append(
 336  0
                             this.uploadPolicy.getLocalizedString("itm_cert_C"))
 337  0
                             .append("</td><td>").append(kv[1]).append(
 338  
                                     "</td></tr>\n");
 339  0
                 if (kv[0].equals("CN")) {
 340  0
                     boolean ok = true;
 341  0
                     if (null != cn)
 342  0
                         ok = cn.equals(kv[1]);
 343  0
                     ret.append("<tr><td>")
 344  0
                             .append(
 345  
                                     this.uploadPolicy
 346  0
                                             .getLocalizedString("itm_cert_CN"))
 347  0
                             .append("</td><td");
 348  0
                     ret.append(ok ? ">" : " class=\"err\">").append(kv[1])
 349  0
                             .append("</td></tr>\n");
 350  0
                     if (!ok)
 351  0
                         reason.add(this.uploadPolicy.getLocalizedString(
 352  
                                 "itm_reason_cnmatch", cn));
 353  
                 }
 354  0
                 if (kv[0].equals("L"))
 355  0
                     ret.append("<tr><td>").append(
 356  0
                             this.uploadPolicy.getLocalizedString("itm_cert_L"))
 357  0
                             .append("</td><td>").append(kv[1]).append(
 358  
                                     "</td></tr>\n");
 359  0
                 if (kv[0].equals("ST"))
 360  0
                     ret.append("<tr><td>")
 361  0
                             .append(
 362  
                                     this.uploadPolicy
 363  0
                                             .getLocalizedString("itm_cert_ST"))
 364  0
                             .append("</td><td>").append(kv[1]).append(
 365  
                                     "</td></tr>\n");
 366  0
                 if (kv[0].equals("O"))
 367  0
                     ret.append("<tr><td>").append(
 368  0
                             this.uploadPolicy.getLocalizedString("itm_cert_O"))
 369  0
                             .append("</td><td>").append(kv[1]).append(
 370  
                                     "</td></tr>\n");
 371  0
                 if (kv[0].equals("OU"))
 372  0
                     ret.append("<tr><td>")
 373  0
                             .append(
 374  
                                     this.uploadPolicy
 375  0
                                             .getLocalizedString("itm_cert_OU"))
 376  0
                             .append("</td><td>").append(kv[1]).append(
 377  
                                     "</td></tr>\n");
 378  
             }
 379  0
         }
 380  0
         return ret.toString();
 381  
     }
 382  
 
 383  
     private void CertDialog(X509Certificate c) throws CertificateException {
 384  
         int i;
 385  0
         boolean expired = false;
 386  0
         boolean notyet = false;
 387  0
         Vector<String> reason = new Vector<String>();
 388  0
         reason.add(this.uploadPolicy.getLocalizedString("itm_reason_itrust"));
 389  
         try {
 390  0
             c.checkValidity();
 391  0
         } catch (CertificateExpiredException e1) {
 392  0
             expired = true;
 393  0
             reason.add(this.uploadPolicy
 394  0
                     .getLocalizedString("itm_reason_expired"));
 395  0
         } catch (CertificateNotYetValidException e2) {
 396  0
             notyet = true;
 397  0
             reason.add(this.uploadPolicy
 398  0
                     .getLocalizedString("itm_reason_notyet"));
 399  0
         }
 400  
 
 401  0
         StringBuffer msg = new StringBuffer();
 402  0
         msg.append("<html><head>");
 403  0
         msg.append("<style type=\"text/css\">\n");
 404  0
         msg.append("td, th, p, body { ");
 405  0
         msg.append("font-family: Arial, Helvetica, sans-serif; ");
 406  0
         msg.append("font-size: 12pt; ");
 407  
         // PLAF hassle. The PLAF renders controls with different text colors,
 408  
         // but
 409  
         // does not set SystemColor.controlText. So we create a dummy button and
 410  
         // retrieve its text color.
 411  0
         Integer ii = Integer
 412  0
                 .valueOf(new JButton(".").getForeground().getRGB() & 0x00ffffff);
 413  0
         msg.append("color: ").append(String.format("#%06x", ii)).append(" }\n");
 414  0
         msg.append("th { text-align: left; }\n");
 415  0
         msg.append("td { margin-left: 20; }\n");
 416  0
         msg.append(".err { color: red; }\n");
 417  0
         msg.append("</style>\n");
 418  0
         msg.append("</head><body>");
 419  0
         msg.append("<h3>").append(
 420  0
                 this.uploadPolicy.getLocalizedString("itm_fail_verify"))
 421  0
                 .append("</h3>");
 422  0
         msg.append("<h4>").append(
 423  0
                 this.uploadPolicy.getLocalizedString("itm_cert_details"))
 424  0
                 .append("</h4>");
 425  0
         msg.append("<table>");
 426  0
         msg.append("<tr><th colspan=2>").append(
 427  0
                 this.uploadPolicy.getLocalizedString("itm_cert_subject"))
 428  0
                 .append("</th></tr>");
 429  0
         msg.append(formatDN(c.getSubjectX500Principal().getName(),
 430  
                 this.hostname, reason));
 431  0
         msg.append("<tr><td>").append(
 432  0
                 this.uploadPolicy.getLocalizedString("itm_cert_nbefore"))
 433  0
                 .append("</td>");
 434  0
         msg.append(notyet ? "<td class=\"err\">" : "<td>").append(
 435  0
                 c.getNotBefore()).append("</td></tr>\n");
 436  0
         msg.append("<tr><td>").append(
 437  0
                 this.uploadPolicy.getLocalizedString("itm_cert_nafter"))
 438  0
                 .append("</td>");
 439  0
         msg.append(expired ? "<td class=\"err\">" : "<td>").append(
 440  0
                 c.getNotAfter()).append("</td></tr>\n");
 441  0
         msg.append("<tr><td>").append(
 442  0
                 this.uploadPolicy.getLocalizedString("itm_cert_serial"))
 443  0
                 .append("</td><td>");
 444  0
         msg.append(c.getSerialNumber());
 445  0
         msg.append("</td></tr>\n");
 446  0
         msg.append("<tr><td>")
 447  0
                 .append(
 448  0
                         this.uploadPolicy.getLocalizedString("itm_cert_fprint",
 449  0
                                 "SHA1")).append("</td><td>");
 450  
         MessageDigest d;
 451  0
         StringBuffer fp = new StringBuffer();
 452  
         try {
 453  0
             d = MessageDigest.getInstance("SHA1");
 454  0
         } catch (NoSuchAlgorithmException e) {
 455  0
             throw new CertificateException(
 456  
                     "Unable to calculate certificate SHA1 fingerprint: "
 457  0
                             + e.getMessage());
 458  0
         }
 459  0
         byte[] sha1sum = d.digest(c.getEncoded());
 460  0
         for (i = 0; i < sha1sum.length; i++) {
 461  0
             if (i > 0)
 462  0
                 fp.append(":");
 463  0
             fp.append(Integer.toHexString((sha1sum[i] >> 4) & 0x0f));
 464  0
             fp.append(Integer.toHexString(sha1sum[i] & 0x0f));
 465  
         }
 466  0
         msg.append(fp).append("</td></tr>\n");
 467  0
         fp.setLength(0);
 468  0
         msg.append("<tr><td>").append(
 469  0
                 this.uploadPolicy.getLocalizedString("itm_cert_fprint", "MD5"))
 470  0
                 .append("</td><td>");
 471  
         try {
 472  0
             d = MessageDigest.getInstance("MD5");
 473  0
         } catch (NoSuchAlgorithmException e) {
 474  0
             throw new CertificateException(
 475  
                     "Unable to calculate certificate MD5 fingerprint: "
 476  0
                             + e.getMessage());
 477  0
         }
 478  0
         byte[] md5sum = d.digest(c.getEncoded());
 479  0
         for (i = 0; i < md5sum.length; i++) {
 480  0
             if (i > 0)
 481  0
                 fp.append(":");
 482  0
             fp.append(Integer.toHexString((md5sum[i] >> 4) & 0x0f));
 483  0
             fp.append(Integer.toHexString(md5sum[i] & 0x0f));
 484  
         }
 485  0
         msg.append(fp).append("</td></tr>\n");
 486  0
         msg.append("</table><table>");
 487  0
         msg.append("<tr><th colspan=2>").append(
 488  0
                 this.uploadPolicy.getLocalizedString("itm_cert_issuer"))
 489  0
                 .append("</th></tr>");
 490  0
         msg
 491  0
                 .append(formatDN(c.getIssuerX500Principal().getName(), null,
 492  
                         reason));
 493  0
         msg.append("</table>");
 494  0
         msg.append("<p><b>").append(
 495  0
                 this.uploadPolicy.getLocalizedString("itm_reasons")).append(
 496  
                 "</b><br><ul>");
 497  0
         Iterator<String> it = reason.iterator();
 498  0
         while (it.hasNext()) {
 499  0
             msg.append("<li>" + it.next() + "</li>\n");
 500  
         }
 501  0
         msg.append("</ul></p>");
 502  0
         msg.append("<p><b>").append(
 503  0
                 this.uploadPolicy.getLocalizedString("itm_accept_prompt"))
 504  0
                 .append("</b></p>");
 505  0
         msg.append("</body></html>");
 506  
 
 507  0
         JPanel p = new JPanel();
 508  0
         p.setLayout(new BorderLayout());
 509  0
         JEditorPane ep = new JEditorPane("text/html", msg.toString());
 510  0
         ep.setEditable(false);
 511  0
         ep.setBackground(p.getBackground());
 512  0
         p.add(ep, BorderLayout.CENTER);
 513  
 
 514  0
         String no = this.uploadPolicy.getLocalizedString("itm_accept_no");
 515  0
         int ans = JOptionPane.showOptionDialog(null, p,
 516  
                 "SSL Certificate Alert", JOptionPane.YES_NO_CANCEL_OPTION,
 517  
                 JOptionPane.WARNING_MESSAGE, null, new String[] {
 518  
                         this.uploadPolicy
 519  0
                                 .getLocalizedString("itm_accept_always"),
 520  0
                         this.uploadPolicy.getLocalizedString("itm_accept_now"),
 521  
                         no
 522  
                 }, no);
 523  0
         switch (ans) {
 524  
             case JOptionPane.CANCEL_OPTION:
 525  
             case JOptionPane.CLOSED_OPTION:
 526  0
                 throw new CertificateException("Server certificate rejected.");
 527  
             case JOptionPane.NO_OPTION:
 528  
             case JOptionPane.YES_OPTION:
 529  
                 // Add certificate to truststore
 530  
                 try {
 531  0
                     this.ts.setCertificateEntry(fp.toString(), c);
 532  0
                 } catch (KeyStoreException e) {
 533  0
                     throw new CertificateException(
 534  0
                             "Unable to add certificate: " + e.getMessage());
 535  0
                 }
 536  0
                 if (ans == JOptionPane.YES_OPTION) {
 537  
                     // Save truststore for permanent acceptance.
 538  
                     // If not explicitely specified, we save to a
 539  
                     // user-truststore.
 540  0
                     if (null == System.getProperty(TSKEY))
 541  0
                         this.tsname = USERTS;
 542  
                     while (true) {
 543  
                         try {
 544  0
                             File f = new File(this.tsname);
 545  0
                             boolean old = false;
 546  0
                             if (f.exists()) {
 547  0
                                 if (!f.renameTo(new File(this.tsname + ".old")))
 548  0
                                     throw new IOException(
 549  
                                             "Could not rename truststore");
 550  0
                                 old = true;
 551  
                             } else {
 552  
                                 // New truststore, get a new password.
 553  0
                                 this.tspasswd = this
 554  0
                                         .getPassword(this.uploadPolicy
 555  0
                                                 .getLocalizedString("itm_new_tstore"));
 556  0
                                 if (null == this.tspasswd)
 557  0
                                     this.tspasswd = "changeit";
 558  
                             }
 559  0
                             FileOutputStream os = new FileOutputStream(
 560  
                                     this.tsname);
 561  0
                             this.ts.store(os, this.tspasswd.toCharArray());
 562  0
                             os.close();
 563  0
                             if (old && (!f.delete()))
 564  0
                                 throw new IOException(
 565  
                                         "Could not delete old truststore");
 566  
                             // Must re-initialize TrustManagerFactory
 567  0
                             this.tmf.init(this.ts);
 568  0
                             System.out.println("Saved cert to " + this.tsname);
 569  0
                             break;
 570  0
                         } catch (Exception e) {
 571  0
                             if (this.tsname.equals(USERTS))
 572  0
                                 throw new CertificateException(e);
 573  0
                             this.tsname = USERTS;
 574  0
                         }
 575  
                     }
 576  
                 }
 577  
         }
 578  0
     }
 579  
 
 580  
     /**
 581  
      * @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[],
 582  
      *      java.lang.String)
 583  
      */
 584  
     public void checkServerTrusted(X509Certificate[] chain, String authType)
 585  
             throws CertificateException {
 586  0
         if ((this.mode & SERVER) != 0) {
 587  0
             if (null == chain || chain.length == 0)
 588  0
                 throw new IllegalArgumentException(
 589  
                         "Certificate chain is null or empty");
 590  
 
 591  
             int i;
 592  0
             TrustManager[] mgrs = this.tmf.getTrustManagers();
 593  0
             for (i = 0; i < mgrs.length; i++) {
 594  0
                 if (mgrs[i] instanceof X509TrustManager) {
 595  0
                     X509TrustManager m = (X509TrustManager) (mgrs[i]);
 596  
                     try {
 597  0
                         m.checkServerTrusted(chain, authType);
 598  0
                         return;
 599  0
                     } catch (Exception e) {
 600  
                         // try next
 601  
                     }
 602  
                 }
 603  
             }
 604  
 
 605  
             // If we get here, the certificate could not be verified.
 606  
             // Ask the user what to do.
 607  0
             CertDialog(chain[0]);
 608  
         }
 609  
         // In dummy mode: Nothing to do.
 610  0
     }
 611  
 
 612  
     /**
 613  
      * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
 614  
      */
 615  
     public X509Certificate[] getAcceptedIssuers() {
 616  0
         System.out.println("getAcceptedIssuers");
 617  0
         return new X509Certificate[0];
 618  
     }
 619  
 }