1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.michaelo.tomcat.realm;
17
18 import java.nio.Buffer;
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21 import java.util.Arrays;
22
23
24
25
26
27
28 public class Sid {
29
30 public static final Sid NULL_SID = new Sid(new byte[] {
31 (byte) 0x01,
32 (byte) 0x01,
33 (byte) 0x00,
34 (byte) 0x00,
35 (byte) 0x00,
36 (byte) 0x00,
37 (byte) 0x00,
38 (byte) 0x00,
39 (byte) 0x00,
40 (byte) 0x00,
41 (byte) 0x00,
42 (byte) 0x00
43 });
44
45 public static final Sid ANONYMOUS_SID = new Sid(new byte[] {
46 (byte) 0x01,
47 (byte) 0x01,
48 (byte) 0x00,
49 (byte) 0x00,
50 (byte) 0x00,
51 (byte) 0x00,
52 (byte) 0x00,
53 (byte) 0x05,
54 (byte) 0x07,
55 (byte) 0x00,
56 (byte) 0x00,
57 (byte) 0x00
58 });
59
60 private byte[] bytes;
61
62 private int revision;
63 private int subAuthorityCount;
64 private byte[] identifierAuthority;
65 private long[] subAuthorities;
66
67 private String sidString;
68
69
70
71
72
73
74
75
76
77
78 public Sid(byte[] sidBytes) {
79 if (sidBytes == null) throw new NullPointerException("sidBytes cannot be null");
80 if (sidBytes.length < 12)
81 throw new IllegalArgumentException("SID must be at least 12 bytes long but is " + sidBytes.length);
82
83 ByteBuffer buf = ByteBuffer.wrap(sidBytes);
84 buf.order(ByteOrder.LITTLE_ENDIAN);
85
86
87 this.revision = buf.get() & 0xFF;
88 if (this.revision != 0x01) throw new IllegalArgumentException("SID revision must be 1 but is " + this.revision);
89
90
91 this.subAuthorityCount = buf.get() & 0xFF;
92 if (this.subAuthorityCount > 15)
93 throw new IllegalArgumentException(
94 "SID subauthority count must be at most 15 but is " + this.subAuthorityCount);
95
96 this.identifierAuthority = new byte[6];
97 buf.get(this.identifierAuthority);
98
99 StringBuilder sidStringBuilder = new StringBuilder("S");
100
101 sidStringBuilder.append('-').append(this.revision);
102
103 ByteBuffer iaBuf = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
104 ((Buffer) iaBuf).position(2);
105 iaBuf.put(this.identifierAuthority);
106 ((Buffer) iaBuf).flip();
107
108 sidStringBuilder.append('-').append(iaBuf.getLong());
109
110 this.subAuthorities = new long[this.subAuthorityCount];
111 for (byte b = 0; b < this.subAuthorityCount; b++) {
112 this.subAuthorities[b] = buf.getInt() & 0xffffffffL;
113
114 sidStringBuilder.append('-').append(this.subAuthorities[b]);
115 }
116
117 this.bytes = Arrays.copyOf(sidBytes, sidBytes.length);
118 this.sidString = sidStringBuilder.toString();
119 }
120
121 public Sid append(long relativeId) {
122 byte[] sidBytes = this.bytes;
123 byte[] appendedSidBytes = new byte[sidBytes.length + 4];
124 System.arraycopy(sidBytes, 0, appendedSidBytes, 0, sidBytes.length);
125 appendedSidBytes[1] = (byte) (this.subAuthorityCount + 1);
126 int signedRelativeId = (int) (relativeId);
127 appendedSidBytes[sidBytes.length + 0] = (byte) (signedRelativeId & 0xFF);
128 appendedSidBytes[sidBytes.length + 1] = (byte) ((signedRelativeId >> 8) & 0xFF);
129 appendedSidBytes[sidBytes.length + 2] = (byte) ((signedRelativeId >> 16) & 0xFF);
130 appendedSidBytes[sidBytes.length + 3] = (byte) ((signedRelativeId >> 24) & 0xFF);
131 return new Sid(appendedSidBytes);
132 }
133
134 public byte[] getBytes() {
135 return Arrays.copyOf(bytes, bytes.length);
136 }
137
138 @Override
139 public boolean equals(Object obj) {
140 if (obj == null) return false;
141
142 if (!(obj instanceof Sid)) return false;
143
144 Sid that = (Sid) obj;
145
146 if (this == that) return true;
147
148 return Arrays.equals(this.bytes, that.bytes);
149 }
150
151 @Override
152 public int hashCode() {
153 return Arrays.hashCode(this.bytes);
154 }
155
156 @Override
157 public String toString() {
158 return sidString;
159 }
160 }