2 * ownCloud Android client application
5 * @author David A. Velasco
6 * Copyright (C) 2015 ownCloud Inc.
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 package com
.owncloud
.android
.ui
.adapter
;
23 import java
.security
.MessageDigest
;
24 import java
.security
.NoSuchAlgorithmException
;
25 import java
.security
.cert
.CertificateEncodingException
;
26 import java
.security
.cert
.X509Certificate
;
27 import java
.text
.DateFormat
;
28 import java
.util
.Date
;
29 import java
.util
.HashMap
;
32 import javax
.security
.auth
.x500
.X500Principal
;
34 import com
.owncloud
.android
.R
;
35 import com
.owncloud
.android
.ui
.dialog
.SslUntrustedCertDialog
;
37 import android
.util
.Log
;
38 import android
.view
.View
;
39 import android
.widget
.TextView
;
44 public class X509CertificateViewAdapter
implements SslUntrustedCertDialog
.CertificateViewAdapter
{
46 //private final static String TAG = X509CertificateViewAdapter.class.getSimpleName();
48 private X509Certificate mCertificate
= null
;
50 private static final String TAG
= X509CertificateViewAdapter
.class.getSimpleName();
52 public X509CertificateViewAdapter(X509Certificate certificate
) {
53 mCertificate
= certificate
;
57 public void updateCertificateView(View dialogView
) {
58 TextView nullCerView
= (TextView
) dialogView
.findViewById(R
.id
.null_cert
);
60 if (mCertificate
!= null
) {
61 nullCerView
.setVisibility(View
.GONE
);
62 showSubject(mCertificate
.getSubjectX500Principal(), dialogView
);
63 showIssuer(mCertificate
.getIssuerX500Principal(), dialogView
);
64 showValidity(mCertificate
.getNotBefore(), mCertificate
.getNotAfter(), dialogView
);
65 showSignature(dialogView
);
68 nullCerView
.setVisibility(View
.VISIBLE
);
72 private byte[] getDigest(String algorithm
, byte[] message
) {
73 MessageDigest md
= null
;
76 md
= MessageDigest
.getInstance(algorithm
);
77 } catch (NoSuchAlgorithmException e
) {
81 return md
.digest(message
);
84 private void showSignature(View dialogView
) {
87 TextView certFingerprintView
= ((TextView
) dialogView
.findViewById(R
.id
.value_certificate_fingerprint
));
88 TextView algorithmView
= ((TextView
) dialogView
.findViewById(R
.id
.value_signature_algorithm
));
91 cert
= mCertificate
.getEncoded();
94 certFingerprintView
.setText(R
.string
.certificate_load_problem
);
95 algorithmView
.setText(R
.string
.certificate_load_problem
);
99 certFingerprintView
.setText(
100 getDigestHexBytesWithColonsAndNewLines(dialogView
, "SHA-256", cert
)
101 + getDigestHexBytesWithColonsAndNewLines(dialogView
, "SHA-1", cert
)
102 + getDigestHexBytesWithColonsAndNewLines(dialogView
, "MD5", cert
));
103 algorithmView
.setText(mCertificate
.getSigAlgName());
107 } catch (CertificateEncodingException e
) {
108 Log
.e(TAG
, "Problem while trying to decode the certificate.");
114 private final String
getDigestHexBytesWithColonsAndNewLines(View dialogView
, final String digestType
, final byte [] cert
) {
115 final byte[] rawDigest
;
116 final String newLine
= System
.getProperty("line.separator");
118 rawDigest
= getDigest(digestType
, cert
);
120 if ( rawDigest
== null
) {
121 return digestType
+ ":" + newLine
+ dialogView
.getContext().getString(R
.string
.digest_algorithm_not_available
) + newLine
+ newLine
;
124 final StringBuilder hex
= new StringBuilder(3 * rawDigest
.length
);
126 for (final byte b
: rawDigest
) {
127 final int hiVal
= (b
& 0xF0) >> 4;
128 final int loVal
= b
& 0x0F;
129 hex
.append((char) ('0' + (hiVal
+ (hiVal
/ 10 * 7))));
130 hex
.append((char) ('0' + (loVal
+ (loVal
/ 10 * 7))));
133 return digestType
+ ":" + newLine
+ hex
.toString().replaceFirst("\\:$","") + newLine
+ newLine
;
136 private void showValidity(Date notBefore
, Date notAfter
, View dialogView
) {
137 TextView fromView
= ((TextView
)dialogView
.findViewById(R
.id
.value_validity_from
));
138 TextView toView
= ((TextView
)dialogView
.findViewById(R
.id
.value_validity_to
));
139 DateFormat dateFormat
= DateFormat
.getDateInstance();
140 fromView
.setText(dateFormat
.format(notBefore
));
141 toView
.setText(dateFormat
.format(notAfter
));
144 private void showSubject(X500Principal subject
, View dialogView
) {
145 Map
<String
, String
> s
= parsePrincipal(subject
);
146 TextView cnView
= ((TextView
)dialogView
.findViewById(R
.id
.value_subject_CN
));
147 TextView oView
= ((TextView
)dialogView
.findViewById(R
.id
.value_subject_O
));
148 TextView ouView
= ((TextView
)dialogView
.findViewById(R
.id
.value_subject_OU
));
149 TextView cView
= ((TextView
)dialogView
.findViewById(R
.id
.value_subject_C
));
150 TextView stView
= ((TextView
)dialogView
.findViewById(R
.id
.value_subject_ST
));
151 TextView lView
= ((TextView
)dialogView
.findViewById(R
.id
.value_subject_L
));
153 if (s
.get("CN") != null
) {
154 cnView
.setText(s
.get("CN"));
155 cnView
.setVisibility(View
.VISIBLE
);
157 cnView
.setVisibility(View
.GONE
);
159 if (s
.get("O") != null
) {
160 oView
.setText(s
.get("O"));
161 oView
.setVisibility(View
.VISIBLE
);
163 oView
.setVisibility(View
.GONE
);
165 if (s
.get("OU") != null
) {
166 ouView
.setText(s
.get("OU"));
167 ouView
.setVisibility(View
.VISIBLE
);
169 ouView
.setVisibility(View
.GONE
);
171 if (s
.get("C") != null
) {
172 cView
.setText(s
.get("C"));
173 cView
.setVisibility(View
.VISIBLE
);
175 cView
.setVisibility(View
.GONE
);
177 if (s
.get("ST") != null
) {
178 stView
.setText(s
.get("ST"));
179 stView
.setVisibility(View
.VISIBLE
);
181 stView
.setVisibility(View
.GONE
);
183 if (s
.get("L") != null
) {
184 lView
.setText(s
.get("L"));
185 lView
.setVisibility(View
.VISIBLE
);
187 lView
.setVisibility(View
.GONE
);
191 private void showIssuer(X500Principal issuer
, View dialogView
) {
192 Map
<String
, String
> s
= parsePrincipal(issuer
);
193 TextView cnView
= ((TextView
)dialogView
.findViewById(R
.id
.value_issuer_CN
));
194 TextView oView
= ((TextView
)dialogView
.findViewById(R
.id
.value_issuer_O
));
195 TextView ouView
= ((TextView
)dialogView
.findViewById(R
.id
.value_issuer_OU
));
196 TextView cView
= ((TextView
)dialogView
.findViewById(R
.id
.value_issuer_C
));
197 TextView stView
= ((TextView
)dialogView
.findViewById(R
.id
.value_issuer_ST
));
198 TextView lView
= ((TextView
)dialogView
.findViewById(R
.id
.value_issuer_L
));
200 if (s
.get("CN") != null
) {
201 cnView
.setText(s
.get("CN"));
202 cnView
.setVisibility(View
.VISIBLE
);
204 cnView
.setVisibility(View
.GONE
);
206 if (s
.get("O") != null
) {
207 oView
.setText(s
.get("O"));
208 oView
.setVisibility(View
.VISIBLE
);
210 oView
.setVisibility(View
.GONE
);
212 if (s
.get("OU") != null
) {
213 ouView
.setText(s
.get("OU"));
214 ouView
.setVisibility(View
.VISIBLE
);
216 ouView
.setVisibility(View
.GONE
);
218 if (s
.get("C") != null
) {
219 cView
.setText(s
.get("C"));
220 cView
.setVisibility(View
.VISIBLE
);
222 cView
.setVisibility(View
.GONE
);
224 if (s
.get("ST") != null
) {
225 stView
.setText(s
.get("ST"));
226 stView
.setVisibility(View
.VISIBLE
);
228 stView
.setVisibility(View
.GONE
);
230 if (s
.get("L") != null
) {
231 lView
.setText(s
.get("L"));
232 lView
.setVisibility(View
.VISIBLE
);
234 lView
.setVisibility(View
.GONE
);
239 private Map
<String
, String
> parsePrincipal(X500Principal principal
) {
240 Map
<String
, String
> result
= new HashMap
<String
, String
>();
241 String toParse
= principal
.getName();
242 String
[] pieces
= toParse
.split(",");
243 String
[] tokens
= {"CN", "O", "OU", "C", "ST", "L"};
244 for (int i
=0; i
< pieces
.length
; i
++) {
245 for (int j
=0; j
<tokens
.length
; j
++) {
246 if (pieces
[i
].startsWith(tokens
[j
] + "=")) {
247 result
.put(tokens
[j
], pieces
[i
].substring(tokens
[j
].length()+1));