View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.cms.ui.workbench.commands;
17  
18  import static org.argeo.cms.CmsMsg.changePassword;
19  import static org.argeo.cms.CmsMsg.currentPassword;
20  import static org.argeo.cms.CmsMsg.newPassword;
21  import static org.argeo.cms.CmsMsg.passwordChanged;
22  import static org.argeo.cms.CmsMsg.repeatNewPassword;
23  import static org.eclipse.jface.dialogs.IMessageProvider.INFORMATION;
24  
25  import java.security.AccessController;
26  import java.util.Arrays;
27  
28  import javax.naming.InvalidNameException;
29  import javax.naming.ldap.LdapName;
30  import javax.security.auth.Subject;
31  import javax.security.auth.x500.X500Principal;
32  import javax.transaction.UserTransaction;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.argeo.cms.CmsException;
37  import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
38  import org.argeo.node.security.CryptoKeyring;
39  import org.eclipse.core.commands.AbstractHandler;
40  import org.eclipse.core.commands.ExecutionEvent;
41  import org.eclipse.core.commands.ExecutionException;
42  import org.eclipse.jface.dialogs.Dialog;
43  import org.eclipse.jface.dialogs.MessageDialog;
44  import org.eclipse.jface.dialogs.TitleAreaDialog;
45  import org.eclipse.swt.SWT;
46  import org.eclipse.swt.graphics.Point;
47  import org.eclipse.swt.layout.GridData;
48  import org.eclipse.swt.layout.GridLayout;
49  import org.eclipse.swt.widgets.Composite;
50  import org.eclipse.swt.widgets.Control;
51  import org.eclipse.swt.widgets.Label;
52  import org.eclipse.swt.widgets.Shell;
53  import org.eclipse.swt.widgets.Text;
54  import org.eclipse.ui.handlers.HandlerUtil;
55  import org.osgi.service.useradmin.User;
56  import org.osgi.service.useradmin.UserAdmin;
57  
58  /** Open the change password dialog */
59  public class OpenChangePasswordDialog extends AbstractHandler {
60  	private final static Log log = LogFactory.getLog(OpenChangePasswordDialog.class);
61  	private UserAdmin userAdmin;
62  	private UserTransaction userTransaction;
63  	private CryptoKeyring keyring = null;
64  
65  	public Object execute(ExecutionEvent event) throws ExecutionException {
66  		ChangePasswordDialog dialog = new ChangePasswordDialog(HandlerUtil.getActiveShell(event), userAdmin);
67  		if (dialog.open() == Dialog.OK) {
68  			MessageDialog.openInformation(HandlerUtil.getActiveShell(event), passwordChanged.lead(),
69  					passwordChanged.lead());
70  		}
71  		return null;
72  	}
73  
74  	@SuppressWarnings("unchecked")
75  	protected void changePassword(char[] oldPassword, char[] newPassword) {
76  		Subject subject = Subject.getSubject(AccessController.getContext());
77  		String name = subject.getPrincipals(X500Principal.class).iterator().next().toString();
78  		LdapName dn;
79  		try {
80  			dn = new LdapName(name);
81  		} catch (InvalidNameException e) {
82  			throw new CmsException("Invalid user dn " + name, e);
83  		}
84  		User user = (User) userAdmin.getRole(dn.toString());
85  		if (!user.hasCredential(null, oldPassword))
86  			throw new CmsException("Invalid password");
87  		if (Arrays.equals(newPassword, new char[0]))
88  			throw new CmsException("New password empty");
89  		try {
90  			userTransaction.begin();
91  			user.getCredentials().put(null, newPassword);
92  			if (keyring != null) {
93  				keyring.changePassword(oldPassword, newPassword);
94  				// TODO change secret keys in the CMS session
95  			}
96  			userTransaction.commit();
97  		} catch (Exception e) {
98  			try {
99  				userTransaction.rollback();
100 			} catch (Exception e1) {
101 				log.error("Could not roll back", e1);
102 			}
103 			if (e instanceof RuntimeException)
104 				throw (RuntimeException) e;
105 			else
106 				throw new CmsException("Cannot change password", e);
107 		}
108 	}
109 
110 	class ChangePasswordDialog extends TitleAreaDialog {
111 		private static final long serialVersionUID = -6963970583882720962L;
112 		private Text oldPassword, newPassword1, newPassword2;
113 
114 		public ChangePasswordDialog(Shell parentShell, UserAdmin securityService) {
115 			super(parentShell);
116 		}
117 
118 		protected Point getInitialSize() {
119 			return new Point(400, 450);
120 		}
121 
122 		protected Control createDialogArea(Composite parent) {
123 			Composite dialogarea = (Composite) super.createDialogArea(parent);
124 			dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
125 			Composite composite = new Composite(dialogarea, SWT.NONE);
126 			composite.setLayout(new GridLayout(2, false));
127 			composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
128 			oldPassword = createLP(composite, currentPassword.lead());
129 			newPassword1 = createLP(composite, newPassword.lead());
130 			newPassword2 = createLP(composite, repeatNewPassword.lead());
131 
132 			setMessage(changePassword.lead(), INFORMATION);
133 			parent.pack();
134 			oldPassword.setFocus();
135 			return composite;
136 		}
137 
138 		@Override
139 		protected void okPressed() {
140 			try {
141 				if (!newPassword1.getText().equals(newPassword2.getText()))
142 					throw new CmsException("New passwords are different");
143 				changePassword(oldPassword.getTextChars(), newPassword1.getTextChars());
144 				close();
145 			} catch (Exception e) {
146 				ErrorFeedback.show("Cannot change password", e);
147 			}
148 		}
149 
150 		/** Creates label and password. */
151 		protected Text createLP(Composite parent, String label) {
152 			new Label(parent, SWT.NONE).setText(label);
153 			Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.PASSWORD | SWT.BORDER);
154 			text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
155 			return text;
156 		}
157 
158 		protected void configureShell(Shell shell) {
159 			super.configureShell(shell);
160 			shell.setText(changePassword.lead());
161 		}
162 	}
163 
164 	public void setUserAdmin(UserAdmin userAdmin) {
165 		this.userAdmin = userAdmin;
166 	}
167 
168 	public void setUserTransaction(UserTransaction userTransaction) {
169 		this.userTransaction = userTransaction;
170 	}
171 
172 	public void setKeyring(CryptoKeyring keyring) {
173 		this.keyring = keyring;
174 	}
175 
176 }