From 9095cdc4f1083cbac31e2b9d657afec0765ce085 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Mon, 11 Aug 2014 03:10:04 -0400 Subject: [PATCH 10/13] Add IECUserRolesExtension class --- .../security/extensions/IECUserRolesExtension.java | 271 +++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 base/util/src/netscape/security/extensions/IECUserRolesExtension.java diff --git a/base/util/src/netscape/security/extensions/IECUserRolesExtension.java b/base/util/src/netscape/security/extensions/IECUserRolesExtension.java new file mode 100644 index 0000000000000000000000000000000000000000..cd0aceae9a57e7b8988e33597f0a8d8e927ff227 --- /dev/null +++ b/base/util/src/netscape/security/extensions/IECUserRolesExtension.java @@ -0,0 +1,271 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2014 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package netscape.security.extensions; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigInteger; +import java.security.cert.CertificateException; +import java.util.Collection; +import java.util.Enumeration; + +import netscape.security.util.BigInt; +import netscape.security.util.DerOutputStream; +import netscape.security.util.DerValue; +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.CertAttrSet; +import netscape.security.x509.Extension; +import netscape.security.x509.OIDMap; + +/** + * This represents the IEC 62351-8 IECUserRoles extension. + * + * ASN.1: + * + * id-IEC62351 OBJECT_IDENTIFIER ::= { 1 2 840 10070 } + * + * id-IECuserRoles OBJECT_IDENTIFIER ::= id-IEC62351 { 8 1 } + * + * IECUserRoles ::= SEQUENCE OF UserRoleInfo + * + * UserRoleInfo ::= SEQUENCE { -- contains the role information blob + * -- IEC62351 specific parameter + * userRole SEQUENCE SIZE (1..MAX) OF RoleID + * aor UTF8String (SIZE(1..64)), + * revision INTEGER (0..255), + * roleDefinition UTF8String (0..23) OPTIONAL, + * -- optional fields to be used within IEEE 1815 and IEC60870-5 + * operation Operation OPTIONAL, + * statusChangeSequenceNumber INTEGER (0..4 294 967 295) OPTIONAL, + * } + * + * RoleId ::= INTEGER (-32 768..32 767) + * + * Operation ::= ENUMERATED { Add (1), Delete (2), Change (3) } + * + */ +public class IECUserRolesExtension extends Extension implements CertAttrSet { + private static final long serialVersionUID = 172340873242193489L; + + public static final String OID = "1.2.840.10070.8.1"; + public static final String NAME = "IECUserRoles"; + public enum Operation { ADD, DELETE, CHANGE }; + public static final BigInteger MAX_STATUS_CHANGE_SEQNO = + new BigInteger("4294967295"); + + public Collection iecUserRoles; + + static { + try { + OIDMap.addAttribute(IECUserRolesExtension.class.getName(), + OID, IECUserRolesExtension.class.getName()); + } catch (CertificateException e) { + } + } + + public IECUserRolesExtension( + boolean crit, + Collection iecUserRoles + ) throws CertificateException { + try { + extensionId = ObjectIdentifier.getObjectIdentifier(OID); + } catch (IOException e) { + // never here + } + + critical = crit; + this.iecUserRoles = iecUserRoles; + } + + public IECUserRolesExtension(Boolean crit, Object byteVal) + throws IOException { + extensionId = ObjectIdentifier.getObjectIdentifier(OID); + critical = crit.booleanValue(); + extensionValue = ((byte[]) byteVal).clone(); + } + + @Override + public String toString() { + String presentation = "oid=" + OID + " "; + + if (critical) { + presentation += "critical=true"; + } + if (extensionValue != null) { + StringBuffer extByteValue = new StringBuffer(" val="); + for (int i = 0; i < extensionValue.length; i++) { + extByteValue.append(extensionValue[i] + " "); + } + presentation += extByteValue.toString(); + } + return presentation; + } + + public void decode(InputStream in) + throws CertificateException, IOException { + } + + public void encode(DerOutputStream out) throws IOException { + encodeExtValue(); + super.encode(out); + } + + public void encode(OutputStream out) + throws CertificateException, IOException { + DerOutputStream temp = new DerOutputStream(); + encode(temp); + out.write(temp.toByteArray()); + } + + public void set(String name, Object obj) + throws CertificateException, IOException { + // NOT USED + } + + public Object get(String name) throws CertificateException, IOException { + // NOT USED + return null; + } + + public Enumeration getAttributeNames() { + return null; + } + + public String getName() { + return NAME; + } + + public void delete(String name) + throws CertificateException, IOException { + // NOT USED + } + + private void encodeExtValue() throws IOException { + if (extensionValue != null) + return; + + // write IECUserRoles SEQUENCE OF UserRoleInfo + DerOutputStream outIECUserRoles = new DerOutputStream(); + for (UserRoleInfo userRoleInfo : iecUserRoles) { + userRoleInfo.encode(outIECUserRoles); + } + + DerOutputStream out = new DerOutputStream(); + out.write(DerValue.tag_Sequence, outIECUserRoles); + extensionValue = out.toByteArray(); + } + + public static class UserRoleInfo { + private Collection userRole; + private String aor; + private int revision; + private String roleDefinition; + private Operation operation; + private BigInteger statusChangeSequenceNumber; + + public UserRoleInfo( + Collection userRole, + String aor, + int revision, + String roleDefinition, + Operation operation, + BigInteger statusChangeSequenceNumber + ) throws CertificateException { + // userRole SEQUENCE SIZE (1..MAX) OF RoleID + // RoleId ::= INTEGER (-32 768..32 767) + if (userRole == null) + throw new CertificateException("userRole cannot be null"); + if (userRole.size() < 1) + throw new CertificateException("userRole must have at least one element"); + for (int roleId : userRole) { + if (roleId < -32768 || roleId > 32767) + throw new CertificateException("RoleId must be in range (-32 768..32 767)"); + } + this.userRole = userRole; + + // aor (area of responsibility) UTF8String (SIZE(1..64)) + if (aor == null) + throw new CertificateException("aor cannot be null"); + if (aor.isEmpty() || aor.length() > 64) + throw new CertificateException("aor must be of SIZE(1..64)"); + this.aor = aor; + + // revision INTEGER (0..255) + if (revision < 0 || revision > 255) + throw new CertificateException("revision must be in range (0..255)"); + this.revision = revision; + + // roleDefinition UTF8String (0..23) OPTIONAL + if (roleDefinition != null && roleDefinition.length() > 23) + throw new CertificateException("roleDefinition must be of SIZE(0..23)"); + this.roleDefinition = roleDefinition; + + // operation Operation OPTIONAL + // Operation ::= ENUMERATED { Add (1), Delete (2), Change (3) } + this.operation = operation; + + // statusChangeSequenceNumber INTEGER (0..4 294 967 295) OPTIONAL + if (statusChangeSequenceNumber != null && ( + statusChangeSequenceNumber.compareTo(BigInteger.ZERO) < 0 + || statusChangeSequenceNumber.compareTo(MAX_STATUS_CHANGE_SEQNO) > 1)) + throw new CertificateException( + "statusChangeSequenceNumber must be in range (0..4 294 967 295)"); + this.statusChangeSequenceNumber = statusChangeSequenceNumber; + } + + public void encode(DerOutputStream out) throws IOException { + DerOutputStream outUserRoleInfo = new DerOutputStream(); + + DerOutputStream outRoles = new DerOutputStream(); + for (int role : userRole) { + outRoles.putInteger(new BigInt(role)); + } + outUserRoleInfo.write(DerValue.tag_Sequence, outRoles); + + outUserRoleInfo.putUTF8String(aor); + + outUserRoleInfo.putInteger(new BigInt(revision)); + + if (roleDefinition != null) + outUserRoleInfo.putUTF8String(roleDefinition); + + if (operation != null) { + int op = 0; + switch (operation) { + case ADD: + op = 1; + break; + case DELETE: + op = 2; + break; + case CHANGE: + op = 3; + break; + } + outUserRoleInfo.putEnumerated(op); + } + + if (statusChangeSequenceNumber != null) + outUserRoleInfo.putInteger(new BigInt(statusChangeSequenceNumber)); + + // write UserRoleInfo SEQUENCE (of the above information) + out.write(DerValue.tag_Sequence, outUserRoleInfo); + } + } +} -- 2.1.0