001: /*_############################################################################
002: _##
003: _## SNMP4J-Agent - VacmMIB.java
004: _##
005: _## Copyright (C) 2005-2007 Frank Fock (SNMP4J.org)
006: _##
007: _## Licensed under the Apache License, Version 2.0 (the "License");
008: _## you may not use this file except in compliance with the License.
009: _## You may obtain a copy of the License at
010: _##
011: _## http://www.apache.org/licenses/LICENSE-2.0
012: _##
013: _## Unless required by applicable law or agreed to in writing, software
014: _## distributed under the License is distributed on an "AS IS" BASIS,
015: _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: _## See the License for the specific language governing permissions and
017: _## limitations under the License.
018: _##
019: _##########################################################################*/
020:
021: package org.snmp4j.agent.mo.snmp;
022:
023: import java.util.*;
024:
025: import org.snmp4j.log.*;
026: import org.snmp4j.agent.*;
027: import org.snmp4j.agent.mo.*;
028: import org.snmp4j.agent.mo.util.*;
029: import org.snmp4j.agent.security.*;
030: import org.snmp4j.security.*;
031: import org.snmp4j.smi.*;
032:
033: /**
034: * This concrete implementation of the SNMP-VIEW-BASED-ACM-MIB (RFC 3415).
035: * The configuration of the view access model can be changed programatically
036: * (see {@link MutableVACM}) or via SNMP but an initial configuration must be
037: * created programatically in order to allow any access to the agent via SNMP.
038: *
039: * @author Frank Fock
040: * @version 1.0
041: */
042: public class VacmMIB implements MOGroup, MutableVACM {
043:
044: private static final LogAdapter logger = LogFactory
045: .getLogger(VacmMIB.class);
046:
047: private static final OID vacmContextEntryOID = new OID(new int[] {
048: 1, 3, 6, 1, 6, 3, 16, 1, 1, 1 });
049:
050: private static final int colVacmGroupName = 3;
051: private static final int colVacmSecurityToGroupStorageType = 4;
052: private static final int colVacmSecurityToGroupRowStatus = 5;
053:
054: private static final int idxVacmGroupName = 0;
055: private static final int idxVacmSecurityToGroupStorageType = 1;
056: private static final int idxVacmSecurityToGroupRowStatus = 2;
057:
058: private static final OID vacmSecurityToGroupEntryOID = new OID(
059: new int[] { 1, 3, 6, 1, 6, 3, 16, 1, 2, 1 });
060:
061: private static final int colVacmAccessContextMatch = 4;
062: private static final int colVacmAccessReadViewName = 5;
063: private static final int colVacmAccessWriteViewName = 6;
064: private static final int colVacmAccessNotifyViewName = 7;
065: private static final int colVacmAccessStorageType = 8;
066: private static final int colVacmAccessRowStatus = 9;
067:
068: // private static final int idxVacmAccessGroupName = 0;
069: private static final int idxVacmAccessContextPrefix = 1;
070: private static final int idxVacmAccessSecurityModel = 2;
071: private static final int idxVacmAccessSecurityLevel = 3;
072: private static final int idxVacmAccessContextMatch = 0;
073: private static final int idxVacmAccessReadViewName = 1;
074: private static final int idxVacmAccessWriteViewName = 2;
075: private static final int idxVacmAccessNotifyViewName = 3;
076: private static final int idxVacmAccessStorageType = 4;
077: private static final int idxVacmAccessRowStatus = 5;
078:
079: private static final OID vacmAccessEntryOID = new OID(new int[] {
080: 1, 3, 6, 1, 6, 3, 16, 1, 4, 1 });
081:
082: public static final int vacmExactMatch = MutableVACM.VACM_MATCH_EXACT;
083: public static final int vacmPrefixMatch = MutableVACM.VACM_MATCH_PREFIX;
084:
085: private static final OID vacmViewSpinLockOID = new OID(new int[] {
086: 1, 3, 6, 1, 6, 3, 16, 1, 5, 1, 0 });
087:
088: private static final int colVacmViewTreeFamilyMask = 3;
089: private static final int colVacmViewTreeFamilyType = 4;
090: private static final int colVacmViewTreeFamilyStorageType = 5;
091: private static final int colVacmViewTreeFamilyRowStatus = 6;
092:
093: // private static final int idxVacmViewTreeViewName = 0;
094: private static final int idxVacmViewTreeSubtree = 1;
095:
096: private static final int idxVacmViewTreeFamilyMask = 0;
097: private static final int idxVacmViewTreeFamilyType = 1;
098: private static final int idxVacmViewTreeFamilyStorageType = 2;
099: private static final int idxVacmViewTreeFamilyRowStatus = 3;
100:
101: private static final OID vacmViewTreeFamilyEntryOID = new OID(
102: new int[] { 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1 });
103:
104: public static final int vacmViewIncluded = MutableVACM.VACM_VIEW_INCLUDED;
105: public static final int vacmViewExcluded = MutableVACM.VACM_VIEW_EXCLUDED;
106:
107: private static final int[] vacmViewTreeFamilyTypeValues = {
108: vacmViewIncluded, vacmViewExcluded };
109:
110: private static MOTableSubIndex[] vacmViewTreeFamilyIndexes = new MOTableSubIndex[] {
111: new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32),
112: new MOTableSubIndex(SMIConstants.SYNTAX_OBJECT_IDENTIFIER,
113: 0, 96) };
114:
115: private static MOTableIndex vacmViewTreeFamilyIndex = new MOTableIndex(
116: vacmViewTreeFamilyIndexes);
117:
118: private static MOTableSubIndex[] vacmAccessIndexes = new MOTableSubIndex[] {
119: new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 1, 32),
120: new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING, 0, 32),
121: new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1),
122: new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1) };
123:
124: private static MOTableIndex vacmAccessIndex = new MOTableIndex(
125: vacmAccessIndexes) {
126: public boolean isValidIndex(OID index) {
127: boolean ok = super .isValidIndex(index);
128: if (ok) {
129: SecurityModels secModels = SecurityModels.getInstance();
130: Integer32 secModel = new Integer32(index.get(index
131: .size() - 2));
132: if ((secModel.getValue() != SecurityModel.SECURITY_MODEL_ANY)
133: && (secModels.getSecurityModel(secModel) == null)) {
134: return false;
135: }
136: int secLevel = index.get(index.size() - 1);
137: if ((secLevel < 1) || (secLevel > 3)) {
138: return false;
139: }
140: }
141: return ok;
142: }
143: };
144:
145: private MOServer server;
146:
147: private DefaultMOTable vacmContextTable;
148:
149: private DefaultMOTable vacmSecurityToGroupTable;
150: private DefaultMOMutableTableModel vacmSecurityToGroupTableModel;
151:
152: private DefaultMOTable vacmAccessTable;
153: private DefaultMOMutableTableModel vacmAccessTableModel;
154:
155: private TestAndIncr vacmViewSpinLock;
156:
157: private DefaultMOTable vacmViewTreeFamilyTable;
158: private DefaultMOMutableTableModel vacmViewTreeFamilyTableModel;
159:
160: public VacmMIB(MOServer server) {
161: this .server = server;
162: createVacmContextTable();
163: createVacmSecuritToGroupTable();
164: createVacmAccessTable();
165: createVacmViewTreeFamilyTable();
166: vacmViewSpinLock = new TestAndIncr(vacmViewSpinLockOID);
167: }
168:
169: public void registerMOs(MOServer server, OctetString context)
170: throws DuplicateRegistrationException {
171: server.register(vacmContextTable, context);
172: server.register(vacmSecurityToGroupTable, context);
173: server.register(vacmAccessTable, context);
174: server.register(vacmViewSpinLock, context);
175: server.register(vacmViewTreeFamilyTable, context);
176: }
177:
178: private void createVacmContextTable() {
179: MOTableSubIndex[] vacmContextTableIndexes = new MOTableSubIndex[] { new MOTableSubIndex(
180: SMIConstants.SYNTAX_OCTET_STRING, 0, 32) };
181: MOTableIndex vacmContextTableIndex = new MOTableIndex(
182: vacmContextTableIndexes);
183: MOColumn[] vacmContextColumns = new MOColumn[] { new MOColumn(
184: 1, SMIConstants.SYNTAX_OCTET_STRING,
185: MOAccessImpl.ACCESS_READ_ONLY) };
186:
187: this .vacmContextTable = new DefaultMOTable(vacmContextEntryOID,
188: vacmContextTableIndex, vacmContextColumns);
189: this .vacmContextTable.setVolatile(true);
190: this .vacmContextTable.setModel(new VacmContextTableModel());
191: }
192:
193: private void createVacmSecuritToGroupTable() {
194: MOTableSubIndex[] vacmSecurityToGroupIndexes = new MOTableSubIndex[] {
195: new MOTableSubIndex(SMIConstants.SYNTAX_INTEGER, 1, 1),
196: new MOTableSubIndex(SMIConstants.SYNTAX_OCTET_STRING,
197: 1, 32) };
198:
199: MOTableIndex vacmSecurityToGroupIndex = new MOTableIndex(
200: vacmSecurityToGroupIndexes) {
201: public boolean isValidIndex(OID index) {
202: boolean ok = super .isValidIndex(index);
203: if (ok) {
204: SecurityModels secModels = SecurityModels
205: .getInstance();
206: if (secModels.getSecurityModel(new Integer32(index
207: .get(0))) == null) {
208: return false;
209: }
210: }
211: return ok;
212: }
213: };
214:
215: MOColumn[] vacmSecurityToGroupColumns = new MOColumn[] {
216: new SnmpAdminString(colVacmGroupName,
217: MOAccessImpl.ACCESS_READ_CREATE, null, true, 1,
218: 32),
219: new StorageType(colVacmSecurityToGroupStorageType,
220: MOAccessImpl.ACCESS_READ_CREATE, new Integer32(
221: StorageType.nonVolatile), true),
222: new RowStatus(colVacmSecurityToGroupRowStatus) };
223:
224: this .vacmSecurityToGroupTable = new DefaultMOTable(
225: vacmSecurityToGroupEntryOID, vacmSecurityToGroupIndex,
226: vacmSecurityToGroupColumns);
227: vacmSecurityToGroupTableModel = new DefaultMOMutableTableModel();
228: vacmSecurityToGroupTableModel
229: .setRowFactory(new DefaultMOMutableRow2PCFactory());
230: this .vacmSecurityToGroupTable
231: .setModel(vacmSecurityToGroupTableModel);
232: }
233:
234: private void createVacmAccessTable() {
235: MOColumn[] vacmAccessColumns = new MOColumn[] {
236: new Enumerated(colVacmAccessContextMatch,
237: MOAccessImpl.ACCESS_READ_CREATE, new Integer32(
238: vacmExactMatch), true, new int[] {
239: vacmExactMatch, vacmPrefixMatch }),
240: new SnmpAdminString(colVacmAccessReadViewName,
241: MOAccessImpl.ACCESS_READ_CREATE,
242: new OctetString(), true, 0, 32),
243: new SnmpAdminString(colVacmAccessWriteViewName,
244: MOAccessImpl.ACCESS_READ_CREATE,
245: new OctetString(), true, 0, 32),
246: new SnmpAdminString(colVacmAccessNotifyViewName,
247: MOAccessImpl.ACCESS_READ_CREATE,
248: new OctetString(), true, 0, 32),
249: new StorageType(colVacmAccessStorageType,
250: MOAccessImpl.ACCESS_READ_CREATE, new Integer32(
251: StorageType.nonVolatile), true),
252: new RowStatus(colVacmAccessRowStatus) };
253:
254: vacmAccessTable = new DefaultMOTable(vacmAccessEntryOID,
255: vacmAccessIndex, vacmAccessColumns);
256: vacmAccessTableModel = new DefaultMOMutableTableModel();
257: vacmAccessTableModel
258: .setRowFactory(new DefaultMOMutableRow2PCFactory());
259: vacmAccessTable.setModel(vacmAccessTableModel);
260: }
261:
262: private void createVacmViewTreeFamilyTable() {
263: MOColumn[] vacmViewTreeFamilyColumns = new MOColumn[] {
264: new SnmpAdminString(colVacmViewTreeFamilyMask,
265: MOAccessImpl.ACCESS_READ_CREATE,
266: new OctetString(), true, 0, 16),
267: new Enumerated(colVacmViewTreeFamilyType,
268: MOAccessImpl.ACCESS_READ_CREATE, new Integer32(
269: vacmViewIncluded), true,
270: vacmViewTreeFamilyTypeValues),
271: new StorageType(colVacmViewTreeFamilyStorageType,
272: MOAccessImpl.ACCESS_READ_CREATE, new Integer32(
273: StorageType.nonVolatile), true),
274: new RowStatus(colVacmViewTreeFamilyRowStatus) };
275:
276: vacmViewTreeFamilyTable = new DefaultMOTable(
277: vacmViewTreeFamilyEntryOID, vacmViewTreeFamilyIndex,
278: vacmViewTreeFamilyColumns);
279: vacmViewTreeFamilyTableModel = new DefaultMOMutableTableModel();
280: vacmViewTreeFamilyTableModel
281: .setRowFactory(new DefaultMOMutableRow2PCFactory());
282: vacmViewTreeFamilyTable.setModel(vacmViewTreeFamilyTableModel);
283: }
284:
285: public void unregisterMOs(MOServer server, OctetString context) {
286: server.unregister(this .vacmContextTable, context);
287: server.unregister(this .vacmSecurityToGroupTable, context);
288: server.unregister(this .vacmAccessTable, context);
289: server.unregister(vacmViewSpinLock, context);
290: server.unregister(vacmViewTreeFamilyTable, context);
291: }
292:
293: public int isAccessAllowed(OctetString context,
294: OctetString securityName, int securityModel,
295: int securityLevel, int viewType, OID oid) {
296: if (logger.isDebugEnabled()) {
297: logger.debug("VACM access requested for context=" + context
298: + ", securityName=" + securityName
299: + ", securityModel=" + securityModel
300: + ", securityLevel=" + securityLevel
301: + ", viewType=" + viewType + ", OID=" + oid);
302: }
303: if (!server.isContextSupported(context)) {
304: if (logger.isDebugEnabled()) {
305: logger.debug("Context '" + context
306: + "' ist not supported");
307: }
308: return VACM.VACM_NO_SUCH_CONTEXT;
309: }
310: OctetString groupName = getGroupName(securityName,
311: securityModel);
312: if (groupName == null) {
313: if (logger.isDebugEnabled()) {
314: logger.debug("No group name for securityName="
315: + securityName + " and securityModel="
316: + securityModel);
317: }
318: return VACM.VACM_NO_GROUP_NAME;
319: }
320: OctetString viewName = getViewNameByGroup(context,
321: securityModel, securityLevel, viewType, groupName);
322: if (viewName == null) {
323: return VACM.VACM_NO_ACCESS_ENTRY;
324: }
325: if (viewName.length() == 0) {
326: return VACM.VACM_NO_SUCH_VIEW;
327: }
328: return isAccessAllowed(viewName, oid);
329: }
330:
331: public OctetString getViewName(OctetString context,
332: OctetString securityName, int securityModel,
333: int securityLevel, int viewType) {
334: OctetString groupName = getGroupName(securityName,
335: securityModel);
336: if (groupName == null) {
337: return null;
338: }
339: return getViewNameByGroup(context, securityModel,
340: securityLevel, viewType, groupName);
341: }
342:
343: private OctetString getViewNameByGroup(OctetString context,
344: int securityModel, int securityLevel, int viewType,
345: OctetString groupName) {
346: List accessEntries = getAccessEntries(groupName);
347:
348: if (logger.isDebugEnabled()) {
349: logger.debug("Got views " + accessEntries
350: + " for group name '" + groupName + "'");
351: }
352:
353: MOTableRow possibleMatch = null;
354: boolean foundExactContextMatch = false;
355: boolean foundMatchedSecModel = false;
356: int foundContextPrefixLength = 0;
357: int foundSecLevel = 0;
358:
359: for (Iterator it = accessEntries.iterator(); it.hasNext();) {
360: MOTableRow row = (MOTableRow) it.next();
361: if (((Integer32) row.getValue(idxVacmAccessRowStatus))
362: .getValue() != RowStatus.active) {
363: continue;
364: }
365: Variable[] indexValues = vacmAccessIndex.getIndexValues(row
366: .getIndex());
367: OctetString rowContext = (OctetString) indexValues[idxVacmAccessContextPrefix];
368: int rowSecurityModel = ((Integer32) indexValues[idxVacmAccessSecurityModel])
369: .getValue();
370: int rowSecurityLevel = ((Integer32) indexValues[idxVacmAccessSecurityLevel])
371: .getValue();
372: int rowContextMatch = ((Integer32) row
373: .getValue(idxVacmAccessContextMatch)).getValue();
374: boolean exactContextMatch = rowContext.equals(context);
375: boolean prefixMatch = (!exactContextMatch)
376: && ((rowContextMatch == vacmPrefixMatch) && (context
377: .startsWith(rowContext)));
378: boolean matchSecModel = (rowSecurityModel == securityModel);
379: boolean matchSecLevel = (rowSecurityLevel <= securityLevel);
380: if ((exactContextMatch || prefixMatch)
381: && ((matchSecModel) || (rowSecurityModel == SecurityModel.SECURITY_MODEL_ANY))
382: && matchSecLevel) {
383: // check better match
384: if ((possibleMatch == null)
385: || (((!foundMatchedSecModel) && (matchSecModel)) || (((!foundMatchedSecModel) || (matchSecModel))
386: && ((!foundExactContextMatch) && (exactContextMatch)) || ((((!foundExactContextMatch) || (exactContextMatch)) && (foundContextPrefixLength < rowContext
387: .length())) || ((foundContextPrefixLength == rowContext
388: .length()) && (foundSecLevel < rowSecurityLevel)))))) {
389: possibleMatch = row;
390: foundExactContextMatch = exactContextMatch;
391: if (prefixMatch) {
392: foundContextPrefixLength = rowContext.length();
393: }
394: foundMatchedSecModel = matchSecModel;
395: foundSecLevel = securityLevel;
396: }
397: }
398: }
399: if (possibleMatch != null) {
400: OctetString viewName = null;
401: switch (viewType) {
402: case VACM.VIEW_READ: {
403: viewName = (OctetString) possibleMatch
404: .getValue(idxVacmAccessReadViewName);
405: break;
406: }
407: case VACM.VIEW_WRITE: {
408: viewName = (OctetString) possibleMatch
409: .getValue(idxVacmAccessWriteViewName);
410: break;
411: }
412: case VACM.VIEW_NOTIFY: {
413: viewName = (OctetString) possibleMatch
414: .getValue(idxVacmAccessNotifyViewName);
415: break;
416: }
417: }
418: if (logger.isDebugEnabled()) {
419: logger.debug("Matching view found for group name '"
420: + groupName + "' is '" + viewName + "'");
421: }
422: return viewName;
423: }
424: return null;
425: }
426:
427: private OctetString getGroupName(OctetString securityName,
428: int securityModel) {
429: OID index = new OID();
430: index.append(securityModel);
431: index.append(securityName.toSubIndex(false));
432: MOTableRow row = vacmSecurityToGroupTableModel.getRow(index);
433: if (row != null) {
434: OctetString groupName = (OctetString) row
435: .getValue(idxVacmGroupName);
436: if (logger.isDebugEnabled()) {
437: logger.debug("Found group name '" + groupName
438: + "' for secName '" + securityName
439: + " and secModel " + securityModel);
440: }
441: return groupName;
442: }
443: return null;
444: }
445:
446: public int isAccessAllowed(OctetString viewName, OID oid) {
447: List views = getViews(viewName);
448: if (views.size() == 0) {
449: if (logger.isDebugEnabled()) {
450: logger.debug("No view tree family entry for view '"
451: + viewName + "'");
452: }
453: return VACM.VACM_NO_SUCH_VIEW;
454: }
455: // iterate from back to forth because the views list must be ordered by
456: // subtree length (view name is the same for all entries) which is the
457: // criteria to find the appropritate view access entry.
458: for (int v = views.size() - 1; v >= 0; v--) {
459: MOTableRow row = (MOTableRow) views.get(v);
460: if (((Integer32) row
461: .getValue(idxVacmViewTreeFamilyRowStatus))
462: .getValue() != RowStatus.active) {
463: // only active rows are relevant
464: continue;
465: }
466: OID index = row.getIndex();
467: Variable[] indexValues = vacmViewTreeFamilyIndex
468: .getIndexValues(index);
469: OID subtree = (OID) indexValues[idxVacmViewTreeSubtree];
470: if (oid.size() < subtree.size()) {
471: // no match
472: continue;
473: }
474: OctetString mask = (OctetString) row
475: .getValue(idxVacmViewTreeFamilyMask);
476: boolean match = true;
477: for (int i = 0; i < subtree.size(); i++) {
478: if ((subtree.get(i) != oid.get(i)) && isBitSet(i, mask)) {
479: match = false;
480: break;
481: }
482: }
483: if (match) {
484: // we found the matching entry
485: if (((Integer32) row
486: .getValue(idxVacmViewTreeFamilyType))
487: .getValue() == vacmViewIncluded) {
488: if (logger.isDebugEnabled()) {
489: logger.debug("Access allowed for view '"
490: + viewName + "' by subtree " + subtree
491: + " for OID " + oid);
492: }
493: return VACM.VACM_OK;
494: } else {
495: // excluded
496: if (logger.isDebugEnabled()) {
497: logger.debug("Access denied for view '"
498: + viewName + "' by subtree " + subtree
499: + " for OID " + oid);
500: }
501: return VACM.VACM_NOT_IN_VIEW;
502: }
503: }
504: }
505: return VACM.VACM_NOT_IN_VIEW;
506: }
507:
508: /**
509: * Adds a security model and name to group name mapping to this VACM. Any
510: * already existing mapping for the security name and model will be silently
511: * replaced.
512: * @param securityModel
513: * the security model.
514: * @param securityName
515: * the security name.
516: * @param groupName
517: * the group name.
518: * @param storageType
519: * the storage type for the new entry.
520: */
521: public void addGroup(int securityModel, OctetString securityName,
522: OctetString groupName, int storageType) {
523: OID index = createGroupIndex(securityModel, securityName);
524: Variable[] values = new Variable[vacmSecurityToGroupTable
525: .getColumnCount()];
526: values[idxVacmGroupName] = groupName;
527: values[idxVacmSecurityToGroupStorageType] = new Integer32(
528: storageType);
529: values[idxVacmSecurityToGroupRowStatus] = new Integer32(
530: RowStatus.active);
531: MOTableRow row = vacmSecurityToGroupTable.createRow(index,
532: values);
533: vacmSecurityToGroupTableModel.addRow(row);
534: }
535:
536: private static OID createGroupIndex(int securityModel,
537: OctetString securityName) {
538: OID index = new OID();
539: index.append(securityModel);
540: index.append(securityName.toSubIndex(false));
541: return index;
542: }
543:
544: /**
545: * Removes a security model and name to group name mapping from this VACM.
546: * @param securityModel
547: * the security model.
548: * @param securityName
549: * the security name.
550: * @return
551: * <code>true</code> when the entry has been removed or <code>false</code>
552: * if such a mapping could not be found.
553: */
554: public boolean removeGroup(int securityModel,
555: OctetString securityName) {
556: OID index = createGroupIndex(securityModel, securityName);
557: return (vacmSecurityToGroupTableModel.removeRow(index) != null);
558: }
559:
560: /**
561: * Adds an access entry to this VACM and thus adds access rights for a group.
562: * @param groupName
563: * the group for which access rights are to be added.
564: * @param contextPrefix
565: * the context or context prefix.
566: * @param securityModel
567: * the security model
568: * @param securityLevel
569: * the security level
570: * @param match
571: * indicates whether exact context match ({@link #vacmExactMatch})
572: * or prefix context match ({@link #vacmPrefixMatch}) should
573: * be used by the new entry.
574: * @param readView
575: * the view name for read access (use a zero length OctetString to disable
576: * access).
577: * @param writeView
578: * the view name for write access (use a zero length OctetString to disable
579: * access).
580: * @param notifyView
581: * the view name for notify access (use a zero length OctetString to
582: * disable access).
583: * @param storageType
584: * the {@link StorageType} for this access entry.
585: */
586: public void addAccess(OctetString groupName,
587: OctetString contextPrefix, int securityModel,
588: int securityLevel, int match, OctetString readView,
589: OctetString writeView, OctetString notifyView,
590: int storageType) {
591: OID index = createAccessIndex(groupName, contextPrefix,
592: securityModel, securityLevel);
593: Variable[] values = new Variable[vacmAccessTable
594: .getColumnCount()];
595: values[idxVacmAccessContextMatch] = new Integer32(match);
596: values[idxVacmAccessReadViewName] = readView;
597: values[idxVacmAccessWriteViewName] = writeView;
598: values[idxVacmAccessNotifyViewName] = notifyView;
599: values[idxVacmAccessStorageType] = new Integer32(storageType);
600: values[idxVacmAccessRowStatus] = new Integer32(RowStatus.active);
601: vacmAccessTableModel.addRow(vacmAccessTableModel.createRow(
602: index, values));
603: }
604:
605: /**
606: * Removes an access entry from this VACM.
607: * @param groupName
608: * the group for which access rights are to be added.
609: * @param contextPrefix
610: * the context or context prefix.
611: * @param securityModel
612: * the security model
613: * @param securityLevel
614: * the security level
615: * @return
616: * <code>true</code> when the entry has been removed or <code>false</code>
617: * if no such entry could be found.
618: */
619: public boolean removeAccess(OctetString groupName,
620: OctetString contextPrefix, int securityModel,
621: int securityLevel) {
622: OID index = createAccessIndex(groupName, contextPrefix,
623: securityModel, securityLevel);
624: return (vacmAccessTableModel.removeRow(index) != null);
625: }
626:
627: private static OID createAccessIndex(OctetString groupName,
628: OctetString contextPrefix, int securityModel,
629: int securityLevel) {
630: OID index = groupName.toSubIndex(false);
631: index.append(contextPrefix.toSubIndex(false));
632: index.append(securityModel);
633: index.append(securityLevel);
634: return index;
635: }
636:
637: /**
638: * Adds a new view to this VACM. An already existing entry with the same
639: * view name and subtree OID will be replaced silently.
640: * @param viewName
641: * the view name.
642: * @param subtree
643: * the subtree OID.
644: * @param mask
645: * the bit mask which, in combination with <code>subtree</code>,
646: * defines a family of view subtrees.
647: * @param type
648: * indicates whether the view defined by <code>subtree</code> and
649: * <code>mask</code> is included ({@link #vacmViewIncluded}) or excluded
650: * (@link #vacmViewExcluded}) from the MIB view.
651: * @param storageType
652: * the {@link StorageType} for this access entry.
653: */
654: public void addViewTreeFamily(OctetString viewName, OID subtree,
655: OctetString mask, int type, int storageType) {
656: OID index = createViewIndex(viewName, subtree);
657: Variable[] values = new Variable[vacmViewTreeFamilyTable
658: .getColumnCount()];
659: values[idxVacmViewTreeFamilyMask] = mask;
660: values[idxVacmViewTreeFamilyType] = new Integer32(type);
661: values[idxVacmViewTreeFamilyStorageType] = new Integer32(
662: storageType);
663: values[idxVacmViewTreeFamilyRowStatus] = new Integer32(
664: RowStatus.active);
665: MOTableRow row = vacmViewTreeFamilyTableModel.createRow(index,
666: values);
667: vacmViewTreeFamilyTableModel.addRow(row);
668: }
669:
670: /**
671: * Removes a view tree family from this VACM.
672: * @param viewName
673: * the view name.
674: * @param subtree
675: * the subtree OID.
676: * @return
677: * <code>true</code> when the entry has been removed or <code>false</code>
678: * if no such entry could be found.
679: */
680: public boolean removeViewTreeFamily(OctetString viewName,
681: OID subtree) {
682: OID index = createViewIndex(viewName, subtree);
683: return (vacmViewTreeFamilyTableModel.removeRow(index) != null);
684: }
685:
686: private static OID createViewIndex(OctetString viewName, OID subtree) {
687: OID index = viewName.toSubIndex(false);
688: index.append(subtree.toSubIndex(false));
689: return index;
690: }
691:
692: /**
693: * Checks whether bit n of the supplied OctetString is set or not.
694: * @param n
695: * denotes the bit to check starting from zero.
696: * @param os OctetString
697: * @return boolean
698: */
699: private static boolean isBitSet(final int n, final OctetString os) {
700: if (os.length() <= n / 8) {
701: return true;
702: }
703: return (os.get(n / 8) & (0x01 << (7 - (n % 8)))) > 0;
704: }
705:
706: private List getAccessEntries(OctetString groupName) {
707: OctetString upperBound = new OctetString(groupName);
708: byte last = -1;
709: if (upperBound.length() > 0) {
710: last = upperBound.get(upperBound.length() - 1);
711: }
712: if (last == -1) {
713: upperBound.append((byte) 0);
714: } else {
715: upperBound.set(upperBound.length() - 1, (byte) (last + 1));
716: }
717: OID lowerOID = groupName.toSubIndex(false);
718: OID upperOID = upperBound.toSubIndex(false);
719: List views = vacmAccessTableModel.getRows(lowerOID, upperOID);
720: return views;
721: }
722:
723: private List getViews(OctetString viewName) {
724: if (viewName.length() == 0) {
725: return Collections.EMPTY_LIST;
726: }
727: OctetString upperBound = new OctetString(viewName);
728: byte last = upperBound.get(upperBound.length() - 1);
729: if (last == -1) {
730: upperBound.append((byte) 0);
731: } else {
732: upperBound.set(upperBound.length() - 1, (byte) (last + 1));
733: }
734: OID lowerOID = viewName.toSubIndex(false);
735: OID upperOID = upperBound.toSubIndex(false);
736: List views = vacmViewTreeFamilyTableModel.getRows(lowerOID,
737: upperOID);
738: return views;
739: }
740:
741: public static class VacmContextIterator implements Iterator {
742:
743: private int index = 0;
744: private OctetString[] contexts;
745:
746: VacmContextIterator(OctetString[] contexts, int offset) {
747: this .contexts = contexts;
748: this .index = offset;
749: }
750:
751: public void remove() {
752: throw new UnsupportedOperationException();
753: }
754:
755: public boolean hasNext() {
756: return (index < contexts.length);
757: }
758:
759: public Object next() {
760: if (index < contexts.length) {
761: OctetString context = contexts[index++];
762: DefaultMOTableRow row = new DefaultMOTableRow(context
763: .toSubIndex(false), new Variable[] { context });
764: return row;
765: }
766: throw new NoSuchElementException();
767: }
768:
769: }
770:
771: private static OctetString getContextFromIndex(OID index) {
772: if (index.size() > 0) {
773: return new OctetString(index.toByteArray(), 1,
774: index.size() - 1);
775: }
776: return new OctetString();
777: }
778:
779: class VacmContextTableModel implements MOTableModel {
780:
781: public int getColumnCount() {
782: return 1;
783: }
784:
785: public int getRowCount() {
786: return server.getContexts().length;
787: }
788:
789: public boolean containsRow(OID index) {
790: return server
791: .isContextSupported(getContextFromIndex(index));
792: }
793:
794: public MOTableRow getRow(OID index) {
795: if (index == null) {
796: return null;
797: }
798: OctetString context = getContextFromIndex(index);
799: if (server.isContextSupported(context)) {
800: DefaultMOTableRow row = new DefaultMOTableRow(index,
801: new Variable[] { context });
802: return row;
803: }
804: return null;
805: }
806:
807: public Iterator iterator() {
808: return tailIterator(new OID());
809: }
810:
811: public Iterator tailIterator(OID lowerBound) {
812: OctetString[] contexts = server.getContexts();
813: if (contexts == null) {
814: return new VacmContextIterator(new OctetString[0], 0);
815: }
816: Arrays.sort(contexts,
817: new LexicographicOctetStringComparator());
818: int offset = 0;
819: if (lowerBound != null) {
820: offset = Arrays.binarySearch(contexts,
821: getContextFromIndex(lowerBound));
822: }
823: if (offset < 0) {
824: offset = -(offset + 1);
825: }
826: return new VacmContextIterator(contexts, offset);
827: }
828:
829: public OID lastIndex() {
830: OctetString[] contexts = server.getContexts();
831: if ((contexts == null) || (contexts.length == 0)) {
832: return null;
833: }
834: Arrays.sort(contexts,
835: new LexicographicOctetStringComparator());
836: return contexts[contexts.length - 1].toSubIndex(false);
837: }
838:
839: public OID firstIndex() {
840: OctetString[] contexts = server.getContexts();
841: if ((contexts == null) || (contexts.length == 0)) {
842: return null;
843: }
844: Arrays.sort(contexts,
845: new LexicographicOctetStringComparator());
846: return contexts[0].toSubIndex(false);
847: }
848:
849: public MOTableRow firstRow() {
850: return getRow(firstIndex());
851: }
852:
853: public MOTableRow lastRow() {
854: return getRow(lastIndex());
855: }
856: }
857:
858: }
|