1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package cz.hobrasoft.pdfmu.operation.signature;
18
19 import static cz.hobrasoft.pdfmu.error.ErrorType.SIGNATURE_ADD_KEYSTORE_FILE_CLOSE;
20 import static cz.hobrasoft.pdfmu.error.ErrorType.SIGNATURE_ADD_KEYSTORE_FILE_NOT_SPECIFIED;
21 import static cz.hobrasoft.pdfmu.error.ErrorType.SIGNATURE_ADD_KEYSTORE_FILE_OPEN;
22 import static cz.hobrasoft.pdfmu.error.ErrorType.SIGNATURE_ADD_KEYSTORE_LOAD;
23 import static cz.hobrasoft.pdfmu.error.ErrorType.SIGNATURE_ADD_KEYSTORE_TYPE_UNSUPPORTED;
24 import cz.hobrasoft.pdfmu.operation.OperationException;
25 import cz.hobrasoft.pdfmu.operation.args.ArgsConfiguration;
26 import cz.hobrasoft.pdfmu.operation.args.PasswordArgs;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.FileNotFoundException;
30 import java.io.IOException;
31 import java.security.KeyStore;
32 import java.security.KeyStoreException;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.cert.CertificateException;
35 import java.util.AbstractMap.SimpleEntry;
36 import java.util.logging.Logger;
37 import net.sourceforge.argparse4j.impl.Arguments;
38 import net.sourceforge.argparse4j.inf.Argument;
39 import net.sourceforge.argparse4j.inf.ArgumentParser;
40 import net.sourceforge.argparse4j.inf.Namespace;
41
42
43
44
45
46 class KeystoreParameters implements ArgsConfiguration {
47
48 public File file = null;
49 public String type = null;
50
51
52 private static final Logger logger = Logger.getLogger(KeystoreParameters.class.getName());
53
54 public KeystoreParameters(String title) {
55 passwordArgs = new PasswordArgs(String.format("%s password", title));
56 }
57
58 public Argument typeArgument;
59 public Argument fileArgument;
60 public PasswordArgs passwordArgs;
61
62 @Deprecated
63 @Override
64 public void addArguments(ArgumentParser parser) {
65 finalizeArguments();
66 }
67
68 public void finalizeArguments() {
69 assert typeArgument != null;
70 typeArgument.type(String.class);
71
72 assert fileArgument != null;
73 fileArgument.type(Arguments.fileType());
74
75 assert passwordArgs != null;
76 passwordArgs.finalizeArguments();
77 }
78
79 @Override
80 public void setFromNamespace(Namespace namespace) {
81 file = namespace.get(fileArgument.getDest());
82 type = namespace.getString(typeArgument.getDest());
83
84 passwordArgs.setFromNamespace(namespace);
85 }
86
87 private String getNonnullType() {
88 if (type == null) {
89
90 logger.info("Keystore type not specified. Using the default type.");
91 return KeyStore.getDefaultType();
92 }
93 return type;
94 }
95
96 public String getPassword() {
97 return passwordArgs.getPassword();
98 }
99
100 private String getNonnullPassword() {
101 String password = getPassword();
102 if (password == null) {
103 logger.info("Keystore password not set. Using empty password.");
104 return "";
105 }
106 return password;
107 }
108
109 public KeyStore loadKeystore() throws OperationException {
110 String type = getNonnullType();
111 logger.info(String.format("Keystore type: %s", type));
112
113
114 KeyStore ks;
115 try {
116 ks = KeyStore.getInstance(type);
117 } catch (KeyStoreException ex) {
118 throw new OperationException(SIGNATURE_ADD_KEYSTORE_TYPE_UNSUPPORTED, ex,
119 new SimpleEntry<String, Object>("type", type));
120 }
121 logger.info(String.format("Keystore security provider: %s", ks.getProvider().getName()));
122 switch (type) {
123 case "Windows-MY":
124 loadWindowsKeystore(ks);
125 break;
126 default:
127 loadFileKeystore(ks, type);
128 }
129 return ks;
130 }
131
132 private void loadFileKeystore(KeyStore ks, String type) throws OperationException {
133 if (file == null) {
134 throw new OperationException(SIGNATURE_ADD_KEYSTORE_FILE_NOT_SPECIFIED,
135 new SimpleEntry<String, Object>("type", type));
136 }
137 logger.info(String.format("Keystore file: %s", file));
138
139 FileInputStream ksIs;
140 try {
141 ksIs = new FileInputStream(file);
142 } catch (FileNotFoundException ex) {
143 throw new OperationException(SIGNATURE_ADD_KEYSTORE_FILE_OPEN, ex,
144 new SimpleEntry<String, Object>("file", file));
145 }
146 char[] password = getNonnullPassword().toCharArray();
147 try {
148 ks.load(ksIs, password);
149 } catch (IOException ex) {
150
151 throw new OperationException(SIGNATURE_ADD_KEYSTORE_LOAD, ex,
152 new SimpleEntry<String, Object>("type", type),
153 new SimpleEntry<String, Object>("file", file));
154 } catch (NoSuchAlgorithmException | CertificateException ex) {
155 throw new OperationException(SIGNATURE_ADD_KEYSTORE_LOAD, ex,
156 new SimpleEntry<String, Object>("type", type),
157 new SimpleEntry<String, Object>("file", file));
158 } finally {
159 try {
160 ksIs.close();
161 } catch (IOException ex) {
162 throw new OperationException(SIGNATURE_ADD_KEYSTORE_FILE_CLOSE, ex,
163 new SimpleEntry<String, Object>("file", file));
164 }
165 }
166 }
167
168 private void loadWindowsKeystore(KeyStore ks) throws OperationException {
169 assert "Windows-MY".equals(type);
170 try {
171 ks.load(null, null);
172 } catch (IOException | NoSuchAlgorithmException | CertificateException ex) {
173 throw new OperationException(SIGNATURE_ADD_KEYSTORE_LOAD, ex,
174 new SimpleEntry<String, Object>("type", type));
175 }
176 }
177
178 public void setSystemProperties(SslKeystore sslKeystore) throws OperationException {
179 sslKeystore.setSystemProperties(file, type, getPassword());
180 }
181 }