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 acl_data;
028:
029: import java.io.IOException;
030:
031: /**
032: * This class represents PKCS#15 PIN attributes.
033: */
034: public class PINAttributes {
035:
036: /** PIN type constant. */
037: private static final int TYPE_BCD = 0;
038: /** PIN type constant. */
039: private static final int TYPE_ASCII = 1;
040: /** PIN type constant. */
041: private static final int TYPE_UTF = 2;
042: /** PIN type constant. */
043: private static final int TYPE_HN = 3;
044: /** PIN type constant. */
045: private static final int TYPE_ISO = 4;
046:
047: /** PIN flag constant. */
048: public static final int FLAG_CASE_SENSITIVE = 0x8000;
049: /** PIN flag constant. */
050: public static final int FLAG_LOCAL = 0x4000;
051: /** PIN flag constant. */
052: public static final int FLAG_CHANGE_DISABLED = 0x2000;
053: /** PIN flag constant. */
054: public static final int FLAG_UNBLOCK_DISABLED = 0x1000;
055: /** PIN flag constant. */
056: public static final int FLAG_INITIALIZED = 0x800;
057: /** PIN flag constant. */
058: public static final int FLAG_NEEDS_PADDING = 0x400;
059: /** PIN flag constant. */
060: public static final int FLAG_UNBLOCKING_PIN = 0x200;
061: /** PIN flag constant. */
062: public static final int FLAG_SOPIN = 0x100;
063: /** PIN flag constant. */
064: public static final int FLAG_DISABLE_ALLOWED = 0x80;
065: /** PIN flag constant. */
066: public static final int FLAG_INTEGRITY_PROTECTED = 0x40;
067: /** PIN flag constant. */
068: public static final int FLAG_CONFIDENTIALITY_PROTECTED = 0x20;
069: /** PIN flag constant. */
070: public static final int FLAG_EXCHANGEREFDATA = 0x10;
071:
072: /** PIN label. */
073: public String label;
074: /** PIN identifier. */
075: public int id;
076: /** pinType PIN attribute. */
077: public int pinType;
078: /** minLength PIN attribute. */
079: public int minLength;
080: /** storedLength PIN attribute. */
081: public int storedLength;
082: /** maxLength PIN attribute. */
083: public int maxLength;
084: /** pinReference PIN attribute. */
085: public int pinReference;
086: /** padChar PIN attribute. */
087: public int padChar;
088: /** pinFlags PIN attribute. */
089: public int pinFlags;
090: /** Path PIN attribute. */
091: public short[] path;
092: /** Pin record */
093: private TLV pinRec;
094:
095: /**
096: * Constructs PINAttributes object.
097: */
098: public PINAttributes() {
099: }
100:
101: /**
102: * Constructs PINAttributes object.
103: * @param r reader for permissions file.
104: * @throws java.io.IOException if I/O error occurs.
105: */
106: PINAttributes(ACLFileReader r) throws IOException {
107:
108: r.checkWord("{");
109:
110: while (true) {
111:
112: String s = r.readWord();
113:
114: if (s.equals("}")) {
115: break;
116: }
117:
118: if (s.equals("label")) {
119: label = r.readLine();
120: continue;
121: }
122:
123: if (s.equals("id")) {
124: id = r.readByte();
125: continue;
126: }
127:
128: String h = r.readWord();
129:
130: if (s.equals("type")) {
131: if (h.equals("bcd")) {
132: pinType = TYPE_BCD;
133: } else if (h.equals("ascii")) {
134: pinType = TYPE_ASCII;
135: } else if (h.equals("utf")) {
136: pinType = TYPE_UTF;
137: } else if (h.equals("half-nibble")) {
138: pinType = TYPE_HN;
139: } else if (h.equals("iso")) {
140: pinType = TYPE_ISO;
141: } else {
142: throw new IOException();
143: }
144: continue;
145: }
146:
147: if (s.equals("min")) {
148: minLength = Integer.parseInt(h, 16);
149: continue;
150: }
151:
152: if (s.equals("stored")) {
153: storedLength = Integer.parseInt(h, 16);
154: continue;
155: }
156:
157: if (s.equals("max")) {
158: maxLength = Integer.parseInt(h, 16);
159: continue;
160: }
161:
162: if (s.equals("reference")) {
163: pinReference = Integer.parseInt(h, 16);
164: continue;
165: }
166:
167: if (s.equals("pad")) {
168: padChar = Integer.parseInt(h, 16);
169: continue;
170: }
171:
172: if (s.equals("flag")) {
173: if (h.equals("case-sensitive")) {
174: pinFlags |= FLAG_CASE_SENSITIVE;
175: } else if (h.equals("change-disabled")) {
176: pinFlags |= FLAG_CHANGE_DISABLED;
177: } else if (h.equals("unblock-disabled")) {
178: pinFlags |= FLAG_UNBLOCK_DISABLED;
179: } else if (h.equals("needs-padding")) {
180: pinFlags |= FLAG_NEEDS_PADDING;
181: } else if (h.equals("disable-allowed")) {
182: pinFlags |= FLAG_DISABLE_ALLOWED;
183: } else if (h.equals("unblockingPIN")) {
184: pinFlags |= FLAG_UNBLOCKING_PIN;
185: } else {
186: throw new IOException();
187: }
188: continue;
189: }
190: throw new IOException();
191: }
192: createPINRec();
193: }
194:
195: /**
196: * Generates TLV structure that represents this PIN.
197: * @return TLV structure
198: * SEQUENCE PKCS15Object
199: * SEQUENCE CommonObjectAttributes
200: * UTF8_STRING label opt +
201: * BIT_STRING flags opt -
202: * SEQUENCE CommonAuthObjectAttributes
203: * OCTET_STRING authID
204: * 0xA0 Choice Object from PathOrObject
205: * SEQUENCE PinAttributes
206: * BIT_STRING PinFlags
207: * ENUMERATED PinType
208: * INT minLength
209: * INT storedLength
210: * INT maxLength
211: * Reference pinReference
212: * OCTET_STRING padChar opt
213: */
214: /**
215: * Creates PIN record
216: */
217: private void createPINRec() {
218:
219: TLV t, c, v;
220:
221: t = TLV.createSequence();
222:
223: t.setChild(TLV.createSequence()).setChild(
224: TLV.createUTF8String(label)); /* label */
225:
226: c = t.child;
227:
228: c.setNext(TLV.createSequence()). /* authId */
229: setChild(TLV.createOctetString(new byte[] { (byte) id }));
230:
231: c.next
232: .setNext(new TLV(ACEntry.CONTEXT_CONSTRUCTED_1))
233: .setChild(TLV.createSequence())
234: .setChild(
235: TLV.createBitString(Utils
236: .shortToBytes(pinFlags), 4))
237: .setNext(
238: new TLV(TLV.ENUMERATED_TYPE, Utils
239: .shortToBytes(pinType)))
240: .setNext(TLV.createInteger(minLength))
241: .setNext(TLV.createInteger(storedLength))
242: .setNext(TLV.createInteger(maxLength))
243: .setNext(TLV.createInteger(pinReference).setTag(0x80))
244: .setNext(
245: TLV
246: .createOctetString(new byte[] { (byte) padChar }));
247:
248: pinRec = t;
249: }
250:
251: /**
252: * Returns pinRec value
253: * @return pinRec value
254: */
255: public TLV getPINRec() {
256: return pinRec;
257: }
258:
259: /**
260: * Returns true if this PIN is a number.
261: * @return true if this PIN is a number.
262: */
263: public boolean isNumeric() {
264: return (pinType != TYPE_UTF);
265: }
266:
267: /**
268: * Returns maximum PIN length in characters.
269: * @return maximum PIN length in characters.
270: */
271: public int getMaxLength() {
272:
273: if ((pinFlags & FLAG_NEEDS_PADDING) == 0) {
274: return maxLength;
275: }
276:
277: if (pinType == TYPE_BCD) {
278: return storedLength * 2;
279: }
280:
281: // UTF symbol may occupy 1 or 2 bytes, additional check is necessary
282:
283: return storedLength;
284: }
285:
286: /**
287: * Verifies if the specified operation can be performed on this PIN.
288: * @param action operation identifier.
289: * @return true if the specified operation can be performed on this PIN.
290: */
291: public boolean check(int action) {
292:
293: if (action == ACLPermissions.CMD_CHANGE) {
294: return (pinFlags & FLAG_CHANGE_DISABLED) == 0;
295: }
296:
297: if (action == ACLPermissions.CMD_DISABLE) {
298: return (pinFlags & FLAG_DISABLE_ALLOWED) != 0;
299: }
300:
301: if (action == ACLPermissions.CMD_UNBLOCK) {
302: return (pinFlags & FLAG_UNBLOCK_DISABLED) == 0;
303: }
304:
305: return true;
306: }
307:
308: /**
309: * Verifies if this PIN can be used to unblock other PINs.
310: * @return true if this PIN can be used to unblock other PINs.
311: */
312: public boolean isUnblockingPIN() {
313: return (pinFlags & FLAG_UNBLOCKING_PIN) != 0;
314: }
315:
316: /**
317: * Transforms string entered by user according to PIN attributes.
318: * @param s the value enterd by user.
319: * @return converted and padded PIN value.
320: */
321: public byte[] transform(String s) {
322:
323: if (s.length() < minLength) {
324: return null;
325: }
326:
327: byte[] data = null;
328:
329: if (pinType == TYPE_UTF) {
330:
331: if ((pinFlags & FLAG_CASE_SENSITIVE) == 0) {
332: s = s.toUpperCase(); // locale?
333: }
334:
335: data = Utils.stringToBytes(s);
336:
337: if (data.length > getMaxLength()) {
338: return null;
339: }
340:
341: } else {
342:
343: byte[] tmp = new byte[s.length()];
344: for (int i = 0; i < tmp.length; i++) {
345: tmp[i] = (byte) (s.charAt(i));
346: }
347:
348: if (pinType == TYPE_ASCII || pinType == TYPE_ISO) {
349: data = tmp;
350: } else {
351: if (pinType == TYPE_HN) {
352: data = tmp;
353: for (int i = 0; i < data.length; i++) {
354: data[i] = (byte) (0xf0 | (data[i] - 0x30));
355: }
356: } else { // type == TYPE_BCD
357:
358: data = new byte[(tmp.length + 1) / 2];
359:
360: for (int i = 0; i < data.length; i++) {
361:
362: int l = i * 2;
363: int b1 = tmp[l] - 0x30;
364: int b2;
365: if (l + 1 == tmp.length) {
366: b2 = padChar;
367: } else {
368: b2 = tmp[l + 1] - 0x30;
369: }
370: data[i] = (byte) ((b1 << 4) | (b2 & 0xf));
371: }
372:
373: }
374: }
375: }
376:
377: if (((pinFlags & FLAG_NEEDS_PADDING) == 0)
378: || (data.length == storedLength)) {
379: return data;
380: }
381:
382: byte[] r = new byte[storedLength];
383: System.arraycopy(data, 0, r, 0, data.length);
384: for (int i = data.length; i < storedLength; i++) {
385: r[i] = (byte) padChar;
386: }
387:
388: return r;
389: }
390: }
|