22
33import com .acuity .iot .dsa .dslink .sys .cert .HostnameWhitelist .WhitelistValue ;
44import java .io .File ;
5+ import java .io .FileOutputStream ;
56import java .io .IOException ;
7+ import java .io .InputStream ;
68import java .security .cert .CertificateEncodingException ;
79import java .security .cert .X509Certificate ;
810import javax .net .ssl .HostnameVerifier ;
@@ -50,6 +52,7 @@ public class SysCertService extends DSNode {
5052 private static final String GENERATE_SELF_SIGNED = "Generate Self-Signed Certificate" ;
5153 private static final String DELETE_KS_ENTRY = "Delete Keystore Entry" ;
5254 private static final String GET_KS_ENTRY = "Get Keystore Entry" ;
55+ private static final String DEFAULT_CERTFILE = "dslink.jks" ;
5356
5457 // Fields
5558 // ------
@@ -60,6 +63,12 @@ public class SysCertService extends DSNode {
6063 private DSInfo keystorePath = getInfo (CERTFILE );
6164 private DSInfo keystorePass = getInfo (CERTFILE_PASS );
6265 private DSInfo keystoreType = getInfo (CERTFILE_TYPE );
66+ private DSInfo generateCsr = getInfo (GENERATE_CSR );
67+ private DSInfo importCaCert = getInfo (IMPORT_CA_CERT );
68+ private DSInfo importPrimaryCert = getInfo (IMPORT_PRIMARY_CERT );
69+ private DSInfo generateSSCert = getInfo (GENERATE_SELF_SIGNED );
70+ private DSInfo getKSEntry = getInfo (GET_KS_ENTRY );
71+ private DSInfo deleteKSEntry = getInfo (DELETE_KS_ENTRY );
6372 private CertCollection localTruststore ;
6473 private CertCollection quarantine ;
6574 private HostnameWhitelist whitelist ;
@@ -128,7 +137,7 @@ public void declareDefaults() {
128137 declareDefault (ALLOW_SERVERS , DSBool .TRUE );
129138 declareDefault (VERIFY_HOSTNAMES , DSBool .TRUE );
130139 declareDefault (HOSTNAME_WHITELIST , new HostnameWhitelist ());
131- declareDefault (CERTFILE , DSString .valueOf ("dslink.jks" ));
140+ declareDefault (CERTFILE , DSString .valueOf (DEFAULT_CERTFILE ));
132141 declareDefault (CERTFILE_TYPE , DSString .valueOf ("JKS" ));
133142 declareDefault (CERTFILE_PASS , DSPasswordAes128 .valueOf ("dsarocks" ));
134143 declareDefault (LOCAL_TRUSTSTORE , new CertCollection ());
@@ -153,17 +162,23 @@ public void prepareParameter(DSInfo info, DSMap parameter) {
153162
154163 @ Override
155164 public ActionResult invoke (DSInfo info , ActionInvocation invocation ) {
156- String csr = ((SysCertService ) info .getParent ()).generateCSR ();
157- return csr != null ? new DSActionValues (info .getAction ())
158- .addResult (DSString .valueOf (csr )) : null ;
165+ String [] results = ((SysCertService ) info .getParent ()).generateCSR ();
166+ if (results != null && results .length > 1 ) {
167+ return new DSActionValues (info .getAction ())
168+ .addResult (DSString .valueOf (results [0 ]))
169+ .addResult (DSString .valueOf (results [1 ]));
170+ } else {
171+ return null ;
172+ }
159173 }
160174 };
161175 act .setResultType (ResultType .VALUES );
176+ act .addValueResult ("Result" , DSValueType .STRING );
162177 act .addValueResult ("CSR" , DSValueType .STRING ).setEditor ("textarea" );
163178 return act ;
164179 }
165180
166- private String generateCSR () {
181+ private String [] generateCSR () {
167182 try {
168183 return KeyToolUtil .generateCSR (getKeystorePath (), getCertFilePass ());
169184 } catch (IOException e ) {
@@ -182,22 +197,25 @@ public void prepareParameter(DSInfo info, DSMap parameter) {
182197 @ Override
183198 public ActionResult invoke (DSInfo info , ActionInvocation invocation ) {
184199 DSMap parameters = invocation .getParameters ();
185- ((SysCertService ) info .getParent ()).importCACert (parameters );
186- return null ;
200+ String result = ((SysCertService ) info .getParent ()).importCACert (parameters );
201+ return new DSActionValues ( info . getAction ()). addResult ( DSString . valueOf ( result )) ;
187202 }
188203 };
189204 act .addParameter ("Alias" , DSValueType .STRING , null );
190205 act .addParameter ("Certificate" , DSValueType .STRING , null ).setEditor ("textarea" );
206+ act .setResultType (ResultType .VALUES );
207+ act .addValueResult ("Result" , DSValueType .STRING );
191208 return act ;
192209 }
193210
194- private void importCACert (DSMap parameters ) {
211+ private String importCACert (DSMap parameters ) {
195212 String alias = parameters .getString ("Alias" );
196213 String certStr = parameters .getString ("Certificate" );
197214 try {
198- KeyToolUtil .importCACert (getKeystorePath (), certStr , alias , getCertFilePass ());
215+ return KeyToolUtil .importCACert (getKeystorePath (), certStr , alias , getCertFilePass ());
199216 } catch (IOException e ) {
200217 DSException .throwRuntime (e );
218+ return null ;
201219 }
202220 }
203221
@@ -211,20 +229,23 @@ public void prepareParameter(DSInfo info, DSMap parameter) {
211229 @ Override
212230 public ActionResult invoke (DSInfo info , ActionInvocation invocation ) {
213231 DSMap parameters = invocation .getParameters ();
214- ((SysCertService ) info .getParent ()).importPrimaryCert (parameters );
215- return null ;
232+ String result = ((SysCertService ) info .getParent ()).importPrimaryCert (parameters );
233+ return new DSActionValues ( info . getAction ()). addResult ( DSString . valueOf ( result )) ;
216234 }
217235 };
218236 act .addParameter ("Certificate" , DSValueType .STRING , null ).setEditor ("textarea" );
237+ act .setResultType (ResultType .VALUES );
238+ act .addValueResult ("Result" , DSValueType .STRING );
219239 return act ;
220240 }
221241
222- private void importPrimaryCert (DSMap parameters ) {
242+ private String importPrimaryCert (DSMap parameters ) {
223243 String certStr = parameters .getString ("Certificate" );
224244 try {
225- KeyToolUtil .importPrimaryCert (getKeystorePath (), certStr , getCertFilePass ());
245+ return KeyToolUtil .importPrimaryCert (getKeystorePath (), certStr , getCertFilePass ());
226246 } catch (IOException e ) {
227247 DSException .throwRuntime (e );
248+ return null ;
228249 }
229250 }
230251
@@ -237,10 +258,12 @@ public void prepareParameter(DSInfo info, DSMap parameter) {
237258
238259 @ Override
239260 public ActionResult invoke (DSInfo info , ActionInvocation invocation ) {
240- ((SysCertService ) info .getParent ()).keytoolGenkey ();
241- return null ;
261+ String result = ((SysCertService ) info .getParent ()).keytoolGenkey ();
262+ return new DSActionValues ( info . getAction ()). addResult ( DSString . valueOf ( result )) ;
242263 }
243264 };
265+ act .setResultType (ResultType .VALUES );
266+ act .addValueResult ("Result" , DSValueType .STRING );
244267 return act ;
245268 }
246269
@@ -275,15 +298,17 @@ public void prepareParameter(DSInfo info, DSMap parameter) {
275298
276299 @ Override
277300 public ActionResult invoke (DSInfo info , ActionInvocation invocation ) {
278- ((SysCertService ) info .getParent ()).deleteKSEntry ();
279- return null ;
301+ String result = ((SysCertService ) info .getParent ()).deleteKSEntry ();
302+ return new DSActionValues ( info . getAction ()). addResult ( DSString . valueOf ( result )) ;
280303 }
281304 };
305+ act .setResultType (ResultType .VALUES );
306+ act .addValueResult ("Result" , DSValueType .STRING );
282307 return act ;
283308 }
284309
285- private void deleteKSEntry () {
286- KeyToolUtil .deleteEntry (getKeystorePath (), getCertFilePass ());
310+ private String deleteKSEntry () {
311+ return KeyToolUtil .deleteEntry (getKeystorePath (), getCertFilePass ());
287312 }
288313
289314 private String getCertFilePass () {
@@ -298,19 +323,66 @@ private String getKeystorePath() {
298323 /**
299324 * Executes the java keytool to generate a new self signed cert.
300325 */
301- private void keytoolGenkey () {
302- KeyToolUtil .generateSelfSigned (getKeystorePath (), getCertFilePass ());
326+ private String keytoolGenkey () {
327+ return KeyToolUtil .generateSelfSigned (getKeystorePath (), getCertFilePass ());
328+ }
329+
330+ private boolean isKeytoolAvailable () {
331+ String result = KeyToolUtil .help ();
332+ return result != null && !result .isEmpty ();
303333 }
304334
305335 @ Override
306336 public void onStarted () {
307337 inst = this ;
308338 AnonymousTrustFactory .init (this );
309- String keystore = this . keystorePath . getElement (). toString ();
339+ String keystore = getKeystorePath ();
310340 File f = new File (keystore );
311- if (!f .exists ()) {
312- keytoolGenkey ();
341+ if (isKeytoolAvailable ()) {
342+ if (!f .exists ()) {
343+ keytoolGenkey ();
344+ }
345+ } else {
346+ info ("Keytool not available. Disabling keytool functionality and attempting to use existing keystore" );
347+ if (!f .exists ()) {
348+ InputStream inpStream = null ;
349+ FileOutputStream outStream = null ;
350+ try {
351+ inpStream = SysCertService .class .getResourceAsStream (DEFAULT_CERTFILE );
352+ if (inpStream != null ) {
353+ int readBytes ;
354+ byte [] buffer = new byte [4096 ];
355+ outStream = new FileOutputStream (f );
356+ while ((readBytes = inpStream .read (buffer )) > 0 ) {
357+ outStream .write (buffer , 0 , readBytes );
358+ }
359+ }
360+ } catch (Exception e ) {
361+ debug ("" , e );
362+ } finally {
363+ try {
364+ if (inpStream != null ) {
365+ inpStream .close ();
366+ }
367+ if (outStream != null ) {
368+ outStream .close ();
369+ }
370+ } catch (Exception e ) {
371+ debug ("" , e );
372+ }
373+ }
374+ if (!f .exists ()) {
375+ error ("Existing keystore not found and new one could not be generated" );
376+ }
377+ }
378+ generateCsr .setHidden (true );
379+ importCaCert .setHidden (true );
380+ importPrimaryCert .setHidden (true );
381+ generateSSCert .setHidden (true );
382+ getKSEntry .setHidden (true );
383+ deleteKSEntry .setHidden (true );
313384 }
385+
314386 try {
315387 System .setProperty ("javax.net.ssl.keyStore" , keystore );
316388 System .setProperty ("javax.net.ssl.keyStoreType" ,
@@ -321,6 +393,18 @@ public void onStarted() {
321393 }
322394 HttpsURLConnection .setDefaultHostnameVerifier (hostnameVerifier );
323395 }
396+
397+ @ Override
398+ protected void onChildChanged (DSInfo info ) {
399+ if (info == keystorePath ) {
400+ System .setProperty ("javax.net.ssl.keyStore" , getKeystorePath ());
401+ } else if (info == keystoreType ) {
402+ System .setProperty ("javax.net.ssl.keyStoreType" ,
403+ keystoreType .getElement ().toString ());
404+ } else if (info == keystorePass ) {
405+ System .setProperty ("javax.net.ssl.keyStorePassword" , getCertFilePass ());
406+ }
407+ }
324408
325409 public boolean isInTrustStore (X509Certificate cert ) {
326410 return getLocalTruststore ().containsCertificate (cert );
0 commit comments