2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 package org
.strongswan
.android
.ui
;
20 import java
.security
.cert
.X509Certificate
;
22 import org
.strongswan
.android
.R
;
23 import org
.strongswan
.android
.data
.TrustedCertificateEntry
;
24 import org
.strongswan
.android
.data
.VpnProfile
;
25 import org
.strongswan
.android
.data
.VpnProfileDataSource
;
26 import org
.strongswan
.android
.data
.VpnType
;
27 import org
.strongswan
.android
.logic
.TrustedCertificateManager
;
29 import android
.app
.Activity
;
30 import android
.app
.AlertDialog
;
31 import android
.content
.DialogInterface
;
32 import android
.content
.Intent
;
33 import android
.os
.Bundle
;
34 import android
.util
.Log
;
35 import android
.view
.Menu
;
36 import android
.view
.MenuInflater
;
37 import android
.view
.MenuItem
;
38 import android
.view
.View
;
39 import android
.view
.View
.OnClickListener
;
40 import android
.view
.ViewGroup
;
41 import android
.widget
.AdapterView
;
42 import android
.widget
.AdapterView
.OnItemSelectedListener
;
43 import android
.widget
.CheckBox
;
44 import android
.widget
.CompoundButton
;
45 import android
.widget
.CompoundButton
.OnCheckedChangeListener
;
46 import android
.widget
.EditText
;
47 import android
.widget
.RelativeLayout
;
48 import android
.widget
.Spinner
;
49 import android
.widget
.TextView
;
51 public class VpnProfileDetailActivity
extends Activity
53 private static final int SELECT_TRUSTED_CERTIFICATE
= 0;
55 private VpnProfileDataSource mDataSource
;
57 private TrustedCertificateEntry mCertEntry
;
58 private VpnType mVpnType
= VpnType
.IKEV2_EAP
;
59 private VpnProfile mProfile
;
60 private EditText mName
;
61 private EditText mGateway
;
62 private Spinner mSelectVpnType
;
63 private ViewGroup mUsernamePassword
;
64 private EditText mUsername
;
65 private EditText mPassword
;
66 private CheckBox mCheckAuto
;
67 private RelativeLayout mSelectCert
;
68 private TextView mCertTitle
;
69 private TextView mCertSubtitle
;
72 public void onCreate(Bundle savedInstanceState
)
74 super.onCreate(savedInstanceState
);
76 /* the title is set when we load the profile, if any */
77 getActionBar().setDisplayHomeAsUpEnabled(true
);
79 mDataSource
= new VpnProfileDataSource(this);
82 setContentView(R
.layout
.profile_detail_view
);
84 mName
= (EditText
)findViewById(R
.id
.name
);
85 mGateway
= (EditText
)findViewById(R
.id
.gateway
);
86 mSelectVpnType
= (Spinner
)findViewById(R
.id
.vpn_type
);
88 mUsernamePassword
= (ViewGroup
)findViewById(R
.id
.username_password_group
);
89 mUsername
= (EditText
)findViewById(R
.id
.username
);
90 mPassword
= (EditText
)findViewById(R
.id
.password
);
92 mCheckAuto
= (CheckBox
)findViewById(R
.id
.ca_auto
);
93 mSelectCert
= (RelativeLayout
)findViewById(R
.id
.select_certificate
);
94 mCertTitle
= (TextView
)findViewById(R
.id
.select_certificate_title
);
95 mCertSubtitle
= (TextView
)findViewById(R
.id
.select_certificate_subtitle
);
98 mSelectVpnType
.setOnItemSelectedListener(new OnItemSelectedListener() {
100 public void onItemSelected(AdapterView
<?
> parent
, View view
, int position
, long id
)
102 mVpnType
= VpnType
.values()[position
];
103 updateClientCredentialView();
107 public void onNothingSelected(AdapterView
<?
> parent
)
108 { /* should not happen */
109 mVpnType
= VpnType
.IKEV2_EAP
;
110 updateClientCredentialView();
114 mCheckAuto
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
116 public void onCheckedChanged(CompoundButton buttonView
, boolean isChecked
)
118 updateCertificateSelector();
122 mSelectCert
.setOnClickListener(new OnClickListener() {
124 public void onClick(View v
)
126 Intent intent
= new Intent(VpnProfileDetailActivity
.this, TrustedCertificatesActivity
.class);
127 startActivityForResult(intent
, SELECT_TRUSTED_CERTIFICATE
);
131 mId
= savedInstanceState
== null ? null
: savedInstanceState
.getLong(VpnProfileDataSource
.KEY_ID
);
134 Bundle extras
= getIntent().getExtras();
135 mId
= extras
== null ? null
: extras
.getLong(VpnProfileDataSource
.KEY_ID
);
138 loadProfileData(savedInstanceState
);
140 updateClientCredentialView();
141 updateCertificateSelector();
145 protected void onDestroy()
152 protected void onSaveInstanceState(Bundle outState
)
154 super.onSaveInstanceState(outState
);
157 outState
.putLong(VpnProfileDataSource
.KEY_ID
, mId
);
159 if (mCertEntry
!= null
)
161 outState
.putString(VpnProfileDataSource
.KEY_CERTIFICATE
, mCertEntry
.getAlias());
166 public boolean onCreateOptionsMenu(Menu menu
)
168 MenuInflater inflater
= getMenuInflater();
169 inflater
.inflate(R
.menu
.profile_edit
, menu
);
174 public boolean onOptionsItemSelected(MenuItem item
)
176 switch (item
.getItemId())
178 case android
.R
.id
.home
:
179 case R
.id
.menu_cancel
:
182 case R
.id
.menu_accept
:
186 return super.onOptionsItemSelected(item
);
191 protected void onActivityResult(int requestCode
, int resultCode
, Intent data
)
195 case SELECT_TRUSTED_CERTIFICATE
:
196 if (resultCode
== RESULT_OK
)
198 String alias
= data
.getStringExtra(VpnProfileDataSource
.KEY_CERTIFICATE
);
199 X509Certificate certificate
= TrustedCertificateManager
.getInstance().getCACertificateFromAlias(alias
);
200 mCertEntry
= certificate
== null ? null
: new TrustedCertificateEntry(alias
, certificate
);
201 updateCertificateSelector();
205 super.onActivityResult(requestCode
, resultCode
, data
);
210 * Update the UI to enter client credentials depending on the type of VPN currently selected
212 private void updateClientCredentialView()
214 mUsernamePassword
.setVisibility(mVpnType
.getRequiresUsernamePassword() ? View
.VISIBLE
: View
.GONE
);
218 * Show an alert in case the previously selected certificate is not found anymore
219 * or the user did not select a certificate in the spinner.
221 private void showCertificateAlert()
223 AlertDialog
.Builder adb
= new AlertDialog
.Builder(VpnProfileDetailActivity
.this);
224 adb
.setTitle(R
.string
.alert_text_nocertfound_title
);
225 adb
.setMessage(R
.string
.alert_text_nocertfound
);
226 adb
.setPositiveButton(android
.R
.string
.ok
, new DialogInterface
.OnClickListener() {
228 public void onClick(DialogInterface dialog
, int id
)
237 * Update the CA certificate selection UI depending on whether the
238 * certificate should be automatically selected or not.
240 private void updateCertificateSelector()
242 if (!mCheckAuto
.isChecked())
244 mSelectCert
.setEnabled(true
);
245 mSelectCert
.setVisibility(View
.VISIBLE
);
247 if (mCertEntry
!= null
)
249 mCertTitle
.setText(mCertEntry
.getSubjectPrimary());
250 mCertSubtitle
.setText(mCertEntry
.getSubjectSecondary());
254 mCertTitle
.setText(R
.string
.profile_ca_select_certificate_label
);
255 mCertSubtitle
.setText(R
.string
.profile_ca_select_certificate
);
260 mSelectCert
.setEnabled(false
);
261 mSelectCert
.setVisibility(View
.GONE
);
266 * Save or update the profile depending on whether we actually have a
267 * profile object or not (this was created in updateProfileData)
269 private void saveProfile()
273 if (mProfile
!= null
)
276 mDataSource
.updateVpnProfile(mProfile
);
280 mProfile
= new VpnProfile();
282 mDataSource
.insertProfile(mProfile
);
284 setResult(RESULT_OK
, new Intent().putExtra(VpnProfileDataSource
.KEY_ID
, mProfile
.getId()));
290 * Verify the user input and display error messages.
291 * @return true if the input is valid
293 private boolean verifyInput()
295 boolean valid
= true
;
296 if (mGateway
.getText().toString().trim().isEmpty())
298 mGateway
.setError(getString(R
.string
.alert_text_no_input_gateway
));
301 if (mVpnType
.getRequiresUsernamePassword())
303 if (mUsername
.getText().toString().trim().isEmpty())
305 mUsername
.setError(getString(R
.string
.alert_text_no_input_username
));
309 if (!mCheckAuto
.isChecked() && mCertEntry
== null
)
311 showCertificateAlert();
318 * Update the profile object with the data entered by the user
320 private void updateProfileData()
322 /* the name is optional, we default to the gateway if none is given */
323 String name
= mName
.getText().toString().trim();
324 String gateway
= mGateway
.getText().toString().trim();
325 mProfile
.setName(name
.isEmpty() ? gateway
: name
);
326 mProfile
.setGateway(gateway
);
327 mProfile
.setVpnType(mVpnType
);
328 if (mVpnType
.getRequiresUsernamePassword())
330 mProfile
.setUsername(mUsername
.getText().toString().trim());
331 String password
= mPassword
.getText().toString().trim();
332 password
= password
.isEmpty() ? null
: password
;
333 mProfile
.setPassword(password
);
335 String certAlias
= mCheckAuto
.isChecked() ? null
: mCertEntry
.getAlias();
336 mProfile
.setCertificateAlias(certAlias
);
340 * Load an existing profile if we got an ID
342 * @param savedInstanceState previously saved state
344 private void loadProfileData(Bundle savedInstanceState
)
348 getActionBar().setTitle(R
.string
.add_profile
);
351 mProfile
= mDataSource
.getVpnProfile(mId
);
352 if (mProfile
!= null
)
354 mName
.setText(mProfile
.getName());
355 mGateway
.setText(mProfile
.getGateway());
356 mVpnType
= mProfile
.getVpnType();
357 mUsername
.setText(mProfile
.getUsername());
358 mPassword
.setText(mProfile
.getPassword());
359 alias
= mProfile
.getCertificateAlias();
360 getActionBar().setTitle(mProfile
.getName());
364 Log
.e(VpnProfileDetailActivity
.class.getSimpleName(),
365 "VPN profile with id " + mId
+ " not found");
370 mSelectVpnType
.setSelection(mVpnType
.ordinal());
372 /* check if the user selected a certificate previously */
373 alias
= savedInstanceState
== null ? alias
: savedInstanceState
.getString(VpnProfileDataSource
.KEY_CERTIFICATE
);
374 mCheckAuto
.setChecked(alias
== null
);
377 X509Certificate certificate
= TrustedCertificateManager
.getInstance().getCACertificateFromAlias(alias
);
378 if (certificate
!= null
)
380 mCertEntry
= new TrustedCertificateEntry(alias
, certificate
);
383 { /* previously selected certificate is not here anymore */
384 showCertificateAlert();