<module>../../statisticsmanager/api</module>
<module>../../statisticsmanager/implementation</module>
<module>../../statisticsmanager/integrationtest</module>
- <module>../../topologymanager</module>
+ <module>../../topologymanager/implementation</module>
<module>../../usermanager/api</module>
<module>../../usermanager/implementation</module>
<module>../../connectionmanager/api</module>
controllerKeyStorePassword=
controllerTrustStore=
controllerTrustStorePassword=
+
+# User Manager configurations
+enableStrongPasswordCheck = false
return ((to >= 0) && (to <= 0xffff));
}
+ public boolean isProtocolValid(String protocol) {
+ int protocol_number = IPProtocols.getProtocolNumberInt(protocol);
+ if (protocol_number < 1 || protocol_number > 255) {
+ return false;
+ }
+ return true;
+ }
+
private Status conflictWithContainerFlow(IContainer container) {
// Return true if it's default container
if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
}
}
+ if ((protocol != null) && !isProtocolValid(protocol)) {
+ return new Status(StatusCode.BADREQUEST, String.format("Protocol %s is not valid", protocol));
+ }
+
if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63",
tosBits));
Assert.assertEquals(nodeId, (Integer) nodeInfo.getInt("id"));
Assert.assertEquals(nodeType, nodeInfo.getString("type"));
- JSONArray propsArray = node.getJSONArray("properties");
-
- for (int j = 0; j < propsArray.length(); j++) {
- JSONObject properties = propsArray.getJSONObject(j);
- String propName = properties.getString("name");
- if (propName.equals("timeStamp")) {
- if (timestamp == null || timestampName == null) {
- Assert.assertFalse("Timestamp exist", true);
- } else {
- Assert.assertEquals(timestamp, (Integer) properties.getInt("value"));
- Assert.assertEquals(timestampName, properties.getString("timestampName"));
- }
- }
- if (propName.equals("actions")) {
- if (actionsValue == null) {
- Assert.assertFalse("Actions exist", true);
- } else {
- Assert.assertEquals(actionsValue, (Integer) properties.getInt("value"));
- }
- }
- if (propName.equals("capabilities")) {
- if (capabilitiesValue == null) {
- Assert.assertFalse("Capabilities exist", true);
- } else {
- Assert.assertEquals(capabilitiesValue, (Integer) properties.getInt("value"));
- }
- }
- if (propName.equals("tables")) {
- if (tablesValue == null) {
- Assert.assertFalse("Tables exist", true);
- } else {
- Assert.assertEquals(tablesValue, (Integer) properties.getInt("value"));
- }
- }
- if (propName.equals("buffers")) {
- if (buffersValue == null) {
- Assert.assertFalse("Buffers exist", true);
- } else {
- Assert.assertEquals(buffersValue, (Integer) properties.getInt("value"));
- }
- }
+ JSONObject properties = node.getJSONObject("properties");
+
+ if (timestamp == null || timestampName == null) {
+ Assert.assertFalse(properties.has("timeStamp"));
+ } else {
+ Assert.assertEquals(timestamp, (Integer) properties.getJSONObject("timeStamp").getInt("value"));
+ Assert.assertEquals(timestampName, properties.getJSONObject("timeStamp").getString("name"));
+ }
+ if (actionsValue == null) {
+ Assert.assertFalse(properties.has("actions"));
+ } else {
+ Assert.assertEquals(actionsValue, (Integer) properties.getJSONObject("actions").getInt("value"));
+ }
+ if (capabilitiesValue == null) {
+ Assert.assertFalse(properties.has("capabilities"));
+ } else {
+ Assert.assertEquals(capabilitiesValue,
+ (Integer) properties.getJSONObject("capabilities").getInt("value"));
+ }
+ if (tablesValue == null) {
+ Assert.assertFalse(properties.has("tables"));
+ } else {
+ Assert.assertEquals(tablesValue, (Integer) properties.getJSONObject("tables").getInt("value"));
+ }
+ if (buffersValue == null) {
+ Assert.assertFalse(properties.has("buffers"));
+ } else {
+ Assert.assertEquals(buffersValue, (Integer) properties.getJSONObject("buffers").getInt("value"));
}
}
JSONObject nodeConnector = nodeConnectorProperties.getJSONObject("nodeconnector");
JSONObject node = nodeConnector.getJSONObject("node");
+ JSONObject properties = nodeConnectorProperties.getJSONObject("properties");
Assert.assertEquals(ncId, (Integer) nodeConnector.getInt("id"));
Assert.assertEquals(ncType, nodeConnector.getString("type"));
Assert.assertEquals(nodeId, (Integer) node.getInt("id"));
Assert.assertEquals(nodeType, node.getString("type"));
-
- JSONArray propsArray = nodeConnectorProperties.getJSONArray("properties");
- for (int j = 0; j < propsArray.length(); j++) {
- JSONObject properties = propsArray.getJSONObject(j);
- String propName = properties.getString("name");
- if (propName.equals("state")) {
- if (state == null) {
- Assert.assertFalse("State exist", true);
- } else {
- Assert.assertEquals(state, (Integer) properties.getInt("value"));
- }
- }
- if (propName.equals("capabilities")) {
- if (capabilities == null) {
- Assert.assertFalse("Capabilities exist", true);
- } else {
- Assert.assertEquals(capabilities, (Integer) properties.getInt("value"));
- }
- }
- if (propName.equals("bandwidth")) {
- if (bandwidth == null) {
- Assert.assertFalse("bandwidth exist", true);
- } else {
- Assert.assertEquals(bandwidth, (Integer) properties.getInt("value"));
- }
- }
+ if (state == null) {
+ Assert.assertFalse(properties.has("state"));
+ } else {
+ Assert.assertEquals(state, (Integer) properties.getJSONObject("state").getInt("value"));
+ }
+ if (capabilities == null) {
+ Assert.assertFalse(properties.has("capabilities"));
+ } else {
+ Assert.assertEquals(capabilities,
+ (Integer) properties.getJSONObject("capabilities").getInt("value"));
+ }
+ if (bandwidth == null) {
+ Assert.assertFalse(properties.has("bandwidth"));
+ } else {
+ Assert.assertEquals(bandwidth, (Integer) properties.getJSONObject("bandwidth").getInt("value"));
}
}
json = new JSONObject(jt);
node = getJsonInstance(json, "nodeProperties", nodeId_1);
Assert.assertNotNull(node);
-
- JSONArray propsArray = node.getJSONArray("properties");
-
- for (int j = 0; j < propsArray.length(); j++) {
- JSONObject properties = propsArray.getJSONObject(j);
- String propName = properties.getString("name");
- if (propName.equals("tier")) {
- Assert.assertEquals(1001, properties.getInt("value"));
- }
- if (propName.equals("description")) {
- Assert.assertEquals("node1", properties.getString("value"));
- }
- }
+ Assert.assertEquals(1001, node.getJSONObject("properties").getJSONObject("tier").getInt("value"));
+ Assert.assertEquals("node1", node.getJSONObject("properties").getJSONObject("description").getString("value"));
// Test delete nodeConnector property
// Delete state property of nodeconnector1
JSONObject headNC = edge.getJSONObject("headNodeConnector");
JSONObject headNode = headNC.getJSONObject("node");
-
- JSONArray propsArray = edgeProp.getJSONArray("properties");
-
- JSONObject bandw = null;
- JSONObject stt = null;
- JSONObject ltc = null;
-
- for (int j = 0; j < propsArray.length(); j++) {
- JSONObject props = propsArray.getJSONObject(j);
- String propName = props.getString("name");
- if (propName.equals("bandwidth")) {
- bandw = props;
- }
- if (propName.equals("state")) {
- stt = props;
- }
- if (propName.equals("latency")) {
- ltc = props;
- }
- }
+ JSONObject Props = edgeProp.getJSONObject("properties");
+ JSONObject bandw = Props.getJSONObject("bandwidth");
+ JSONObject stt = Props.getJSONObject("state");
+ JSONObject ltc = Props.getJSONObject("latency");
if (headNC.getInt("id") == headNC1_nodeConnId) {
Assert.assertEquals(headNode.getString("type"), nodeType);
Integer nodeId_1 = 3366;
String nodeConnectorType_1 = "STUB";
Integer nodeConnectorId_1 = 12;
-
String nodeType_2 = "STUB";
Integer nodeId_2 = 4477;
String nodeConnectorType_2 = "STUB";
}
}
}
-
// Configure the OSGi container
@Configuration
public Option[] config() {
org.slf4j,
org.apache.catalina.filters,
org.codehaus.jackson.jaxrs,
+ org.codehaus.jackson.annotate,
!org.codehaus.enunciate.jaxrs
</Import-Package>
<Web-ContextPath>/controller/nb/v2/switchmanager</Web-ContextPath>
package org.opendaylight.controller.switchmanager.northbound;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.Property;
private NodeConnector nodeconnector;
@XmlElementRef
@XmlElementWrapper
+ @JsonIgnore
private Set<Property> properties;
// JAXB required constructor
this.properties = properties;
}
+ @JsonProperty(value="properties")
+ public Map<String, Property> getMapProperties() {
+ Map<String, Property> map = new HashMap<String, Property>();
+ for (Property p : properties) {
+ map.put(p.getName(), p);
+ }
+ return map;
+ }
+
+ public void setMapProperties(Map<String, Property> propertiesMap) {
+ this.properties = new HashSet<Property>(propertiesMap.values());
+ }
+
public Set<Property> getProperties() {
return properties;
}
package org.opendaylight.controller.switchmanager.northbound;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.Property;
private Node node;
@XmlElementRef
@XmlElementWrapper
+ @JsonIgnore
private Set<Property> properties;
// JAXB required constructor
this.properties = properties;
}
+ @JsonProperty(value="properties")
+ public Map<String, Property> getMapProperties() {
+ Map<String, Property> map = new HashMap<String, Property>();
+ for (Property p : properties) {
+ map.put(p.getName(), p);
+ }
+ return map;
+ }
+
+ public void setMapProperties(Map<String, Property> propertiesMap) {
+ this.properties = new HashSet<Property>(propertiesMap.values());
+ }
+
public Set<Property> getProperties() {
return properties;
}
org.opendaylight.controller.usermanager,
org.opendaylight.controller.topologymanager,
com.sun.jersey.spi.container.servlet,
+ org.codehaus.jackson.annotate,
javax.ws.rs,
javax.ws.rs.core,
javax.xml.bind,
package org.opendaylight.controller.topology.northbound;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
import org.opendaylight.controller.sal.core.Edge;
import org.opendaylight.controller.sal.core.Property;
private Edge edge;
@XmlElementRef
@XmlElementWrapper
+ @JsonIgnore
private Set<Property> properties;
// JAXB required constructor
this.properties = properties;
}
+ @JsonProperty(value="properties")
+ public Map<String, Property> getMapProperties() {
+ Map<String, Property> map = new HashMap<String, Property>();
+ for (Property p : properties) {
+ map.put(p.getName(), p);
+ }
+ return map;
+ }
+
+ public void setMapProperties(Map<String, Property> propertiesMap) {
+ this.properties = new HashSet<Property>(propertiesMap.values());
+ }
+
public Set<Property> getProperties() {
return properties;
}
-
public void setProperties(Set<Property> properties) {
this.properties = properties;
}
}
public static AppRoleLevel fromString(String levelString) {
- for (AppRoleLevel level : AppRoleLevel.values()) {
- if (level.toString().equals(levelString)) {
- return level;
+ for (AppRoleLevel rolelevel : AppRoleLevel.values()) {
+ if (rolelevel.toString().equals(levelString)) {
+ return rolelevel;
}
}
return null;
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class Actions extends Property {
private static final long serialVersionUID = 1L;
@XmlElement(name="value")
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
* seconds.
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
@SuppressWarnings("serial")
public class AdvertisedBandwidth extends Bandwidth {
public static final String AdvertisedBandwidthPropName = "advertisedBandwidth";
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* seconds.
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class Bandwidth extends Property {
private static final long serialVersionUID = 1L;
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* Describes supported buffers (#packets)
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class Buffers extends Property {
private static final long serialVersionUID = 1L;
@XmlElement(name="value")
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* Describes supported capabilities
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class Capabilities extends Property {
private static final long serialVersionUID = 1L;
@XmlElement(name="value")
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement
@SuppressWarnings("serial")
+@XmlAccessorType(XmlAccessType.NONE)
public class Config extends Property {
@XmlElement(name="value")
private short configValue;
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement
@SuppressWarnings("serial")
+@XmlAccessorType(XmlAccessType.NONE)
public class Description extends Property {
@XmlElement(name="value")
private String descriptionValue;
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* The class represents the forwarding mode property of a node.
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
@SuppressWarnings("serial")
public class ForwardingMode extends Property {
@XmlElement(name="value")
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* Describe a latency in picoseconds or multiple of its.
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class Latency extends Property {
private static final long serialVersionUID = 1L;
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* The class represents the Name property of an element.
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
@SuppressWarnings("serial")
public class Name extends Property {
@XmlElement(name="value")
@Override
public String toString() {
if (this.nodeType.equals(NodeIDType.OPENFLOW)) {
- return this.nodeType.toString() + "|"
+ return this.nodeType + "|"
+ HexEncode.longToHexString((Long) this.nodeID);
} else {
- return this.nodeType.toString() + "|" + this.nodeID.toString();
+ return this.nodeType + "|" + this.nodeID.toString();
}
}
.equals(NodeConnectorIDType.SWSTACK) ||
this.nodeConnectorType
.equals(NodeConnectorIDType.HWPATH)) {
- return this.nodeConnectorType.toString();
+ return this.nodeConnectorType;
} else {
- return this.nodeConnectorType.toString() + "|"
+ return this.nodeConnectorType + "|"
+ this.nodeConnectorID.toString();
}
}
}
public String getNodeTableIdAsString() {
- return this.nodeTableType.toString() + "|"
+ return this.nodeTableType + "|"
+ this.nodeTableID.toString();
}
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
* bits per seconds.
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class PeerBandwidth extends Bandwidth {
private static final long serialVersionUID = 1L;
import java.io.Serializable;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
* element
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
@XmlSeeAlso({ Config.class, Name.class, State.class, TimeStamp.class,
Latency.class, Bandwidth.class, Tier.class, Actions.class,
AdvertisedBandwidth.class, Buffers.class, Capabilities.class,
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
*
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
@SuppressWarnings("serial")
public class State extends Property {
@XmlElement(name="value")
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
* seconds.
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class SupportedBandwidth extends Bandwidth {
private static final long serialVersionUID = 1L;
public static final String SupportedBandwidthPropName = "supportedBandwidth";
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* Describes supported # of datapath tables
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class Tables extends Property {
private static final long serialVersionUID = 1L;
@XmlElement(name="value")
package org.opendaylight.controller.sal.core;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
*
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
@SuppressWarnings("serial")
public class Tier extends Property {
@XmlElement(name="value")
import java.util.Date;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
* to qualify what are we talking about
*/
@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
public class TimeStamp extends Property {
private static final long serialVersionUID = 1L;
@XmlElement(name = "value")
private long timestamp;
- @XmlElement(name = "timestampName")
+ @XmlElement(name = "name")
private String timestampName;
public static final String TimeStampPropName = "timeStamp";
WESP("WESP",141),
ROHC("ROHC",142);
*/
- private static final String regexNumberString = "^[0-9]+$";
+ private static final String regexDecimalString = "^[0-9]{3}$";
+ private static final String regexHexString = "^(0(x|X))[0-9a-fA-F]{2}$";
private String protocolName;
private int protocolNumber;
}
public static short getProtocolNumberShort(String name) {
- if (name.matches(regexNumberString)) {
+ if (name.matches(regexHexString)) {
+ return Short.valueOf(Short.decode(name));
+ }
+ if (name.matches(regexDecimalString)) {
return Short.valueOf(name);
}
for (IPProtocols proto : IPProtocols.values()) {
}
public static int getProtocolNumberInt(String name) {
- if (name.matches(regexNumberString)) {
+ if (name.matches(regexHexString)) {
+ return Integer.valueOf(Integer.decode(name));
+ }
+ if (name.matches(regexDecimalString)) {
return Integer.valueOf(name);
}
for (IPProtocols proto : IPProtocols.values()) {
}
public static byte getProtocolNumberByte(String name) {
- if (name.matches(regexNumberString)) {
+ if (name.matches(regexHexString)) {
+ return Integer.valueOf(Integer.decode(name)).byteValue();
+ }
+ if (name.matches(regexDecimalString)) {
return Integer.valueOf(name).byteValue();
}
for (IPProtocols proto : IPProtocols.values()) {
<groupId>org.opendaylight.controller</groupId>
<artifactId>commons.opendaylight</artifactId>
<version>1.4.0-SNAPSHOT</version>
- <relativePath>../commons/opendaylight</relativePath>
+ <relativePath>../../commons/opendaylight</relativePath>
</parent>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
protected String user;
protected List<String> roles;
private String password;
+
+ private static final boolean strongPasswordCheck = Boolean.getBoolean("enableStrongPasswordCheck");
+ private static final String BAD_PASSWORD = "Bad Password";
private static final int USERNAME_MAXLENGTH = 32;
- private static final int PASSWORD_MINLENGTH = 5;
- private static final int PASSWORD_MAXLENGTH = 256;
+ protected static final String PASSWORD_REGEX = "(?=.*[^\\w])(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,256}$";
private static final Pattern INVALID_USERNAME_CHARACTERS = Pattern.compile("([/\\s\\.\\?#%;\\\\]+)");
private static MessageDigest oneWayFunction = null;
static {
public UserConfig(String user, String password, List<String> roles) {
this.user = user;
- this.password = password;
- if (this.validatePassword().isSuccess()) {
- /*
- * Only if the password is a valid one, hash it. So in case it is not
- * valid, when UserConfig.validate() is called, the proper
- * validation error will be returned to the caller. If we hashed a
- * priori instead, the mis-configuration would be masked
- */
- this.password = hash(this.password);
- }
+ /*
+ * Password validation to be done on clear text password. If fails, mark
+ * the password with a well known label, so that object validation can
+ * report the proper error. Only if password is a valid one, hash it.
+ */
+ this.password = (validatePassword(password).isSuccess()) ? hash(password) : BAD_PASSWORD;
this.roles = (roles == null) ? new ArrayList<String>() : new ArrayList<String>(roles);
}
}
public Status validate() {
- Status validCheck = validateRoles();
+ Status validCheck = validateUsername();
if (validCheck.isSuccess()) {
- validCheck = validateUsername();
+ validCheck = (!password.equals(BAD_PASSWORD)) ? new Status(StatusCode.SUCCESS) : new Status(
+ StatusCode.BADREQUEST,
+ "Password should be 8 to 256 characters long, contain both upper and lower case letters, "
+ + "at least one number and at least one non alphanumeric character");
}
if (validCheck.isSuccess()) {
- validCheck = validatePassword();
+ validCheck = validateRoles();
}
return validCheck;
}
return new Status(StatusCode.SUCCESS);
}
- private Status validatePassword() {
+ private Status validatePassword(String password) {
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");
+ if (strongPasswordCheck && !password.matches(UserConfig.PASSWORD_REGEX)) {
+ return new Status(StatusCode.BADREQUEST, "Password should be 8 to 256 characters long, "
+ + "contain both upper and lower case letters, at least one number "
+ + "and at least one non alphanumeric character");
}
return new Status(StatusCode.SUCCESS);
}
UserConfig.oneWayFunction.reset();
return HexEncode.bytesToHexString(UserConfig.oneWayFunction.digest(message.getBytes(Charset.defaultCharset())));
}
+
+ /**
+ * Returns UserConfig instance populated with the passed parameters. It does
+ * not run any checks on the passed parameters.
+ *
+ * @param userName
+ * the user name
+ * @param password
+ * the plain text password
+ * @param roles
+ * the list of roles
+ * @return the UserConfig object populated with the passed parameters. No
+ * validity check is run on the input parameters.
+ */
+ public static UserConfig getUncheckedUserConfig(String userName, String password, List<String> roles) {
+ UserConfig config = new UserConfig();
+ config.user = userName;
+ config.password = hash(password);
+ config.roles = roles;
+ return config;
+ }
}
UserConfig userConfig2 = new UserConfig("uname", "ciscocisco", roles);
assertEquals(userConfig, userConfig2);
}
+
+ @Test
+ public void userConfigPasswordTest() {
+
+ String regex = UserConfig.PASSWORD_REGEX;
+ String password = null;
+
+ // Good password
+ password = "aBc@eF#h9";
+ assertTrue(password.matches(regex));
+ password = "^aBc@eF#h9$88ad*o&";
+ assertTrue(password.matches(regex));
+ password = "_^aBc@\":eF#h;9$\\8|8ad*o&-(){}/,.><?+-";
+ assertTrue(password.matches(regex));
+ password = "culonE1)";
+ assertTrue(password.matches(regex));
+
+ // Too short
+ password = "aB3@eF#";
+ assertFalse(password.matches(regex));
+
+ // No number
+ password = "#BeCCC#CeDfDf";
+ assertFalse(password.matches(regex));
+
+ // No lower case
+ password = "AB8C#CC@C4";
+ assertFalse(password.matches(regex));
+
+ // No upper case
+ password = "ab8defg9!";
+ assertFalse(password.matches(regex));
+
+ // No special characters
+ password = "aBc4ef7H8";
+ assertFalse(password.matches(regex));
+ }
}
*/
@Override
public Object[] getImplementations() {
- return null;
+ return new Object[]{};
}
/**
}
private void checkDefaultNetworkAdmin() {
- // If startup config is not there, it's old or it was deleted,
- // need to add Default Network Admin User
+ /*
+ * If startup config is not there, it's old or it was deleted or if a
+ * password recovery was run, need to add Default Network Admin User
+ */
if (!localUserConfigList.containsKey(DEFAULT_ADMIN)) {
List<String> roles = new ArrayList<String>(1);
roles.add(DEFAULT_ADMIN_ROLE);
- localUserConfigList.put(DEFAULT_ADMIN, new UserConfig(DEFAULT_ADMIN, DEFAULT_ADMIN_PASSWORD, roles));
+ // Need to skip the strong password check for the default admin
+ UserConfig defaultAdmin = UserConfig.getUncheckedUserConfig(UserManager.DEFAULT_ADMIN,
+ UserManager.DEFAULT_ADMIN_PASSWORD, roles);
+ localUserConfigList.put(UserManager.DEFAULT_ADMIN, defaultAdmin);
}
}
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
@RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST)
@ResponseBody
- public Status changePassword(@PathVariable("username") String username, HttpServletRequest request,
- @RequestParam("currentPassword") String currentPassword, @RequestParam("newPassword") String newPassword) {
+ public Status changePassword(
+ @PathVariable("username") String username, HttpServletRequest request,
+ @RequestParam(value = "currentPassword", required=false) String currentPassword,
+ @RequestParam("newPassword") String newPassword) {
IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
if (userManager == null) {
- return new Status(StatusCode.GONE, "User Manager not found");
+ return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
}
- if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
- return new Status(StatusCode.FORBIDDEN, "Operation not permitted");
- }
+ Status status;
+ String requestingUser = request.getUserPrincipal().getName();
+
+ //changing own password
+ if (requestingUser.equals(username) ) {
+ status = userManager.changeLocalUserPassword(username, currentPassword, newPassword);
+ //enforce the user to re-login with new password
+ if (status.isSuccess() && !newPassword.equals(currentPassword)) {
+ userManager.userLogout(username);
+ HttpSession session = request.getSession(false);
+ if ( session != null) {
+ session.invalidate();
+ }
+ }
+
+ //admin level user resetting other's password
+ } else if (authorize(userManager, UserLevel.NETWORKADMIN, request)) {
+
+ //Since User Manager doesn't have an unprotected password change API,
+ //we re-create the user with the new password (and current roles).
+ List<String> roles = userManager.getUserRoles(username);
+ UserConfig newConfig = new UserConfig(username, newPassword, roles);
+
+ //validate before removing existing config, so we don't remove but fail to add
+ status = newConfig.validate();
+ if (!status.isSuccess()) {
+ return status;
+ }
+
+ userManager.userLogout(username);
+ status = userManager.removeLocalUser(username);
+ if (!status.isSuccess()) {
+ return status;
+ }
+ if (userManager.addLocalUser(newConfig).isSuccess()) {
+ status = new Status(StatusCode.SUCCESS, "Password for user " + username + " reset successfully.");
+ } else {
+ //unexpected
+ status = new Status(StatusCode.INTERNALERROR, "Failed resetting password for user " + username + ". User is now removed.");
+ }
- if (newPassword.isEmpty()) {
- return new Status(StatusCode.BADREQUEST, "Empty passwords not allowed");
+ //unauthorized
+ } else {
+ status = new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
}
- Status status = userManager.changeLocalUserPassword(username, currentPassword, newPassword);
if (status.isSuccess()) {
- DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for", username);
+ DaylightWebUtil.auditlog("User", requestingUser, "changed password for", username);
}
return status;
}
</div>
<div class="span3">
<div id="toolbar" class="btn-group">
+ <input type="hidden" id="currentuser" value="${username}" data-role="${role}">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<div class="icon-user"></div> ${username} <span class="caret"></span>
</a>
// change password binding
$('#'+one.main.admin.id.modal.password.submit, $modal).click(function() {
one.main.admin.password.submit(id, $modal, function(result) {
- if (result.code == 'SUCCESS') {
- $modal.modal('hide');
- successCallback();
+ if (result.success) {
+ //if changed own password, enforce relogin
+ if (id.trim() == $('#currentuser').val().trim()) {
+ alert("Password changed successfully. Please re-login with your new password.");
+ window.location = '/';
+ }
} else {
alert(result.code+': '+result.description);
}