1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package com
.owncloud
.android
.ui
.dialog
;
20 import java
.io
.IOException
;
21 import java
.security
.KeyStoreException
;
22 import java
.security
.NoSuchAlgorithmException
;
23 import java
.security
.cert
.CertificateException
;
24 import java
.security
.cert
.X509Certificate
;
26 import android
.app
.Dialog
;
27 import android
.content
.Context
;
28 import android
.os
.Bundle
;
29 import android
.util
.Log
;
30 import android
.view
.View
;
31 import android
.view
.Window
;
32 import android
.widget
.TextView
;
34 import com
.owncloud
.android
.R
;
35 import com
.owncloud
.android
.network
.CertificateCombinedException
;
36 import com
.owncloud
.android
.network
.OwnCloudClientUtils
;
37 import com
.owncloud
.android
.operations
.RemoteOperationResult
;
40 * Dialog to request the user about a certificate that could not be validated with the certificates store in the system.
42 * @author David A. Velasco
44 public class SslValidatorDialog
extends Dialog
{
46 private final static String TAG
= SslValidatorDialog
.class.getSimpleName();
48 private OnSslValidatorListener mListener
;
49 private CertificateCombinedException mException
= null
;
54 * Creates a new SslValidatorDialog to ask the user if an untrusted certificate from a server should
57 * @param context Android context where the dialog will live.
58 * @param result Result of a failed remote operation.
59 * @param listener Object to notice when the server certificate was added to the local certificates store.
60 * @return A new SslValidatorDialog instance, or NULL if the operation can not be recovered
61 * by setting the certificate as reliable.
63 public static SslValidatorDialog
newInstance(Context context
, RemoteOperationResult result
, OnSslValidatorListener listener
) {
64 if (result
!= null
&& result
.isSslRecoverableException()) {
65 SslValidatorDialog dialog
= new SslValidatorDialog(context
, listener
);
73 * Private constructor.
75 * Instances have to be created through static {@link SslValidatorDialog#newInstance}.
77 * @param context Android context where the dialog will live
78 * @param e Exception causing the need of prompt the user about the server certificate.
79 * @param listener Object to notice when the server certificate was added to the local certificates store.
81 private SslValidatorDialog(Context context
, OnSslValidatorListener listener
) {
90 protected void onCreate(Bundle savedInstanceState
) {
91 super.onCreate(savedInstanceState
);
92 requestWindowFeature(Window
.FEATURE_NO_TITLE
);
93 mView
= getLayoutInflater().inflate(R
.layout
.ssl_validator_layout
, null
);
94 setContentView(mView
);
96 mView
.findViewById(R
.id
.ok
).setOnClickListener(
97 new View
.OnClickListener() {
99 public void onClick(View v
) {
103 if (mListener
!= null
)
104 mListener
.onSavedCertificate();
106 Log
.d(TAG
, "Nobody there to notify the certificate was saved");
108 } catch (Exception e
) {
110 if (mListener
!= null
)
111 mListener
.onFailedSavingCertificate();
112 Log
.e(TAG
, "Server certificate could not be saved in the known servers trust store ", e
);
117 mView
.findViewById(R
.id
.cancel
).setOnClickListener(
118 new View
.OnClickListener() {
120 public void onClick(View v
) {
127 public void updateResult(RemoteOperationResult result
) {
128 if (result
.isSslRecoverableException()) {
129 mException
= (CertificateCombinedException
) result
.getException();
132 ((TextView
)mView
.findViewById(R
.id
.reason_cert_not_trusted
)).setVisibility(View
.GONE
);
133 ((TextView
)mView
.findViewById(R
.id
.reason_cert_expired
)).setVisibility(View
.GONE
);
134 ((TextView
)mView
.findViewById(R
.id
.reason_cert_not_yet_valid
)).setVisibility(View
.GONE
);
135 ((TextView
)mView
.findViewById(R
.id
.reason_hostname_not_verified
)).setVisibility(View
.GONE
);
136 ((TextView
)mView
.findViewById(R
.id
.subject
)).setVisibility(View
.GONE
);
139 if (mException
.getCertPathValidatorException() != null
) {
140 ((TextView
)mView
.findViewById(R
.id
.reason_cert_not_trusted
)).setVisibility(View
.VISIBLE
);
143 if (mException
.getCertificateExpiredException() != null
) {
144 ((TextView
)mView
.findViewById(R
.id
.reason_cert_expired
)).setVisibility(View
.VISIBLE
);
147 if (mException
.getCertificateNotYetValidException() != null
) {
148 ((TextView
)mView
.findViewById(R
.id
.reason_cert_not_yet_valid
)).setVisibility(View
.VISIBLE
);
151 if (mException
.getSslPeerUnverifiedException() != null
) {
152 ((TextView
)mView
.findViewById(R
.id
.reason_hostname_not_verified
)).setVisibility(View
.VISIBLE
);
156 showCertificateData(mException
.getServerCertificate());
161 private void showCertificateData(X509Certificate cert
) {
162 TextView subject
= (TextView
)mView
.findViewById(R
.id
.subject
);
164 String text
= cert
.getSubjectDN().getName();
165 text
= text
.substring(text
.indexOf(",") + 1);
166 subject
.setVisibility(View
.VISIBLE
);
167 subject
.setText(text
);
169 // this should not happen
170 subject
.setText(R
.string
.ssl_validator_certificate_not_available
);
174 private void saveServerCert() throws KeyStoreException
, NoSuchAlgorithmException
, CertificateException
, IOException
{
175 if (mException
.getServerCertificate() != null
) {
176 OwnCloudClientUtils
.addCertToKnownServersStore(mException
.getServerCertificate(), getContext());
181 public interface OnSslValidatorListener
{
182 public void onSavedCertificate();
183 public void onFailedSavingCertificate();