001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.satsa.acl;
028:
029: import com.sun.satsa.util.Utils;
030:
031: import java.io.IOException;
032:
033: /**
034: * This class represents PKCS#15 PIN attributes.
035: */
036: public class PINAttributes {
037:
038: /** PIN type constant. */
039: private static final int TYPE_BCD = 0;
040: /** PIN type constant. */
041: private static final int TYPE_ASCII = 1;
042: /** PIN type constant. */
043: private static final int TYPE_UTF = 2;
044: /** PIN type constant. */
045: private static final int TYPE_HN = 3;
046: /** PIN type constant. */
047: private static final int TYPE_ISO = 4;
048:
049: /** PIN flag constant. */
050: public static final int FLAG_CASE_SENSITIVE = 1;
051: /** PIN flag constant. */
052: public static final int FLAG_CHANGE_DISABLED = 2;
053: /** PIN flag constant. */
054: public static final int FLAG_UNBLOCK_DISABLED = 4;
055: /** PIN flag constant. */
056: public static final int FLAG_NEEDS_PADDING = 8;
057: /** PIN flag constant. */
058: public static final int FLAG_DISABLE_ALLOWED = 16;
059: /** PIN flag constant. */
060: public static final int FLAG_UNBLOCKING_PIN = 32;
061:
062: /** PIN label. */
063: public String label;
064: /** PIN identifier. */
065: public int id;
066: /** pinType PIN attribute. */
067: public int pinType;
068: /** minLength PIN attribute. */
069: public int minLength;
070: /** storedLength PIN attribute. */
071: public int storedLength;
072: /** maxLength PIN attribute. */
073: public int maxLength;
074: /** pinReference PIN attribute. */
075: public int pinReference;
076: /** padChar PIN attribute. */
077: public int padChar;
078: /** pinFlags PIN attribute. */
079: public int pinFlags;
080: /** Path PIN attribute. */
081: public short[] path;
082:
083: /**
084: * Constructs PINAttributes object.
085: */
086: public PINAttributes() {
087: }
088:
089: /**
090: * Constructs PINAttributes object.
091: * @param r reader for permissions file.
092: * @throws java.io.IOException if I/O error occurs.
093: */
094: PINAttributes(ACLFileReader r) throws IOException {
095:
096: r.checkWord("{");
097:
098: while (true) {
099:
100: String s = r.readWord();
101:
102: if (s.equals("}")) {
103: break;
104: }
105:
106: if (s.equals("label")) {
107: label = r.readLine();
108: continue;
109: }
110:
111: if (s.equals("id")) {
112: id = r.readByte();
113: continue;
114: }
115:
116: String h = r.readWord();
117:
118: if (s.equals("type")) {
119: if (h.equals("bcd")) {
120: pinType = TYPE_BCD;
121: } else if (h.equals("ascii")) {
122: pinType = TYPE_ASCII;
123: } else if (h.equals("utf")) {
124: pinType = TYPE_UTF;
125: } else if (h.equals("half-nibble")) {
126: pinType = TYPE_HN;
127: } else if (h.equals("iso")) {
128: pinType = TYPE_ISO;
129: } else {
130: throw new IOException();
131: }
132: continue;
133: }
134:
135: if (s.equals("min")) {
136: minLength = Integer.parseInt(h, 16);
137: continue;
138: }
139:
140: if (s.equals("stored")) {
141: storedLength = Integer.parseInt(h, 16);
142: continue;
143: }
144:
145: if (s.equals("max")) {
146: maxLength = Integer.parseInt(h, 16);
147: continue;
148: }
149:
150: if (s.equals("reference")) {
151: pinReference = Integer.parseInt(h, 16);
152: continue;
153: }
154:
155: if (s.equals("pad")) {
156: padChar = Integer.parseInt(h, 16);
157: continue;
158: }
159:
160: if (s.equals("flag")) {
161: if (h.equals("case-sensitive")) {
162: pinFlags |= FLAG_CASE_SENSITIVE;
163: } else if (h.equals("change-disabled")) {
164: pinFlags |= FLAG_CHANGE_DISABLED;
165: } else if (h.equals("unblock-disabled")) {
166: pinFlags |= FLAG_UNBLOCK_DISABLED;
167: } else if (h.equals("needs-padding")) {
168: pinFlags |= FLAG_NEEDS_PADDING;
169: } else if (h.equals("disable-allowed")) {
170: pinFlags |= FLAG_DISABLE_ALLOWED;
171: } else if (h.equals("unblockingPIN")) {
172: pinFlags |= FLAG_UNBLOCKING_PIN;
173: } else {
174: throw new IOException();
175: }
176: continue;
177: }
178: throw new IOException();
179: }
180: }
181:
182: /**
183: * Returns true if this PIN is a number.
184: * @return true if this PIN is a number.
185: */
186: public boolean isNumeric() {
187: return (pinType != TYPE_UTF);
188: }
189:
190: /**
191: * Returns maximum PIN length in characters.
192: * @return maximum PIN length in characters.
193: */
194: public int getMaxLength() {
195:
196: if ((pinFlags & FLAG_NEEDS_PADDING) == 0) {
197: return maxLength;
198: }
199:
200: if (pinType == TYPE_BCD) {
201: return storedLength * 2;
202: }
203:
204: // UTF symbol may occupy 1 or 2 bytes, additional check is necessary
205:
206: return storedLength;
207: }
208:
209: /**
210: * Verifies if the specified operation can be performed on this PIN.
211: * @param action operation identifier.
212: * @return true if the specified operation can be performed on this PIN.
213: */
214: public boolean check(int action) {
215:
216: if (action == ACLPermissions.CMD_CHANGE) {
217: return (pinFlags & FLAG_CHANGE_DISABLED) == 0;
218: }
219:
220: if (action == ACLPermissions.CMD_DISABLE) {
221: return (pinFlags & FLAG_DISABLE_ALLOWED) != 0;
222: }
223:
224: if (action == ACLPermissions.CMD_UNBLOCK) {
225: return (pinFlags & FLAG_UNBLOCK_DISABLED) == 0;
226: }
227:
228: return true;
229: }
230:
231: /**
232: * Verifies if this PIN can be used to unblock other PINs.
233: * @return true if this PIN can be used to unblock other PINs.
234: */
235: public boolean isUnblockingPIN() {
236: return (pinFlags & FLAG_UNBLOCKING_PIN) != 0;
237: }
238:
239: /**
240: * Transforms string entered by user according to PIN attributes.
241: * @param s the value enterd by user.
242: * @return converted and padded PIN value.
243: */
244: public byte[] transform(String s) {
245:
246: if (s.length() < minLength) {
247: return null;
248: }
249:
250: byte[] data = null;
251:
252: if (pinType == TYPE_UTF) {
253:
254: if ((pinFlags & FLAG_CASE_SENSITIVE) == 0) {
255: s = s.toUpperCase(); // locale?
256: }
257:
258: data = Utils.stringToBytes(s);
259:
260: if (data.length > getMaxLength()) {
261: return null;
262: }
263:
264: } else {
265:
266: byte[] tmp = new byte[s.length()];
267: for (int i = 0; i < tmp.length; i++) {
268: tmp[i] = (byte) (s.charAt(i));
269: }
270:
271: if (pinType == TYPE_ASCII || pinType == TYPE_ISO) {
272: data = tmp;
273: } else {
274: if (pinType == TYPE_HN) {
275: data = tmp;
276: for (int i = 0; i < data.length; i++) {
277: data[i] = (byte) (0xf0 | (data[i] - 0x30));
278: }
279: } else { // type == TYPE_BCD
280:
281: data = new byte[(tmp.length + 1) / 2];
282:
283: for (int i = 0; i < data.length; i++) {
284:
285: int l = i * 2;
286: int b1 = tmp[l] - 0x30;
287: int b2;
288: if (l + 1 == tmp.length) {
289: b2 = padChar;
290: } else {
291: b2 = tmp[l + 1] - 0x30;
292: }
293: data[i] = (byte) ((b1 << 4) | (b2 & 0xf));
294: }
295:
296: }
297: }
298: }
299:
300: if (((pinFlags & FLAG_NEEDS_PADDING) == 0)
301: || (data.length == storedLength)) {
302: return data;
303: }
304:
305: byte[] r = new byte[storedLength];
306: System.arraycopy(data, 0, r, 0, data.length);
307: for (int i = data.length; i < storedLength; i++) {
308: r[i] = (byte) padChar;
309: }
310:
311: return r;
312: }
313: }
|