/* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.usermanager; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.opendaylight.controller.sal.authorization.AuthResultEnum; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.usermanager.AuthResponse; /** * Configuration Java Object which represents a Local AAA user configuration * information for User Manager. */ public class UserConfig implements Serializable { private static final long serialVersionUID = 1L; /* * Clear text password as we are moving to some MD5 digest for when saving * configurations */ protected String user; protected List roles; private String password; private static final int USERNAME_MAXLENGTH = 32; private static final int PASSWORD_MINLENGTH = 5; private static final int PASSWORD_MAXLENGTH = 256; private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern .compile("([/\\s\\.\\?#%;\\\\]+)"); public UserConfig() { } public UserConfig(String user, String password, List roles) { this.user = user; this.password = password; this.roles = (roles == null) ? new ArrayList() : new ArrayList(roles); } public String getUser() { return user; } public String getPassword() { return password; } public List getRoles() { return new ArrayList(roles); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((password == null) ? 0 : password.hashCode()); result = prime * result + ((roles == null) ? 0 : roles.hashCode()); result = prime * result + ((user == null) ? 0 : user.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; UserConfig other = (UserConfig) obj; if (password == null) { if (other.password != null) return false; } else if (!password.equals(other.password)) return false; if (roles == null) { if (other.roles != null) return false; } else if (!roles.equals(other.roles)) return false; if (user == null) { if (other.user != null) return false; } else if (!user.equals(other.user)) return false; return true; } @Override public String toString() { return "UserConfig[user=" + user + ", password=" + password + ", roles=" + roles +"]"; } public Status validate() { Status validCheck = validateRoles(); if (validCheck.isSuccess()) { validCheck = validateUsername(); } if (validCheck.isSuccess()) { validCheck = validatePassword(); } return validCheck; } protected Status validateUsername() { if (user == null || user.isEmpty()) { return new Status(StatusCode.BADREQUEST, "Username cannot be empty"); } Matcher mUser = UserConfig.INVALID_USERNAME_CHARACTERS.matcher(user); if (user.length() > UserConfig.USERNAME_MAXLENGTH || mUser.find() == true) { return new Status(StatusCode.BADREQUEST, "Username can have 1-32 non-whitespace " + "alphanumeric characters and any special " + "characters except ./#%;?\\"); } return new Status(StatusCode.SUCCESS); } private Status validatePassword() { if (password == null || password.isEmpty()) { return new Status(StatusCode.BADREQUEST, "Password cannot be empty"); } if (password.length() < UserConfig.PASSWORD_MINLENGTH || password.length() > UserConfig.PASSWORD_MAXLENGTH) { return new Status(StatusCode.BADREQUEST, "Password should have 5-256 characters"); } return new Status(StatusCode.SUCCESS); } protected Status validateRoles() { if (roles == null || roles.isEmpty()) { return new Status(StatusCode.BADREQUEST, "No role specified"); } return new Status(StatusCode.SUCCESS); } public Status update(String currentPassword, String newPassword, List newRoles) { // To make any changes to a user configured profile, current password // must always be provided if (!this.password.equals(currentPassword)) { return new Status(StatusCode.BADREQUEST, "Current password is incorrect"); } // Create a new object with the proposed modifications UserConfig proposed = new UserConfig(); proposed.user = this.user; proposed.password = (newPassword != null)? newPassword : this.password; proposed.roles = (newRoles != null)? newRoles : this.roles; // Validate it Status status = proposed.validate(); if (!status.isSuccess()) { return status; } // Accept the modifications this.user = proposed.user; this.password = proposed.password; this.roles = new ArrayList(proposed.roles); return status; } public AuthResponse authenticate(String clearTextPass) { AuthResponse locResponse = new AuthResponse(); if (password.equals(clearTextPass)) { locResponse.setStatus(AuthResultEnum.AUTH_ACCEPT_LOC); locResponse.addData(getRolesString()); } else { locResponse.setStatus(AuthResultEnum.AUTH_REJECT_LOC); } return locResponse; } protected String getRolesString() { StringBuffer buffer = new StringBuffer(); if (!roles.isEmpty()) { Iterator iter = roles.iterator(); buffer.append(iter.next()); while (iter.hasNext()) { buffer.append(" "); buffer.append(iter.next()); } } return buffer.toString(); } }