diff options
Diffstat (limited to 'agent/mibgroup/mibII/vacm_vars.c')
-rw-r--r-- | agent/mibgroup/mibII/vacm_vars.c | 1843 |
1 files changed, 1843 insertions, 0 deletions
diff --git a/agent/mibgroup/mibII/vacm_vars.c b/agent/mibgroup/mibII/vacm_vars.c new file mode 100644 index 0000000..85cef94 --- /dev/null +++ b/agent/mibgroup/mibII/vacm_vars.c @@ -0,0 +1,1843 @@ +/* + * SNMPv3 View-based Access Control Model + */ +/* Portions of this file are subject to the following copyright(s). See + * the Net-SNMP's COPYING file for more details and other copyrights + * that may apply: + */ +/* + * Portions of this file are copyrighted by: + * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms specified in the COPYING file + * distributed with the Net-SNMP package. + */ + +#include <net-snmp/net-snmp-config.h> + +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif +#if HAVE_MALLOC_H +#include <malloc.h> +#endif +#include <ctype.h> +#include <sys/types.h> +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#if HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include <net-snmp/agent/agent_callbacks.h> +#include <net-snmp/agent/sysORTable.h> +#include "vacm_vars.h" +#include "util_funcs/header_generic.h" + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +static unsigned int vacmViewSpinLock = 0; + +void +init_vacm_vars(void) +{ + + oid reg[] = { SNMP_OID_SNMPMODULES, 16, 2, 2, 1 }; + +#define PRIVRW (NETSNMP_SNMPV2ANY | 0x5000) + + struct variable1 vacm_sec2group[] = { + {SECURITYGROUP, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE, + var_vacm_sec2group, 1, {3}}, + {SECURITYSTORAGE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_sec2group, 1, {4}}, + {SECURITYSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_sec2group, 1, {5}}, + }; + + struct variable1 vacm_access[] = { + {ACCESSMATCH, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_access, 1, {4}}, + {ACCESSREAD, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE, + var_vacm_access, 1, {5}}, + {ACCESSWRITE, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE, + var_vacm_access, 1, {6}}, + {ACCESSNOTIFY, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE, + var_vacm_access, 1, {7}}, + {ACCESSSTORAGE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_access, 1, {8}}, + {ACCESSSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_access, 1, {9}}, + }; + + struct variable3 vacm_view[] = { + {VACMVIEWSPINLOCK, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_view, 1, {1}}, + {VIEWMASK, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE, + var_vacm_view, 3, {2, 1, 3}}, + {VIEWTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_view, 3, {2, 1, 4}}, + {VIEWSTORAGE, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_view, 3, {2, 1, 5}}, + {VIEWSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_vacm_view, 3, {2, 1, 6}}, + }; + + /* + * Define the OID pointer to the top of the mib tree that we're + * registering underneath + */ + oid vacm_sec2group_oid[] = { OID_VACMGROUPENTRY }; + oid vacm_access_oid[] = { OID_VACMACCESSENTRY }; + oid vacm_view_oid[] = { OID_VACMMIBVIEWS }; + + /* + * we need to be called back later + */ + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, + store_vacm, NULL); + + /* + * register ourselves with the agent to handle our mib tree + */ + REGISTER_MIB("mibII/vacm:sec2group", vacm_sec2group, variable1, + vacm_sec2group_oid); + REGISTER_MIB("mibII/vacm:access", vacm_access, variable1, + vacm_access_oid); + REGISTER_MIB("mibII/vacm:view", vacm_view, variable3, vacm_view_oid); + + REGISTER_SYSOR_ENTRY(reg, "View-based Access Control Model for SNMP."); +} + + + +u_char * +var_vacm_sec2group(struct variable * vp, + oid * name, + size_t * length, + int exact, + size_t * var_len, WriteMethod ** write_method) +{ + struct vacm_groupEntry *gp; + oid *groupSubtree; + ssize_t groupSubtreeLen; + int secmodel; + char secname[VACMSTRINGLEN], *cp; + + /* + * Set up write_method first, in case we return NULL before getting to + * the switch (vp->magic) below. In some of these cases, we still want + * to call the appropriate write_method, if only to have it return the + * appropriate error. + */ + + switch (vp->magic) { +#ifndef NETSNMP_NO_WRITE_SUPPORT + case SECURITYGROUP: + *write_method = write_vacmGroupName; + break; + case SECURITYSTORAGE: + *write_method = write_vacmSecurityToGroupStorageType; + break; + case SECURITYSTATUS: + *write_method = write_vacmSecurityToGroupStatus; + break; +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + default: + *write_method = NULL; + } + + *var_len = 0; /* assume 0 length until found */ + + if (memcmp(name, vp->name, sizeof(oid) * vp->namelen) != 0) { + memcpy(name, vp->name, sizeof(oid) * vp->namelen); + *length = vp->namelen; + } + if (exact) { + if (*length < 13) + return NULL; + + secmodel = name[11]; + groupSubtree = name + 13; + groupSubtreeLen = *length - 13; + if ( name[12] != groupSubtreeLen ) + return NULL; /* Either extra subids, or an incomplete string */ + cp = secname; + while (groupSubtreeLen-- > 0) { + if (*groupSubtree > 255) + return NULL; /* illegal value */ + if (cp - secname > VACM_MAX_STRING) + return NULL; + *cp++ = (char) *groupSubtree++; + } + *cp = 0; + + gp = vacm_getGroupEntry(secmodel, secname); + } else { + secmodel = *length > 11 ? name[11] : 0; + groupSubtree = name + 12; + groupSubtreeLen = *length - 12; + cp = secname; + while (groupSubtreeLen-- > 0) { + if (*groupSubtree > 255) + return NULL; /* illegal value */ + if (cp - secname > VACM_MAX_STRING) + return NULL; + *cp++ = (char) *groupSubtree++; + } + *cp = 0; + vacm_scanGroupInit(); + while ((gp = vacm_scanGroupNext()) != NULL) { + if (gp->securityModel > secmodel || + (gp->securityModel == secmodel + && strcmp(gp->securityName, secname) > 0)) + break; + } + if (gp) { + name[11] = gp->securityModel; + *length = 12; + cp = gp->securityName; + while (*cp) { + name[(*length)++] = *cp++; + } + } + } + + if (gp == NULL) { + return NULL; + } + + *var_len = sizeof(long_return); + switch (vp->magic) { + case SECURITYMODEL: + long_return = gp->securityModel; + return (u_char *) & long_return; + + case SECURITYNAME: + *var_len = gp->securityName[0]; + return (u_char *) & gp->securityName[1]; + + case SECURITYGROUP: + *var_len = strlen(gp->groupName); + return (u_char *) gp->groupName; + + case SECURITYSTORAGE: + long_return = gp->storageType; + return (u_char *) & long_return; + + case SECURITYSTATUS: + long_return = gp->status; + return (u_char *) & long_return; + + default: + break; + } + + return NULL; +} + +u_char * +var_vacm_access(struct variable * vp, + oid * name, + size_t * length, + int exact, size_t * var_len, WriteMethod ** write_method) +{ + struct vacm_accessEntry *gp; + int secmodel, seclevel; + char groupName[VACMSTRINGLEN] = { 0 }; + char contextPrefix[VACMSTRINGLEN] = { 0 }; + oid *op; + unsigned long len, i = 0; + char *cp; + int cmp; + + /* + * Set up write_method first, in case we return NULL before getting to + * the switch (vp->magic) below. In some of these cases, we still want + * to call the appropriate write_method, if only to have it return the + * appropriate error. + */ + + switch (vp->magic) { +#ifndef NETSNMP_NO_WRITE_SUPPORT + case ACCESSMATCH: + *write_method = write_vacmAccessContextMatch; + break; + case ACCESSREAD: + *write_method = write_vacmAccessReadViewName; + break; + case ACCESSWRITE: + *write_method = write_vacmAccessWriteViewName; + break; + case ACCESSNOTIFY: + *write_method = write_vacmAccessNotifyViewName; + break; + case ACCESSSTORAGE: + *write_method = write_vacmAccessStorageType; + break; + case ACCESSSTATUS: + *write_method = write_vacmAccessStatus; + break; +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + default: + *write_method = NULL; + } + + *var_len = 0; /* assume 0 length until found */ + + if (memcmp(name, vp->name, sizeof(oid) * vp->namelen) != 0) { + memcpy(name, vp->name, sizeof(oid) * vp->namelen); + *length = vp->namelen; + } + + if (exact) { + if (*length < 15) + return NULL; + + /* + * Extract the group name index from the requested OID .... + */ + op = name + 11; + len = *op++; + if (len > VACM_MAX_STRING) + return NULL; + cp = groupName; + while (len-- > 0) { + if (*op > 255) + return NULL; /* illegal value */ + *cp++ = (char) *op++; + } + *cp = 0; + + /* + * ... followed by the context index ... + */ + len = *op++; + if (len > VACM_MAX_STRING) + return NULL; + cp = contextPrefix; + while (len-- > 0) { + if (*op > 255) + return NULL; /* illegal value */ + *cp++ = (char) *op++; + } + *cp = 0; + + /* + * ... and the secModel and secLevel index values. + */ + secmodel = *op++; + seclevel = *op++; + if (op != name + *length) { + return NULL; + } + + gp = vacm_getAccessEntry(groupName, contextPrefix, secmodel, + seclevel); + if ( gp && gp->securityLevel != seclevel ) + return NULL; /* This isn't strictly what was asked for */ + + } else { + secmodel = seclevel = 0; + groupName[0] = 0; + contextPrefix[0] = 0; + op = name + 11; + if (op >= name + *length) { + } else { + len = *op; + if (len > VACM_MAX_STRING) + return NULL; + cp = groupName; + for (i = 0; i <= len; i++) { + if (*op > 255) { + return NULL; /* illegal value */ + } + *cp++ = (char) *op++; + } + *cp = 0; + } + if (op >= name + *length) { + } else { + len = *op; + if (len > VACM_MAX_STRING) + return NULL; + cp = contextPrefix; + for (i = 0; i <= len; i++) { + if (*op > 255) { + return NULL; /* illegal value */ + } + *cp++ = (char) *op++; + } + *cp = 0; + } + if (op >= name + *length) { + } else { + secmodel = *op++; + } + if (op >= name + *length) { + } else { + seclevel = *op++; + } + vacm_scanAccessInit(); + while ((gp = vacm_scanAccessNext()) != NULL) { + cmp = strcmp(gp->groupName, groupName); + if (cmp > 0) + break; + if (cmp < 0) + continue; + cmp = strcmp(gp->contextPrefix, contextPrefix); + if (cmp > 0) + break; + if (cmp < 0) + continue; + if (gp->securityModel > secmodel) + break; + if (gp->securityModel < secmodel) + continue; + if (gp->securityLevel > seclevel) + break; + } + if (gp) { + *length = 11; + cp = gp->groupName; + do { + name[(*length)++] = *cp++; + } while (*cp); + cp = gp->contextPrefix; + do { + name[(*length)++] = *cp++; + } while (*cp); + name[(*length)++] = gp->securityModel; + name[(*length)++] = gp->securityLevel; + } + } + + if (!gp) { + return NULL; + } + + *var_len = sizeof(long_return); + switch (vp->magic) { + case ACCESSMATCH: + long_return = gp->contextMatch; + return (u_char *) & long_return; + + case ACCESSLEVEL: + long_return = gp->securityLevel; + return (u_char *) & long_return; + + case ACCESSMODEL: + long_return = gp->securityModel; + return (u_char *) & long_return; + + case ACCESSPREFIX: + *var_len = *gp->contextPrefix; + return (u_char *) & gp->contextPrefix[1]; + + case ACCESSREAD: + *var_len = strlen(gp->views[VACM_VIEW_READ]); + return (u_char *) gp->views[VACM_VIEW_READ]; + + case ACCESSWRITE: + *var_len = strlen(gp->views[VACM_VIEW_WRITE]); + return (u_char *) gp->views[VACM_VIEW_WRITE]; + + case ACCESSNOTIFY: + *var_len = strlen(gp->views[VACM_VIEW_NOTIFY]); + return (u_char *) gp->views[VACM_VIEW_NOTIFY]; + + case ACCESSSTORAGE: + long_return = gp->storageType; + return (u_char *) & long_return; + + case ACCESSSTATUS: + long_return = gp->status; + return (u_char *) & long_return; + } + + return NULL; +} + +u_char * +var_vacm_view(struct variable * vp, + oid * name, + size_t * length, + int exact, size_t * var_len, WriteMethod ** write_method) +{ + struct vacm_viewEntry *gp = NULL; + char viewName[VACMSTRINGLEN] = { 0 }; + oid subtree[MAX_OID_LEN] = { 0 }; + size_t subtreeLen = 0; + oid *op, *op1; + unsigned long len = 0, i = 0; + char *cp; + int cmp, cmp2; + + /* + * Set up write_method first, in case we return NULL before getting to + * the switch (vp->magic) below. In some of these cases, we still want + * to call the appropriate write_method, if only to have it return the + * appropriate error. + */ + + switch (vp->magic) { +#ifndef NETSNMP_NO_WRITE_SUPPORT + case VIEWMASK: + *write_method = write_vacmViewMask; + break; + case VIEWTYPE: + *write_method = write_vacmViewType; + break; + case VIEWSTORAGE: + *write_method = write_vacmViewStorageType; + break; + case VIEWSTATUS: + *write_method = write_vacmViewStatus; + break; +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + default: + *write_method = NULL; + } + + *var_len = sizeof(long_return); + + if (vp->magic != VACMVIEWSPINLOCK) { + if (memcmp(name, vp->name, sizeof(oid) * vp->namelen) != 0) { + memcpy(name, vp->name, sizeof(oid) * vp->namelen); + *length = vp->namelen; + } + + if (exact) { + if (*length < 15) + return NULL; + + /* + * Extract the view name index from the requested OID .... + */ + op = name + 12; + len = *op++; + if (len > VACM_MAX_STRING) + return NULL; + cp = viewName; + while (len-- > 0) { + if (*op > 255) + return NULL; + *cp++ = (char) *op++; + } + *cp = 0; + + /* + * ... followed by the view OID index. + */ + subtree[0] = len = *op++; + subtreeLen = 1; + if (len > MAX_OID_LEN) + return NULL; + if ( (op+len) != (name + *length) ) + return NULL; /* Declared length doesn't match what we actually got */ + op1 = &(subtree[1]); + while (len-- > 0) { + *op1++ = *op++; + subtreeLen++; + } + + gp = vacm_getViewEntry(viewName, &subtree[1], subtreeLen-1, + VACM_MODE_IGNORE_MASK); + if (gp != NULL) { + if (gp->viewSubtreeLen != subtreeLen) { + gp = NULL; + } + } + } else { + viewName[0] = 0; + op = name + 12; + if (op >= name + *length) { + } else { + len = *op; + if (len > VACM_MAX_STRING) + return NULL; + cp = viewName; + for (i = 0; i <= len && op < name + *length; i++) { + if (*op > 255) { + return NULL; + } + *cp++ = (char) *op++; + } + *cp = 0; + } + if (op >= name + *length) { + } else { + len = *op++; + op1 = subtree; + *op1++ = len; + subtreeLen++; + for (i = 0; i <= len && op < name + *length; i++) { + *op1++ = *op++; + subtreeLen++; + } + } + vacm_scanViewInit(); + while ((gp = vacm_scanViewNext()) != NULL) { + cmp = strcmp(gp->viewName, viewName); + cmp2 = + snmp_oid_compare(gp->viewSubtree, gp->viewSubtreeLen, + subtree, subtreeLen); + if (cmp == 0 && cmp2 > 0) + break; + if (cmp > 0) + break; + } + if (gp) { + *length = 12; + cp = gp->viewName; + do { + name[(*length)++] = *cp++; + } while (*cp); + op1 = gp->viewSubtree; + len = gp->viewSubtreeLen; + while (len-- > 0) { + name[(*length)++] = *op1++; + } + } + } + + if (gp == NULL) { + return NULL; + } + } else { + if (header_generic(vp, name, length, exact, var_len, write_method)) { + return NULL; + } + } /*endif -- vp->magic != VACMVIEWSPINLOCK */ + + switch (vp->magic) { + case VACMVIEWSPINLOCK: +#ifndef NETSNMP_NO_WRITE_SUPPORT + *write_method = write_vacmViewSpinLock; +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + long_return = vacmViewSpinLock; + return (u_char *) & long_return; + + case VIEWNAME: + *var_len = gp->viewName[0]; + return (u_char *) & gp->viewName[1]; + + case VIEWSUBTREE: + *var_len = gp->viewSubtreeLen * sizeof(oid); + return (u_char *) gp->viewSubtree; + + case VIEWMASK: + *var_len = gp->viewMaskLen; + return (u_char *) gp->viewMask; + + case VIEWTYPE: + long_return = gp->viewType; + return (u_char *) & long_return; + + case VIEWSTORAGE: + long_return = gp->viewStorageType; + return (u_char *) & long_return; + + case VIEWSTATUS: + long_return = gp->viewStatus; + return (u_char *) & long_return; + } + + return NULL; +} + +#ifndef NETSNMP_NO_WRITE_SUPPORT +int +sec2group_parse_oid(oid * oidIndex, size_t oidLen, + int *model, unsigned char **name, size_t * nameLen) +{ + int nameL; + int i; + + /* + * first check the validity of the oid + */ + if ((oidLen <= 0) || (!oidIndex)) { + return 1; + } + nameL = oidIndex[1]; /* the initial name length */ + if ((int) oidLen != nameL + 2) { + return 1; + } + + /* + * its valid, malloc the space and store the results + */ + if (name == NULL) { + return 1; + } + + *name = (unsigned char *) malloc(nameL + 1); + if (*name == NULL) { + return 1; + } + + *model = oidIndex[0]; + *nameLen = nameL; + + + for (i = 0; i < nameL; i++) { + if (oidIndex[i + 2] > 255) { + free(*name); + return 1; + } + name[0][i] = (unsigned char) oidIndex[i + 2]; + } + name[0][nameL] = 0; + + return 0; + +} + +struct vacm_groupEntry * +sec2group_parse_groupEntry(oid * name, size_t name_len) +{ + struct vacm_groupEntry *geptr; + + char *newName; + int model; + size_t nameLen; + + /* + * get the name and engineID out of the incoming oid + */ + if (sec2group_parse_oid + (&name[SEC2GROUP_MIB_LENGTH], name_len - SEC2GROUP_MIB_LENGTH, + &model, (u_char **) & newName, &nameLen)) + return NULL; + + /* + * Now see if a user exists with these index values + */ + geptr = vacm_getGroupEntry(model, newName); + free(newName); + + return geptr; + +} /* end vacm_parse_groupEntry() */ + +int +write_vacmGroupName(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static unsigned char string[VACMSTRINGLEN]; + struct vacm_groupEntry *geptr; + static int resetOnFail; + + if (action == RESERVE1) { + resetOnFail = 0; + if (var_val_type != ASN_OCTET_STR) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len < 1 || var_val_len > 32) { + return SNMP_ERR_WRONGLENGTH; + } + } else if (action == RESERVE2) { + if ((geptr = sec2group_parse_groupEntry(name, name_len)) == NULL) { + return SNMP_ERR_INCONSISTENTNAME; + } else { + resetOnFail = 1; + memcpy(string, geptr->groupName, VACMSTRINGLEN); + memcpy(geptr->groupName, var_val, var_val_len); + geptr->groupName[var_val_len] = 0; + if (geptr->status == RS_NOTREADY) { + geptr->status = RS_NOTINSERVICE; + } + } + } else if (action == FREE) { + /* + * Try to undo the SET here (abnormal usage of FREE clause) + */ + if ((geptr = sec2group_parse_groupEntry(name, name_len)) != NULL && + resetOnFail) { + memcpy(geptr->groupName, string, VACMSTRINGLEN); + } + } + return SNMP_ERR_NOERROR; +} + +int +write_vacmSecurityToGroupStorageType(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, + oid * name, size_t name_len) +{ + /* + * variables we may use later + */ + static long long_ret; + struct vacm_groupEntry *geptr; + + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)) { + return SNMP_ERR_WRONGLENGTH; + } + if (action == COMMIT) { + /* + * don't allow creations here + */ + if ((geptr = sec2group_parse_groupEntry(name, name_len)) == NULL) { + return SNMP_ERR_NOSUCHNAME; + } + long_ret = *((long *) var_val); + if ((long_ret == ST_VOLATILE || long_ret == ST_NONVOLATILE) && + (geptr->storageType == ST_VOLATILE || + geptr->storageType == ST_NONVOLATILE)) { + geptr->storageType = long_ret; + } else if (long_ret == geptr->storageType) { + return SNMP_ERR_NOERROR; + } else { + return SNMP_ERR_INCONSISTENTVALUE; + } + } + return SNMP_ERR_NOERROR; +} + + +int +write_vacmSecurityToGroupStatus(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, + oid * name, size_t name_len) +{ + static long long_ret; + int model; + char *newName; + size_t nameLen; + struct vacm_groupEntry *geptr; + + if (action == RESERVE1) { + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long_ret)) { + return SNMP_ERR_WRONGLENGTH; + } + long_ret = *((long *) var_val); + if (long_ret == RS_NOTREADY || long_ret < 1 || long_ret > 6) { + return SNMP_ERR_WRONGVALUE; + } + + /* + * See if we can parse the oid for model/name first. + */ + + if (sec2group_parse_oid(&name[SEC2GROUP_MIB_LENGTH], + name_len - SEC2GROUP_MIB_LENGTH, + &model, (u_char **) & newName, &nameLen)) { + return SNMP_ERR_INCONSISTENTNAME; + } + + if (model < 1 || nameLen < 1 || nameLen > 32) { + free(newName); + return SNMP_ERR_NOCREATION; + } + + /* + * Now see if a group already exists with these index values. + */ + geptr = vacm_getGroupEntry(model, newName); + + if (geptr != NULL) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + free(newName); + long_ret = RS_NOTREADY; + return SNMP_ERR_INCONSISTENTVALUE; + } + if (long_ret == RS_DESTROY && geptr->storageType == ST_PERMANENT) { + free(newName); + return SNMP_ERR_WRONGVALUE; + } + } else { + if (long_ret == RS_ACTIVE || long_ret == RS_NOTINSERVICE) { + free(newName); + return SNMP_ERR_INCONSISTENTVALUE; + } + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + + /* + * Generate a new group entry. + */ + if ((geptr = + vacm_createGroupEntry(model, newName)) == NULL) { + free(newName); + return SNMP_ERR_GENERR; + } + + /* + * Set defaults. + */ + geptr->storageType = ST_NONVOLATILE; + geptr->status = RS_NOTREADY; + } + } + free(newName); + } else if (action == ACTION) { + sec2group_parse_oid(&name[SEC2GROUP_MIB_LENGTH], + name_len - SEC2GROUP_MIB_LENGTH, + &model, (u_char **) & newName, &nameLen); + + geptr = vacm_getGroupEntry(model, newName); + + if (geptr != NULL) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_ACTIVE) { + /* + * Check that all the mandatory objects have been set by now, + * otherwise return inconsistentValue. + */ + if (geptr->groupName[0] == 0) { + free(newName); + return SNMP_ERR_INCONSISTENTVALUE; + } + geptr->status = RS_ACTIVE; + } else if (long_ret == RS_CREATEANDWAIT) { + if (geptr->groupName[0] != 0) { + geptr->status = RS_NOTINSERVICE; + } + } else if (long_ret == RS_NOTINSERVICE) { + if (geptr->status == RS_ACTIVE) { + geptr->status = RS_NOTINSERVICE; + } else if (geptr->status == RS_NOTREADY) { + free(newName); + return SNMP_ERR_INCONSISTENTVALUE; + } + } + } + free(newName); + } else if (action == COMMIT) { + sec2group_parse_oid(&name[SEC2GROUP_MIB_LENGTH], + name_len - SEC2GROUP_MIB_LENGTH, + &model, (u_char **) & newName, &nameLen); + + geptr = vacm_getGroupEntry(model, newName); + + if (geptr != NULL) { + if (long_ret == RS_DESTROY) { + vacm_destroyGroupEntry(model, newName); + } + } + free(newName); + } else if (action == UNDO) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + sec2group_parse_oid(&name[SEC2GROUP_MIB_LENGTH], + name_len - SEC2GROUP_MIB_LENGTH, + &model, (u_char **) & newName, &nameLen); + + geptr = vacm_getGroupEntry(model, newName); + + if (geptr != NULL) { + vacm_destroyGroupEntry(model, newName); + } + free(newName); + } + } + + return SNMP_ERR_NOERROR; +} + +int +access_parse_oid(oid * oidIndex, size_t oidLen, + unsigned char **groupName, size_t * groupNameLen, + unsigned char **contextPrefix, size_t * contextPrefixLen, + int *model, int *level) +{ + int groupNameL, contextPrefixL; + int i; + + /* + * first check the validity of the oid + */ + if ((oidLen <= 0) || (!oidIndex)) { + return 1; + } + groupNameL = oidIndex[0]; + contextPrefixL = oidIndex[groupNameL + 1]; /* the initial name length */ + if ((int) oidLen != groupNameL + contextPrefixL + 4) { + return 1; + } + + /* + * its valid, malloc the space and store the results + */ + if (contextPrefix == NULL || groupName == NULL) { + return 1; + } + + *groupName = (unsigned char *) malloc(groupNameL + 1); + if (*groupName == NULL) { + return 1; + } + + *contextPrefix = (unsigned char *) malloc(contextPrefixL + 1); + if (*contextPrefix == NULL) { + free(*groupName); + return 1; + } + + *contextPrefixLen = contextPrefixL; + *groupNameLen = groupNameL; + + for (i = 0; i < groupNameL; i++) { + if (oidIndex[i + 1] > 255) { + free(*groupName); + free(*contextPrefix); + return 1; + } + groupName[0][i] = (unsigned char) oidIndex[i + 1]; + } + groupName[0][groupNameL] = 0; + + + for (i = 0; i < contextPrefixL; i++) { + if (oidIndex[i + groupNameL + 2] > 255) { + free(*groupName); + free(*contextPrefix); + return 1; + } + contextPrefix[0][i] = (unsigned char) oidIndex[i + groupNameL + 2]; + } + contextPrefix[0][contextPrefixL] = 0; + + *model = oidIndex[groupNameL + contextPrefixL + 2]; + *level = oidIndex[groupNameL + contextPrefixL + 3]; + + return 0; + +} + +struct vacm_accessEntry * +access_parse_accessEntry(oid * name, size_t name_len) +{ + struct vacm_accessEntry *aptr; + + char *newGroupName = NULL; + char *newContextPrefix = NULL; + int model, level; + size_t groupNameLen, contextPrefixLen; + + /* + * get the name and engineID out of the incoming oid + */ + if (access_parse_oid + (&name[ACCESS_MIB_LENGTH], name_len - ACCESS_MIB_LENGTH, + (u_char **) & newGroupName, &groupNameLen, + (u_char **) & newContextPrefix, &contextPrefixLen, &model, + &level)) + return NULL; + + /* + * Now see if a user exists with these index values + */ + aptr = + vacm_getAccessEntry(newGroupName, newContextPrefix, model, level); + SNMP_FREE(newContextPrefix); + SNMP_FREE(newGroupName); + + return aptr; + +} /* end vacm_parse_accessEntry() */ + +int +write_vacmAccessStatus(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static long long_ret; + int model, level; + char *newGroupName = NULL, *newContextPrefix = NULL; + size_t groupNameLen, contextPrefixLen; + struct vacm_accessEntry *aptr = NULL; + + if (action == RESERVE1) { + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long_ret)) { + return SNMP_ERR_WRONGLENGTH; + } + long_ret = *((long *) var_val); + if (long_ret == RS_NOTREADY || long_ret < 1 || long_ret > 6) { + return SNMP_ERR_WRONGVALUE; + } + + /* + * See if we can parse the oid for model/name first. + */ + if (access_parse_oid(&name[ACCESS_MIB_LENGTH], + name_len - ACCESS_MIB_LENGTH, + (u_char **) & newGroupName, &groupNameLen, + (u_char **) & newContextPrefix, + &contextPrefixLen, &model, &level)) { + return SNMP_ERR_INCONSISTENTNAME; + } + + if (model < 0 || groupNameLen < 1 || groupNameLen > 32 || + contextPrefixLen > 32) { + free(newGroupName); + free(newContextPrefix); + return SNMP_ERR_NOCREATION; + } + + /* + * Now see if a group already exists with these index values. + */ + aptr = + vacm_getAccessEntry(newGroupName, newContextPrefix, model, + level); + + if (aptr != NULL) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + free(newGroupName); + free(newContextPrefix); + return SNMP_ERR_INCONSISTENTVALUE; + } + if (long_ret == RS_DESTROY && aptr->storageType == ST_PERMANENT) { + free(newGroupName); + free(newContextPrefix); + return SNMP_ERR_WRONGVALUE; + } + } else { + if (long_ret == RS_ACTIVE || long_ret == RS_NOTINSERVICE) { + free(newGroupName); + free(newContextPrefix); + return SNMP_ERR_INCONSISTENTVALUE; + } + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + if ((aptr = vacm_createAccessEntry(newGroupName, + newContextPrefix, + model, + level)) == NULL) { + free(newGroupName); + free(newContextPrefix); + return SNMP_ERR_GENERR; + } + + /* + * Set defaults. + */ + aptr->contextMatch = 1; /* exact(1) is the DEFVAL */ + aptr->storageType = ST_NONVOLATILE; + aptr->status = RS_NOTREADY; + } + } + free(newGroupName); + free(newContextPrefix); + } else if (action == ACTION) { + access_parse_oid(&name[ACCESS_MIB_LENGTH], + name_len - ACCESS_MIB_LENGTH, + (u_char **) & newGroupName, &groupNameLen, + (u_char **) & newContextPrefix, &contextPrefixLen, + &model, &level); + aptr = + vacm_getAccessEntry(newGroupName, newContextPrefix, model, + level); + + if (aptr != NULL) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_ACTIVE) { + aptr->status = RS_ACTIVE; + } else if (long_ret == RS_CREATEANDWAIT) { + aptr->status = RS_NOTINSERVICE; + } else if (long_ret == RS_NOTINSERVICE) { + if (aptr->status == RS_ACTIVE) { + aptr->status = RS_NOTINSERVICE; + } else if (aptr->status == RS_NOTREADY) { + free(newGroupName); + free(newContextPrefix); + return SNMP_ERR_INCONSISTENTVALUE; + } + } + } + free(newGroupName); + free(newContextPrefix); + } else if (action == COMMIT) { + access_parse_oid(&name[ACCESS_MIB_LENGTH], + name_len - ACCESS_MIB_LENGTH, + (u_char **) & newGroupName, &groupNameLen, + (u_char **) & newContextPrefix, &contextPrefixLen, + &model, &level); + aptr = + vacm_getAccessEntry(newGroupName, newContextPrefix, model, + level); + + if (aptr) { + if (long_ret == RS_DESTROY) { + vacm_destroyAccessEntry(newGroupName, newContextPrefix, + model, level); + } + } + free(newGroupName); + free(newContextPrefix); + } else if (action == UNDO) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + access_parse_oid(&name[ACCESS_MIB_LENGTH], + name_len - ACCESS_MIB_LENGTH, + (u_char **) & newGroupName, &groupNameLen, + (u_char **) & newContextPrefix, + &contextPrefixLen, &model, &level); + aptr = + vacm_getAccessEntry(newGroupName, newContextPrefix, model, + level); + if (aptr != NULL) { + vacm_destroyAccessEntry(newGroupName, newContextPrefix, + model, level); + } + } + free(newGroupName); + free(newContextPrefix); + } + + return SNMP_ERR_NOERROR; +} + +int +write_vacmAccessStorageType(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + /* + * variables we may use later + */ + static long long_ret; + struct vacm_accessEntry *aptr; + + if (var_val_type != ASN_INTEGER) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmSecurityToGroupStorageType not ASN_INTEGER\n")); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmSecurityToGroupStorageType: bad length\n")); + return SNMP_ERR_WRONGLENGTH; + } + if (action == COMMIT) { + /* + * don't allow creations here + */ + if ((aptr = access_parse_accessEntry(name, name_len)) == NULL) { + return SNMP_ERR_NOSUCHNAME; + } + long_ret = *((long *) var_val); + /* + * if ((long_ret == ST_VOLATILE || long_ret == ST_NONVOLATILE) && + * (aptr->storageType == ST_VOLATILE || + * aptr->storageType == ST_NONVOLATILE)) + */ + /* + * This version only supports volatile storage + */ + if (long_ret == aptr->storageType) { + return SNMP_ERR_NOERROR; + } else { + return SNMP_ERR_INCONSISTENTVALUE; + } + } + return SNMP_ERR_NOERROR; +} + +int +write_vacmAccessContextMatch(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + /* + * variables we may use later + */ + static long long_ret; + struct vacm_accessEntry *aptr; + + if (var_val_type != ASN_INTEGER) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessContextMatch not ASN_INTEGER\n")); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > sizeof(long_ret)) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessContextMatch: bad length\n")); + return SNMP_ERR_WRONGLENGTH; + } + if (action == COMMIT) { + /* + * don't allow creations here + */ + if ((aptr = access_parse_accessEntry(name, name_len)) == NULL) { + return SNMP_ERR_NOSUCHNAME; + } + long_ret = *((long *) var_val); + if (long_ret == CM_EXACT || long_ret == CM_PREFIX) { + aptr->contextMatch = long_ret; + } else { + return SNMP_ERR_WRONGVALUE; + } + } + return SNMP_ERR_NOERROR; +} + +int +write_vacmAccessReadViewName(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static unsigned char string[VACMSTRINGLEN]; + struct vacm_accessEntry *aptr = NULL; + static int resetOnFail; + + if (action == RESERVE1) { + resetOnFail = 0; + if (var_val_type != ASN_OCTET_STR) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessReadViewName not ASN_OCTET_STR\n")); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > 32) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessReadViewName: bad length\n")); + return SNMP_ERR_WRONGLENGTH; + } + } else if (action == RESERVE2) { + if ((aptr = access_parse_accessEntry(name, name_len)) == NULL) { + return SNMP_ERR_INCONSISTENTNAME; + } else { + resetOnFail = 1; + memcpy(string, aptr->views[VACM_VIEW_READ], VACMSTRINGLEN); + memcpy(aptr->views[VACM_VIEW_READ], var_val, var_val_len); + aptr->views[VACM_VIEW_READ][var_val_len] = 0; + } + } else if (action == FREE) { + /* + * Try to undo the SET here (abnormal usage of FREE clause) + */ + if ((aptr = access_parse_accessEntry(name, name_len)) != NULL && + resetOnFail) { + memcpy(aptr->views[VACM_VIEW_READ], string, var_val_len); + } + } + return SNMP_ERR_NOERROR; +} + +int +write_vacmAccessWriteViewName(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static unsigned char string[VACMSTRINGLEN]; + struct vacm_accessEntry *aptr = NULL; + static int resetOnFail; + + if (action == RESERVE1) { + resetOnFail = 0; + if (var_val_type != ASN_OCTET_STR) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessWriteViewName not ASN_OCTET_STR\n")); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > 32) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessWriteViewName: bad length\n")); + return SNMP_ERR_WRONGLENGTH; + } + } else if (action == RESERVE2) { + if ((aptr = access_parse_accessEntry(name, name_len)) == NULL) { + return SNMP_ERR_INCONSISTENTNAME; + } else { + resetOnFail = 1; + memcpy(string, aptr->views[VACM_VIEW_WRITE], VACMSTRINGLEN); + memcpy(aptr->views[VACM_VIEW_WRITE], var_val, var_val_len); + aptr->views[VACM_VIEW_WRITE][var_val_len] = 0; + } + } else if (action == FREE) { + /* + * Try to undo the SET here (abnormal usage of FREE clause) + */ + if ((aptr = access_parse_accessEntry(name, name_len)) != NULL && + resetOnFail) { + memcpy(aptr->views[VACM_VIEW_WRITE], string, var_val_len); + } + } + return SNMP_ERR_NOERROR; +} + +int +write_vacmAccessNotifyViewName(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static unsigned char string[VACMSTRINGLEN]; + struct vacm_accessEntry *aptr = NULL; + static int resetOnFail; + + if (action == RESERVE1) { + resetOnFail = 0; + if (var_val_type != ASN_OCTET_STR) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessNotifyViewName not ASN_OCTET_STR\n")); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > 32) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmAccessNotifyViewName: bad length\n")); + return SNMP_ERR_WRONGLENGTH; + } + } else if (action == RESERVE2) { + if ((aptr = access_parse_accessEntry(name, name_len)) == NULL) { + return SNMP_ERR_INCONSISTENTNAME; + } else { + resetOnFail = 1; + memcpy(string, aptr->views[VACM_VIEW_NOTIFY], VACMSTRINGLEN); + memcpy(aptr->views[VACM_VIEW_NOTIFY], var_val, var_val_len); + aptr->views[VACM_VIEW_NOTIFY][var_val_len] = 0; + } + } else if (action == FREE) { + /* + * Try to undo the SET here (abnormal usage of FREE clause) + */ + if ((aptr = access_parse_accessEntry(name, name_len)) != NULL && + resetOnFail) { + memcpy(aptr->views[VACM_VIEW_NOTIFY], string, var_val_len); + } + } + return SNMP_ERR_NOERROR; +} + +int +view_parse_oid(oid * oidIndex, size_t oidLen, + unsigned char **viewName, size_t * viewNameLen, + oid ** subtree, size_t * subtreeLen) +{ + int viewNameL, subtreeL, i; + + /* + * first check the validity of the oid + */ + if ((oidLen <= 0) || (!oidIndex)) { + return SNMP_ERR_INCONSISTENTNAME; + } + viewNameL = oidIndex[0]; + subtreeL = oidLen - viewNameL - 1; /* the initial name length */ + + /* + * its valid, malloc the space and store the results + */ + if (viewName == NULL || subtree == NULL) { + return SNMP_ERR_RESOURCEUNAVAILABLE; + } + + if (subtreeL < 0) { + return SNMP_ERR_NOCREATION; + } + + *viewName = (unsigned char *) malloc(viewNameL + 1); + + if (*viewName == NULL) { + return SNMP_ERR_RESOURCEUNAVAILABLE; + } + + *subtree = (oid *) malloc(subtreeL * sizeof(oid)); + if (*subtree == NULL) { + free(*viewName); + return SNMP_ERR_RESOURCEUNAVAILABLE; + } + + *subtreeLen = subtreeL; + *viewNameLen = viewNameL; + + for (i = 0; i < viewNameL; i++) { + if (oidIndex[i + 1] > 255) { + free(*viewName); + free(*subtree); + return SNMP_ERR_INCONSISTENTNAME; + } + viewName[0][i] = (unsigned char) oidIndex[i + 1]; + } + viewName[0][viewNameL] = 0; + + for (i = 0; i < subtreeL; i++) { + subtree[0][i] = (oid) oidIndex[i + viewNameL + 1]; + } + + return 0; +} + +struct vacm_viewEntry * +view_parse_viewEntry(oid * name, size_t name_len) +{ + struct vacm_viewEntry *vptr; + + char *newViewName; + oid *newViewSubtree; + size_t viewNameLen, viewSubtreeLen; + + if (view_parse_oid(&name[VIEW_MIB_LENGTH], name_len - VIEW_MIB_LENGTH, + (u_char **) & newViewName, &viewNameLen, + (oid **) & newViewSubtree, &viewSubtreeLen)) + return NULL; + + vptr = + vacm_getViewEntry(newViewName, &newViewSubtree[1], viewSubtreeLen-1, + VACM_MODE_IGNORE_MASK); + free(newViewName); + free(newViewSubtree); + + return vptr; + +} /* end vacm_parse_viewEntry() */ + +int +write_vacmViewStatus(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static long long_ret; + char *newViewName; + oid *newViewSubtree; + size_t viewNameLen, viewSubtreeLen; + struct vacm_viewEntry *vptr; + int rc = 0; + + if (action == RESERVE1) { + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long_ret)) { + return SNMP_ERR_WRONGLENGTH; + } + long_ret = *((long *) var_val); + if (long_ret == RS_NOTREADY || long_ret < 1 || long_ret > 6) { + return SNMP_ERR_WRONGVALUE; + } + + /* + * See if we can parse the oid for model/name first. + */ + if ((rc = + view_parse_oid(&name[VIEW_MIB_LENGTH], + name_len - VIEW_MIB_LENGTH, + (u_char **) & newViewName, &viewNameLen, + (oid **) & newViewSubtree, &viewSubtreeLen))) { + return rc; + } + + if (viewNameLen < 1 || viewNameLen > 32) { + free(newViewName); + free(newViewSubtree); + return SNMP_ERR_NOCREATION; + } + + /* + * Now see if a group already exists with these index values. + */ + vptr = + vacm_getViewEntry(newViewName, &newViewSubtree[1], viewSubtreeLen-1, + VACM_MODE_IGNORE_MASK); + if (vptr && + netsnmp_oid_equals(vptr->viewSubtree + 1, vptr->viewSubtreeLen - 1, + newViewSubtree + 1, viewSubtreeLen - 1) != 0) { + vptr = NULL; + } + if (vptr != NULL) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + free(newViewName); + free(newViewSubtree); + long_ret = RS_NOTREADY; + return SNMP_ERR_INCONSISTENTVALUE; + } + if (long_ret == RS_DESTROY && vptr->viewStorageType == ST_PERMANENT) { + free(newViewName); + free(newViewSubtree); + return SNMP_ERR_WRONGVALUE; + } + } else { + if (long_ret == RS_ACTIVE || long_ret == RS_NOTINSERVICE) { + free(newViewName); + free(newViewSubtree); + return SNMP_ERR_INCONSISTENTVALUE; + } + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + + /* + * Generate a new group entry. + */ + if ((vptr = + vacm_createViewEntry(newViewName, &newViewSubtree[1], + viewSubtreeLen - 1)) == NULL) { + free(newViewName); + free(newViewSubtree); + return SNMP_ERR_GENERR; + } + + /* + * Set defaults. + */ + vptr->viewStorageType = ST_NONVOLATILE; + vptr->viewStatus = RS_NOTREADY; + vptr->viewType = SNMP_VIEW_INCLUDED; + } + } + free(newViewName); + free(newViewSubtree); + } else if (action == ACTION) { + view_parse_oid(&name[VIEW_MIB_LENGTH], name_len - VIEW_MIB_LENGTH, + (u_char **) & newViewName, &viewNameLen, + (oid **) & newViewSubtree, &viewSubtreeLen); + + vptr = + vacm_getViewEntry(newViewName, &newViewSubtree[1], viewSubtreeLen-1, + VACM_MODE_IGNORE_MASK); + + if (vptr != NULL) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_ACTIVE) { + vptr->viewStatus = RS_ACTIVE; + } else if (long_ret == RS_CREATEANDWAIT) { + vptr->viewStatus = RS_NOTINSERVICE; + } else if (long_ret == RS_NOTINSERVICE) { + if (vptr->viewStatus == RS_ACTIVE) { + vptr->viewStatus = RS_NOTINSERVICE; + } else if (vptr->viewStatus == RS_NOTREADY) { + free(newViewName); + free(newViewSubtree); + return SNMP_ERR_INCONSISTENTVALUE; + } + } + } + free(newViewName); + free(newViewSubtree); + } else if (action == COMMIT) { + view_parse_oid(&name[VIEW_MIB_LENGTH], name_len - VIEW_MIB_LENGTH, + (u_char **) & newViewName, &viewNameLen, + (oid **) & newViewSubtree, &viewSubtreeLen); + + vptr = + vacm_getViewEntry(newViewName, &newViewSubtree[1], viewSubtreeLen-1, + VACM_MODE_IGNORE_MASK); + + if (vptr != NULL) { + if (long_ret == RS_DESTROY) { + vacm_destroyViewEntry(newViewName, newViewSubtree, + viewSubtreeLen); + } + } + free(newViewName); + free(newViewSubtree); + } else if (action == UNDO) { + if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) { + view_parse_oid(&name[VIEW_MIB_LENGTH], + name_len - VIEW_MIB_LENGTH, + (u_char **) & newViewName, &viewNameLen, + (oid **) & newViewSubtree, &viewSubtreeLen); + + vptr = vacm_getViewEntry(newViewName, &newViewSubtree[1], + viewSubtreeLen-1, VACM_MODE_IGNORE_MASK); + + if (vptr != NULL) { + vacm_destroyViewEntry(newViewName, newViewSubtree, + viewSubtreeLen); + } + free(newViewName); + free(newViewSubtree); + } + } + + return SNMP_ERR_NOERROR; +} + +int +write_vacmViewStorageType(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + long newValue = *((long *) var_val); + static long oldValue; + struct vacm_viewEntry *vptr = NULL; + + if (action == RESERVE1) { + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long)) { + return SNMP_ERR_WRONGLENGTH; + } + } else if (action == RESERVE2) { + if ((vptr = view_parse_viewEntry(name, name_len)) == NULL) { + return SNMP_ERR_INCONSISTENTNAME; + } else { + if ((newValue == ST_VOLATILE || newValue == ST_NONVOLATILE) && + (vptr->viewStorageType == ST_VOLATILE || + vptr->viewStorageType == ST_NONVOLATILE)) { + oldValue = vptr->viewStorageType; + vptr->viewStorageType = newValue; + } else if (newValue == vptr->viewStorageType) { + return SNMP_ERR_NOERROR; + } else { + return SNMP_ERR_INCONSISTENTVALUE; + } + } + } else if (action == UNDO) { + if ((vptr = view_parse_viewEntry(name, name_len)) != NULL) { + vptr->viewStorageType = oldValue; + } + } + + return SNMP_ERR_NOERROR; +} + +int +write_vacmViewMask(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static unsigned char string[VACMSTRINGLEN]; + static long length; + struct vacm_viewEntry *vptr = NULL; + + if (action == RESERVE1) { + if (var_val_type != ASN_OCTET_STR) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len > 16) { + return SNMP_ERR_WRONGLENGTH; + } + } else if (action == RESERVE2) { + if ((vptr = view_parse_viewEntry(name, name_len)) == NULL) { + return SNMP_ERR_INCONSISTENTNAME; + } else { + memcpy(string, vptr->viewMask, vptr->viewMaskLen); + length = vptr->viewMaskLen; + memcpy(vptr->viewMask, var_val, var_val_len); + vptr->viewMaskLen = var_val_len; + } + } else if (action == FREE) { + if ((vptr = view_parse_viewEntry(name, name_len)) != NULL) { + memcpy(vptr->viewMask, string, length); + vptr->viewMaskLen = length; + } + } + return SNMP_ERR_NOERROR; +} + +int +write_vacmViewType(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + long newValue = *((long *) var_val); + static long oldValue; + struct vacm_viewEntry *vptr = NULL; + + if (action == RESERVE1) { + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long)) { + return SNMP_ERR_WRONGLENGTH; + } + if (newValue < 1 || newValue > 2) { + return SNMP_ERR_WRONGVALUE; + } + } else if (action == RESERVE2) { + if ((vptr = view_parse_viewEntry(name, name_len)) == NULL) { + return SNMP_ERR_INCONSISTENTNAME; + } else { + oldValue = vptr->viewType; + vptr->viewType = newValue; + } + } else if (action == UNDO) { + if ((vptr = view_parse_viewEntry(name, name_len)) != NULL) { + vptr->viewType = oldValue; + } + } + + return SNMP_ERR_NOERROR; +} + +int +write_vacmViewSpinLock(int action, + u_char * var_val, + u_char var_val_type, + size_t var_val_len, + u_char * statP, oid * name, size_t name_len) +{ + static long long_ret; + + if (action == RESERVE1) { + if (var_val_type != ASN_INTEGER) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmViewSpinLock not ASN_INTEGER\n")); + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long_ret)) { + DEBUGMSGTL(("mibII/vacm_vars", + "write to vacmViewSpinLock: bad length\n")); + return SNMP_ERR_WRONGLENGTH; + } + long_ret = *((long *) var_val); + if (long_ret != (long) vacmViewSpinLock) { + return SNMP_ERR_INCONSISTENTVALUE; + } + } else if (action == COMMIT) { + if (vacmViewSpinLock == 2147483647) { + vacmViewSpinLock = 0; + } else { + vacmViewSpinLock++; + } + } + return SNMP_ERR_NOERROR; +} +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ |