usmUser.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:53k
- /*
- * usmUser.c
- */
- #include <net-snmp/net-snmp-config.h>
- #include <stdlib.h>
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #if HAVE_WINSOCK_H
- #include <winsock.h>
- #endif
- #include <net-snmp/net-snmp-includes.h>
- #include <net-snmp/agent/net-snmp-agent-includes.h>
- #include "util_funcs.h"
- #include "usmUser.h"
- int usmStatusCheck(struct usmUser *uptr);
- struct variable4 usmUser_variables[] = {
- {USMUSERSPINLOCK, ASN_INTEGER, RWRITE, var_usmUser, 1, {1}},
- {USMUSERSECURITYNAME, ASN_OCTET_STR, RONLY, var_usmUser, 3, {2, 1, 3}},
- {USMUSERCLONEFROM, ASN_OBJECT_ID, RWRITE, var_usmUser, 3, {2, 1, 4}},
- {USMUSERAUTHPROTOCOL, ASN_OBJECT_ID, RWRITE, var_usmUser, 3,
- {2, 1, 5}},
- {USMUSERAUTHKEYCHANGE, ASN_OCTET_STR, RWRITE, var_usmUser, 3,
- {2, 1, 6}},
- {USMUSEROWNAUTHKEYCHANGE, ASN_OCTET_STR, RWRITE, var_usmUser, 3,
- {2, 1, 7}},
- {USMUSERPRIVPROTOCOL, ASN_OBJECT_ID, RWRITE, var_usmUser, 3,
- {2, 1, 8}},
- {USMUSERPRIVKEYCHANGE, ASN_OCTET_STR, RWRITE, var_usmUser, 3,
- {2, 1, 9}},
- {USMUSEROWNPRIVKEYCHANGE, ASN_OCTET_STR, RWRITE, var_usmUser, 3,
- {2, 1, 10}},
- {USMUSERPUBLIC, ASN_OCTET_STR, RWRITE, var_usmUser, 3, {2, 1, 11}},
- {USMUSERSTORAGETYPE, ASN_INTEGER, RWRITE, var_usmUser, 3, {2, 1, 12}},
- {USMUSERSTATUS, ASN_INTEGER, RWRITE, var_usmUser, 3, {2, 1, 13}},
- };
- oid usmUser_variables_oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 2 };
- /*
- * needed for the write_ functions to find the start of the index
- */
- #define USM_MIB_LENGTH 12
- static unsigned int usmUserSpinLock = 0;
- void
- init_usmUser(void)
- {
- REGISTER_MIB("snmpv3/usmUser", usmUser_variables, variable4,
- usmUser_variables_oid);
- }
- void
- init_register_usmUser_context(const char *contextName) {
- register_mib_context("snmpv3/usmUser",
- (struct variable *) usmUser_variables,
- sizeof(struct variable4),
- sizeof(usmUser_variables)/sizeof(struct variable4),
- usmUser_variables_oid,
- sizeof(usmUser_variables_oid)/sizeof(oid),
- DEFAULT_MIB_PRIORITY, 0, 0, NULL,
- contextName, -1, 0);
- }
- /*******************************************************************-o-******
- * usm_generate_OID
- *
- * Parameters:
- * *prefix (I) OID prefix to the usmUser table entry.
- * prefixLen (I)
- * *uptr (I) Pointer to a user in the user list.
- * *length (O) Length of generated index OID.
- *
- * Returns:
- * Pointer to the OID index for the user (uptr) -OR-
- * NULL on failure.
- *
- *
- * Generate the index OID for a given usmUser name. 'length' is set to
- * the length of the index OID.
- *
- * Index OID format is:
- *
- * <...prefix>.<engineID_length>.<engineID>.<user_name_length>.<user_name>
- */
- oid *
- usm_generate_OID(oid * prefix, size_t prefixLen, struct usmUser *uptr,
- size_t * length)
- {
- oid *indexOid;
- int i;
- *length = 2 + uptr->engineIDLen + strlen(uptr->name) + prefixLen;
- indexOid = (oid *) malloc(*length * sizeof(oid));
- if (indexOid) {
- memmove(indexOid, prefix, prefixLen * sizeof(oid));
- indexOid[prefixLen] = uptr->engineIDLen;
- for (i = 0; i < (int) uptr->engineIDLen; i++)
- indexOid[prefixLen + 1 + i] = (oid) uptr->engineID[i];
- indexOid[prefixLen + uptr->engineIDLen + 1] = strlen(uptr->name);
- for (i = 0; i < (int) strlen(uptr->name); i++)
- indexOid[prefixLen + uptr->engineIDLen + 2 + i] =
- (oid) uptr->name[i];
- }
- return indexOid;
- } /* end usm_generate_OID() */
- /*
- * usm_parse_oid(): parses an index to the usmTable to break it down into
- * a engineID component and a name component. The results are stored in:
- *
- * **engineID: a newly malloced string.
- * *engineIDLen: The length of the malloced engineID string above.
- * **name: a newly malloced string.
- * *nameLen: The length of the malloced name string above.
- *
- * returns 1 if an error is encountered, or 0 if successful.
- */
- int
- usm_parse_oid(oid * oidIndex, size_t oidLen,
- unsigned char **engineID, size_t * engineIDLen,
- unsigned char **name, size_t * nameLen)
- {
- int nameL;
- int engineIDL;
- int i;
- /*
- * first check the validity of the oid
- */
- if ((oidLen <= 0) || (!oidIndex)) {
- DEBUGMSGTL(("usmUser",
- "parse_oid: null oid or zero length oid passed inn"));
- return 1;
- }
- engineIDL = *oidIndex; /* initial engineID length */
- if ((int) oidLen < engineIDL + 2) {
- DEBUGMSGTL(("usmUser",
- "parse_oid: invalid oid length: less than the engineIDLenn"));
- return 1;
- }
- nameL = oidIndex[engineIDL + 1]; /* the initial name length */
- if ((int) oidLen != engineIDL + nameL + 2) {
- DEBUGMSGTL(("usmUser",
- "parse_oid: invalid oid length: length is not exactn"));
- return 1;
- }
- /*
- * its valid, malloc the space and store the results
- */
- if (engineID == NULL || name == NULL) {
- DEBUGMSGTL(("usmUser",
- "parse_oid: null storage pointer passed in.n"));
- return 1;
- }
- *engineID = (unsigned char *) malloc(engineIDL);
- if (*engineID == NULL) {
- DEBUGMSGTL(("usmUser",
- "parse_oid: malloc of the engineID failedn"));
- return 1;
- }
- *engineIDLen = engineIDL;
- *name = (unsigned char *) malloc(nameL + 1);
- if (*name == NULL) {
- DEBUGMSGTL(("usmUser", "parse_oid: malloc of the name failedn"));
- free(*engineID);
- return 1;
- }
- *nameLen = nameL;
- for (i = 0; i < engineIDL; i++) {
- if (oidIndex[i + 1] > 255) {
- goto UPO_parse_error;
- }
- engineID[0][i] = (unsigned char) oidIndex[i + 1];
- }
- for (i = 0; i < nameL; i++) {
- if (oidIndex[i + 2 + engineIDL] > 255) {
- UPO_parse_error:
- free(*engineID);
- free(*name);
- return 1;
- }
- name[0][i] = (unsigned char) oidIndex[i + 2 + engineIDL];
- }
- name[0][nameL] = 0;
- return 0;
- } /* end usm_parse_oid() */
- /*******************************************************************-o-******
- * usm_parse_user
- *
- * Parameters:
- * *name Complete OID indexing a given usmUser entry.
- * name_length
- *
- * Returns:
- * Pointer to a usmUser -OR-
- * NULL if name does not convert to a usmUser.
- *
- * Convert an (full) OID and return a pointer to a matching user in the
- * user list if one exists.
- */
- struct usmUser *
- usm_parse_user(oid * name, size_t name_len)
- {
- struct usmUser *uptr;
- char *newName;
- u_char *engineID;
- size_t nameLen, engineIDLen;
- /*
- * get the name and engineID out of the incoming oid
- */
- if (usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
- &engineID, &engineIDLen, (u_char **) & newName,
- &nameLen))
- return NULL;
- /*
- * Now see if a user exists with these index values
- */
- uptr = usm_get_user(engineID, engineIDLen, newName);
- free(engineID);
- free(newName);
- return uptr;
- } /* end usm_parse_user() */
- /*******************************************************************-o-******
- * var_usmUser
- *
- * Parameters:
- * *vp (I) Variable-binding associated with this action.
- * *name (I/O) Input name requested, output name found.
- * *length (I/O) Length of input and output oid's.
- * exact (I) TRUE if an exact match was requested.
- * *var_len (O) Length of variable or 0 if function returned.
- * (**write_method) Hook to name a write method (UNUSED).
- *
- * Returns:
- * Pointer to (char *) containing related data of length 'length'
- * (May be NULL.)
- *
- *
- * Call-back function passed to the agent in order to return information
- * for the USM MIB tree.
- *
- *
- * If this invocation is not for USMUSERSPINLOCK, lookup user name
- * in the usmUser list.
- *
- * If the name does not match any user and the request
- * is for an exact match, -or- if the usmUser list is empty, create a
- * new list entry.
- *
- * Finally, service the given USMUSER* var-bind. A NULL user generally
- * results in a NULL return value.
- */
- u_char *
- var_usmUser(struct variable * vp,
- oid * name,
- size_t * length,
- int exact, size_t * var_len, WriteMethod ** write_method)
- {
- struct usmUser *uptr = NULL, *nptr, *pptr;
- int i, rtest, result;
- oid *indexOid;
- size_t len;
- /*
- * variables we may use later
- */
- static long long_ret;
- static u_char string[1];
- static oid objid[2]; /* for .0.0 */
- *write_method = 0; /* assume it isnt writable for the time being */
- *var_len = sizeof(long_ret); /* assume an integer and change later if not */
- if (vp->magic != USMUSERSPINLOCK) {
- oid newname[MAX_OID_LEN];
- len = (*length < vp->namelen) ? *length : vp->namelen;
- rtest = snmp_oid_compare(name, len, vp->name, len);
- if (rtest > 0 ||
- /*
- * (rtest == 0 && !exact && (int) vp->namelen+1 < (int) *length) ||
- */
- (exact == 1 && rtest != 0)) {
- if (var_len)
- *var_len = 0;
- return 0;
- }
- memset(newname, 0, sizeof(newname));
- if (((int) *length) <= (int) vp->namelen || rtest == -1) {
- /*
- * oid is not within our range yet
- */
- /*
- * need to fail if not exact
- */
- uptr = usm_get_userList();
- } else {
- for (nptr = usm_get_userList(), pptr = NULL, uptr = NULL;
- nptr != NULL; pptr = nptr, nptr = nptr->next) {
- indexOid =
- usm_generate_OID(vp->name, vp->namelen, nptr, &len);
- result = snmp_oid_compare(name, *length, indexOid, len);
- DEBUGMSGTL(("usmUser", "Checking user: %s - ",
- nptr->name));
- for (i = 0; i < (int) nptr->engineIDLen; i++) {
- DEBUGMSG(("usmUser", " %x", nptr->engineID[i]));
- }
- DEBUGMSG(("usmUser", " - %d n -> OID: ", result));
- DEBUGMSGOID(("usmUser", indexOid, len));
- DEBUGMSG(("usmUser", "n"));
- free(indexOid);
- if (exact) {
- if (result == 0) {
- uptr = nptr;
- }
- } else {
- if (result == 0) {
- /*
- * found an exact match. Need the next one for !exact
- */
- uptr = nptr->next;
- } else if (result == -1) {
- uptr = nptr;
- break;
- }
- }
- }
- } /* endif -- name <= vp->name */
- /*
- * if uptr is NULL and exact we need to continue for creates
- */
- if (uptr == NULL && !exact)
- return (NULL);
- if (uptr) {
- indexOid = usm_generate_OID(vp->name, vp->namelen, uptr, &len);
- *length = len;
- memmove(name, indexOid, len * sizeof(oid));
- DEBUGMSGTL(("usmUser", "Found user: %s - ", uptr->name));
- for (i = 0; i < (int) uptr->engineIDLen; i++) {
- DEBUGMSG(("usmUser", " %x", uptr->engineID[i]));
- }
- DEBUGMSG(("usmUser", "n -> OID: "));
- DEBUGMSGOID(("usmUser", indexOid, len));
- DEBUGMSG(("usmUser", "n"));
- free(indexOid);
- }
- } else {
- if (header_generic(vp, name, length, exact, var_len, write_method))
- return 0;
- } /* endif -- vp->magic != USMUSERSPINLOCK */
- switch (vp->magic) {
- case USMUSERSPINLOCK:
- *write_method = write_usmUserSpinLock;
- long_ret = usmUserSpinLock;
- return (unsigned char *) &long_ret;
- case USMUSERSECURITYNAME:
- if (uptr) {
- *var_len = strlen(uptr->secName);
- return (unsigned char *) uptr->secName;
- }
- return NULL;
- case USMUSERCLONEFROM:
- *write_method = write_usmUserCloneFrom;
- if (uptr) {
- objid[0] = 0; /* "When this object is read, the ZeroDotZero OID */
- objid[1] = 0; /* is returned." */
- *var_len = sizeof(oid) * 2;
- return (unsigned char *) objid;
- }
- return NULL;
- case USMUSERAUTHPROTOCOL:
- *write_method = write_usmUserAuthProtocol;
- if (uptr) {
- *var_len = uptr->authProtocolLen * sizeof(oid);
- return (u_char *) uptr->authProtocol;
- }
- return NULL;
- case USMUSERAUTHKEYCHANGE:
- case USMUSEROWNAUTHKEYCHANGE:
- /*
- * we treat these the same, and let the calling module
- * distinguish between them
- */
- *write_method = write_usmUserAuthKeyChange;
- if (uptr) {
- *string = 0; /* always return a NULL string */
- *var_len = 0;
- return string;
- }
- return NULL;
- case USMUSERPRIVPROTOCOL:
- *write_method = write_usmUserPrivProtocol;
- if (uptr) {
- *var_len = uptr->privProtocolLen * sizeof(oid);
- return (u_char *) uptr->privProtocol;
- }
- return NULL;
- case USMUSERPRIVKEYCHANGE:
- case USMUSEROWNPRIVKEYCHANGE:
- /*
- * we treat these the same, and let the calling module
- * distinguish between them
- */
- *write_method = write_usmUserPrivKeyChange;
- if (uptr) {
- *string = 0; /* always return a NULL string */
- *var_len = 0;
- return string;
- }
- return NULL;
- case USMUSERPUBLIC:
- *write_method = write_usmUserPublic;
- if (uptr) {
- if (uptr->userPublicString) {
- *var_len = strlen((char *) uptr->userPublicString);
- return uptr->userPublicString;
- }
- *string = 0;
- *var_len = 0; /* return an empty string if the public
- * string hasn't been defined yet */
- return string;
- }
- return NULL;
- case USMUSERSTORAGETYPE:
- *write_method = write_usmUserStorageType;
- if (uptr) {
- long_ret = uptr->userStorageType;
- return (unsigned char *) &long_ret;
- }
- return NULL;
- case USMUSERSTATUS:
- *write_method = write_usmUserStatus;
- if (uptr) {
- long_ret = uptr->userStatus;
- return (unsigned char *) &long_ret;
- }
- return NULL;
- default:
- DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_usmUsern",
- vp->magic));
- }
- return 0;
- } /* end var_usmUser() */
- /*
- * write_usmUserSpinLock(): called when a set is performed on the
- * usmUserSpinLock object
- */
- int
- write_usmUserSpinLock(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;
- if (var_val_type != ASN_INTEGER) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserSpinLock not ASN_INTEGERn"));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len > sizeof(long_ret)) {
- DEBUGMSGTL(("usmUser", "write to usmUserSpinLock: bad lengthn"));
- return SNMP_ERR_WRONGLENGTH;
- }
- long_ret = *((long *) var_val);
- if (long_ret != (long) usmUserSpinLock)
- return SNMP_ERR_INCONSISTENTVALUE;
- if (action == COMMIT) {
- if (usmUserSpinLock == 2147483647)
- usmUserSpinLock = 0;
- else
- usmUserSpinLock++;
- }
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserSpinLock() */
- /*******************************************************************-o-******
- * write_usmUserCloneFrom
- *
- * Parameters:
- * action
- * *var_val
- * var_val_type
- * var_val_len
- * *statP (UNUSED)
- * *name OID of user to clone from.
- * name_len
- *
- * Returns:
- * SNMP_ERR_NOERROR On success -OR- If user exists
- * and has already been cloned.
- * SNMP_ERR_GENERR Local function call failures.
- * SNMP_ERR_INCONSISTENTNAME 'name' does not exist in user list
- * -OR- user to clone from != RS_ACTIVE.
- * SNMP_ERR_WRONGLENGTH OID length > than local buffer size.
- * SNMP_ERR_WRONGTYPE ASN_OBJECT_ID is wrong.
- *
- *
- * XXX: should handle action=UNDO's.
- */
- int
- write_usmUserCloneFrom(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)
- {
- struct usmUser *uptr, *cloneFrom;
- if (action == RESERVE1) {
- if (var_val_type != ASN_OBJECT_ID) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserCloneFrom not ASN_OBJECT_IDn"));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len > USM_LENGTH_OID_MAX * sizeof(oid) ||
- var_val_len % sizeof(oid) != 0) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserCloneFrom: bad lengthn"));
- return SNMP_ERR_WRONGLENGTH;
- }
- } else if (action == RESERVE2) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- /*
- * We don't allow creations here.
- */
- return SNMP_ERR_INCONSISTENTNAME;
- }
- /*
- * Has the user already been cloned? If so, writes to this variable
- * are defined to have no effect and to produce no error.
- */
- if (uptr->cloneFrom != NULL) {
- return SNMP_ERR_NOERROR;
- }
- cloneFrom =
- usm_parse_user((oid *) var_val, var_val_len / sizeof(oid));
- if (cloneFrom == NULL || cloneFrom->userStatus != SNMP_ROW_ACTIVE) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- uptr->cloneFrom = snmp_duplicate_objid((oid *) var_val,
- var_val_len / sizeof(oid));
- usm_cloneFrom_user(cloneFrom, uptr);
- if (usmStatusCheck(uptr) && uptr->userStatus == SNMP_ROW_NOTREADY) {
- uptr->userStatus = SNMP_ROW_NOTINSERVICE;
- }
- }
- return SNMP_ERR_NOERROR;
- }
- /*******************************************************************-o-******
- * write_usmUserAuthProtocol
- *
- * Parameters:
- * action
- * *var_val OID of auth transform to set.
- * var_val_type
- * var_val_len
- * *statP
- * *name OID of user upon which to perform set operation.
- * name_len
- *
- * Returns:
- * SNMP_ERR_NOERROR On success.
- * SNMP_ERR_GENERR
- * SNMP_ERR_INCONSISTENTVALUE
- * SNMP_ERR_NOSUCHNAME
- * SNMP_ERR_WRONGLENGTH
- * SNMP_ERR_WRONGTYPE
- */
- int
- write_usmUserAuthProtocol(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 oid *optr;
- static size_t olen;
- static int resetOnFail;
- struct usmUser *uptr;
- if (action == RESERVE1) {
- resetOnFail = 0;
- if (var_val_type != ASN_OBJECT_ID) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserAuthProtocol not ASN_OBJECT_IDn"));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len > USM_LENGTH_OID_MAX * sizeof(oid) ||
- var_val_len % sizeof(oid) != 0) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserAuthProtocol: bad lengthn"));
- return SNMP_ERR_WRONGLENGTH;
- }
- } else if (action == RESERVE2) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if (uptr->userStatus == RS_ACTIVE
- || uptr->userStatus == RS_NOTREADY
- || uptr->userStatus == RS_NOTINSERVICE) {
- /*
- * The authProtocol is already set. It is only legal to CHANGE it
- * to usmNoAuthProtocol...
- */
- if (snmp_oid_compare
- ((oid *) var_val, var_val_len / sizeof(oid),
- usmNoAuthProtocol,
- sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0) {
- /*
- * ... and then only if the privProtocol is equal to
- * usmNoPrivProtocol.
- */
- if (snmp_oid_compare
- (uptr->privProtocol, uptr->privProtocolLen,
- usmNoPrivProtocol,
- sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0) {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- optr = uptr->authProtocol;
- olen = uptr->authProtocolLen;
- resetOnFail = 1;
- uptr->authProtocol = snmp_duplicate_objid((oid *) var_val,
- var_val_len /
- sizeof(oid));
- if (uptr->authProtocol == NULL) {
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->authProtocolLen = var_val_len / sizeof(oid);
- } else
- if (snmp_oid_compare
- ((oid *) var_val, var_val_len / sizeof(oid),
- uptr->authProtocol, uptr->authProtocolLen) == 0) {
- /*
- * But it's also okay to set it to the same thing as it
- * currently is.
- */
- return SNMP_ERR_NOERROR;
- } else {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- } else {
- /*
- * This row is under creation. It's okay to set
- * usmUserAuthProtocol to any valid authProtocol but it will be
- * overwritten when usmUserCloneFrom is set (so don't write it if
- * that has already been set).
- */
- if (snmp_oid_compare
- ((oid *) var_val, var_val_len / sizeof(oid),
- usmNoAuthProtocol,
- sizeof(usmNoAuthProtocol) / sizeof(oid)) == 0
- #ifndef DISABLE_MD5
- || snmp_oid_compare((oid *) var_val,
- var_val_len / sizeof(oid),
- usmHMACMD5AuthProtocol,
- sizeof(usmHMACMD5AuthProtocol) /
- sizeof(oid)) == 0
- #endif
- || snmp_oid_compare((oid *) var_val,
- var_val_len / sizeof(oid),
- usmHMACSHA1AuthProtocol,
- sizeof(usmHMACSHA1AuthProtocol) /
- sizeof(oid)) == 0) {
- if (uptr->cloneFrom != NULL) {
- optr = uptr->authProtocol;
- olen = uptr->authProtocolLen;
- resetOnFail = 1;
- uptr->authProtocol =
- snmp_duplicate_objid((oid *) var_val,
- var_val_len / sizeof(oid));
- if (uptr->authProtocol == NULL) {
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->authProtocolLen = var_val_len / sizeof(oid);
- }
- } else {
- /*
- * Unknown authentication protocol.
- */
- return SNMP_ERR_WRONGVALUE;
- }
- }
- } else if (action == COMMIT) {
- SNMP_FREE(optr);
- optr = NULL;
- } else if (action == FREE || action == UNDO) {
- if ((uptr = usm_parse_user(name, name_len)) != NULL) {
- if (resetOnFail) {
- SNMP_FREE(uptr->authProtocol);
- uptr->authProtocol = optr;
- uptr->authProtocolLen = olen;
- }
- }
- }
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserAuthProtocol() */
- /*******************************************************************-o-******
- * write_usmUserAuthKeyChange
- *
- * Parameters:
- * action
- * *var_val Octet string representing new KeyChange value.
- * var_val_type
- * var_val_len
- * *statP (UNUSED)
- * *name OID of user upon which to perform set operation.
- * name_len
- *
- * Returns:
- * SNMP_ERR_NOERR Success.
- * SNMP_ERR_WRONGTYPE
- * SNMP_ERR_WRONGLENGTH
- * SNMP_ERR_NOSUCHNAME
- * SNMP_ERR_GENERR
- *
- * Note: This function handles both the usmUserAuthKeyChange and
- * usmUserOwnAuthKeyChange objects. We are not passed the name
- * of the user requseting the keychange, so we leave this to the
- * calling module to verify when and if we should be called. To
- * change this would require a change in the mib module API to
- * pass in the securityName requesting the change.
- *
- * XXX: should handle action=UNDO's.
- */
- int
- write_usmUserAuthKeyChange(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)
- {
- struct usmUser *uptr;
- unsigned char buf[SNMP_MAXBUF_SMALL];
- size_t buflen = SNMP_MAXBUF_SMALL;
- const char fnAuthKey[] = "write_usmUserAuthKeyChange";
- const char fnOwnAuthKey[] = "write_usmUserOwnAuthKeyChange";
- const char *fname;
- static unsigned char *oldkey;
- static size_t oldkeylen;
- static int resetOnFail;
- if (name[USM_MIB_LENGTH - 1] == 6) {
- fname = fnAuthKey;
- } else {
- fname = fnOwnAuthKey;
- }
- if (action == RESERVE1) {
- resetOnFail = 0;
- if (var_val_type != ASN_OCTET_STR) {
- DEBUGMSGTL(("usmUser", "write to %s not ASN_OCTET_STRn",
- fname));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len == 0) {
- return SNMP_ERR_WRONGLENGTH;
- }
- } else if (action == RESERVE2) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- } else {
- #ifndef DISABLE_MD5
- if (snmp_oid_compare(uptr->authProtocol, uptr->authProtocolLen,
- usmHMACMD5AuthProtocol,
- sizeof(usmHMACMD5AuthProtocol) /
- sizeof(oid)) == 0) {
- if (var_val_len != 0 && var_val_len != 32) {
- return SNMP_ERR_WRONGLENGTH;
- }
- } else
- #endif
- if (snmp_oid_compare
- (uptr->authProtocol, uptr->authProtocolLen,
- usmHMACSHA1AuthProtocol,
- sizeof(usmHMACSHA1AuthProtocol) / sizeof(oid)) == 0) {
- if (var_val_len != 0 && var_val_len != 40) {
- return SNMP_ERR_WRONGLENGTH;
- }
- }
- }
- } else if (action == ACTION) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if (uptr->cloneFrom == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if (snmp_oid_compare(uptr->authProtocol, uptr->authProtocolLen,
- usmNoAuthProtocol,
- sizeof(usmNoAuthProtocol) / sizeof(oid)) ==
- 0) {
- /*
- * "When the value of the corresponding usmUserAuthProtocol is
- * usmNoAuthProtocol, then a set is successful, but effectively
- * is a no-op."
- */
- DEBUGMSGTL(("usmUser",
- "%s: noAuthProtocol keyChange... success!n",
- fname));
- return SNMP_ERR_NOERROR;
- }
- /*
- * Change the key.
- */
- DEBUGMSGTL(("usmUser", "%s: changing auth key for user %sn",
- fname, uptr->secName));
- if (decode_keychange(uptr->authProtocol, uptr->authProtocolLen,
- uptr->authKey, uptr->authKeyLen,
- var_val, var_val_len,
- buf, &buflen) != SNMPERR_SUCCESS) {
- DEBUGMSGTL(("usmUser", "%s: ... failedn", fname));
- return SNMP_ERR_GENERR;
- }
- DEBUGMSGTL(("usmUser", "%s: ... succeededn", fname));
- resetOnFail = 1;
- oldkey = uptr->authKey;
- oldkeylen = uptr->authKeyLen;
- memdup(&uptr->authKey, buf, buflen);
- if (uptr->authKey == NULL) {
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->authKeyLen = buflen;
- } else if (action == COMMIT) {
- SNMP_FREE(oldkey);
- oldkey = NULL;
- } else if (action == UNDO) {
- if ((uptr = usm_parse_user(name, name_len)) != NULL && resetOnFail) {
- SNMP_FREE(uptr->authKey);
- uptr->authKey = oldkey;
- uptr->authKeyLen = oldkeylen;
- }
- }
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserAuthKeyChange() */
- int
- write_usmUserPrivProtocol(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 oid *optr;
- static size_t olen;
- static int resetOnFail;
- struct usmUser *uptr;
- if (action == RESERVE1) {
- resetOnFail = 0;
- if (var_val_type != ASN_OBJECT_ID) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserPrivProtocol not ASN_OBJECT_IDn"));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len > USM_LENGTH_OID_MAX * sizeof(oid) ||
- var_val_len % sizeof(oid) != 0) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserPrivProtocol: bad lengthn"));
- return SNMP_ERR_WRONGLENGTH;
- }
- } else if (action == RESERVE2) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if (uptr->userStatus == RS_ACTIVE
- || uptr->userStatus == RS_NOTREADY
- || uptr->userStatus == RS_NOTINSERVICE) {
- /*
- * The privProtocol is already set. It is only legal to CHANGE it
- * to usmNoPrivProtocol.
- */
- if (snmp_oid_compare
- ((oid *) var_val, var_val_len / sizeof(oid),
- usmNoPrivProtocol,
- sizeof(usmNoPrivProtocol) / sizeof(oid)) == 0) {
- resetOnFail = 1;
- optr = uptr->privProtocol;
- olen = uptr->privProtocolLen;
- uptr->privProtocol = snmp_duplicate_objid((oid *) var_val,
- var_val_len /
- sizeof(oid));
- if (uptr->privProtocol == NULL) {
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->privProtocolLen = var_val_len / sizeof(oid);
- } else
- if (snmp_oid_compare
- ((oid *) var_val, var_val_len / sizeof(oid),
- uptr->privProtocol, uptr->privProtocolLen) == 0) {
- /*
- * But it's also okay to set it to the same thing as it
- * currently is.
- */
- return SNMP_ERR_NOERROR;
- } else {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- } else {
- /*
- * This row is under creation. It's okay to set
- * usmUserPrivProtocol to any valid privProtocol with the proviso
- * that if usmUserAuthProtocol is set to usmNoAuthProtocol, it may
- * only be set to usmNoPrivProtocol. The value will be overwritten
- * when usmUserCloneFrom is set (so don't write it if that has
- * already been set).
- */
- if (snmp_oid_compare(uptr->authProtocol, uptr->authProtocolLen,
- usmNoAuthProtocol,
- sizeof(usmNoAuthProtocol) /
- sizeof(oid)) == 0) {
- if (snmp_oid_compare
- ((oid *) var_val, var_val_len / sizeof(oid),
- usmNoPrivProtocol,
- sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0) {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- } else {
- if (snmp_oid_compare
- ((oid *) var_val, var_val_len / sizeof(oid),
- usmNoPrivProtocol,
- sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0
- #ifndef DISABLE_DES
- && snmp_oid_compare((oid *) var_val,
- var_val_len / sizeof(oid),
- usmDESPrivProtocol,
- sizeof(usmDESPrivProtocol) /
- sizeof(oid) != 0)
- #endif
- && snmp_oid_compare((oid *) var_val,
- var_val_len / sizeof(oid),
- usmAESPrivProtocol,
- sizeof(usmAESPrivProtocol) /
- sizeof(oid) != 0)) {
- return SNMP_ERR_WRONGVALUE;
- }
- }
- resetOnFail = 1;
- optr = uptr->privProtocol;
- olen = uptr->privProtocolLen;
- uptr->privProtocol = snmp_duplicate_objid((oid *) var_val,
- var_val_len /
- sizeof(oid));
- if (uptr->privProtocol == NULL) {
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->privProtocolLen = var_val_len / sizeof(oid);
- }
- } else if (action == COMMIT) {
- SNMP_FREE(optr);
- optr = NULL;
- } else if (action == FREE || action == UNDO) {
- if ((uptr = usm_parse_user(name, name_len)) != NULL) {
- if (resetOnFail) {
- SNMP_FREE(uptr->privProtocol);
- uptr->privProtocol = optr;
- uptr->privProtocolLen = olen;
- }
- }
- }
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserPrivProtocol() */
- /*
- * Note: This function handles both the usmUserPrivKeyChange and
- * usmUserOwnPrivKeyChange objects. We are not passed the name
- * of the user requseting the keychange, so we leave this to the
- * calling module to verify when and if we should be called. To
- * change this would require a change in the mib module API to
- * pass in the securityName requesting the change.
- *
- */
- int
- write_usmUserPrivKeyChange(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)
- {
- struct usmUser *uptr;
- unsigned char buf[SNMP_MAXBUF_SMALL];
- size_t buflen = SNMP_MAXBUF_SMALL;
- const char fnPrivKey[] = "write_usmUserPrivKeyChange";
- const char fnOwnPrivKey[] = "write_usmUserOwnPrivKeyChange";
- const char *fname;
- static unsigned char *oldkey;
- static size_t oldkeylen;
- static int resetOnFail;
- if (name[USM_MIB_LENGTH - 1] == 9) {
- fname = fnPrivKey;
- } else {
- fname = fnOwnPrivKey;
- }
- if (action == RESERVE1) {
- resetOnFail = 0;
- if (var_val_type != ASN_OCTET_STR) {
- DEBUGMSGTL(("usmUser", "write to %s not ASN_OCTET_STRn",
- fname));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len == 0) {
- return SNMP_ERR_WRONGLENGTH;
- }
- } else if (action == RESERVE2) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- } else {
- #ifndef DISABLE_DES
- if (snmp_oid_compare(uptr->privProtocol, uptr->privProtocolLen,
- usmDESPrivProtocol,
- sizeof(usmDESPrivProtocol) /
- sizeof(oid)) == 0) {
- if (var_val_len != 0 && var_val_len != 32) {
- return SNMP_ERR_WRONGLENGTH;
- }
- }
- #endif
- if (snmp_oid_compare(uptr->privProtocol, uptr->privProtocolLen,
- usmAESPrivProtocol,
- sizeof(usmAESPrivProtocol) /
- sizeof(oid)) == 0) {
- if (var_val_len != 0 && var_val_len != 32) {
- return SNMP_ERR_WRONGLENGTH;
- }
- }
- }
- } else if (action == ACTION) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if (uptr->cloneFrom == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if (snmp_oid_compare(uptr->privProtocol, uptr->privProtocolLen,
- usmNoPrivProtocol,
- sizeof(usmNoPrivProtocol) / sizeof(oid)) ==
- 0) {
- /*
- * "When the value of the corresponding usmUserPrivProtocol is
- * usmNoPrivProtocol, then a set is successful, but effectively
- * is a no-op."
- */
- DEBUGMSGTL(("usmUser",
- "%s: noPrivProtocol keyChange... success!n",
- fname));
- return SNMP_ERR_NOERROR;
- }
- /*
- * Change the key.
- */
- DEBUGMSGTL(("usmUser", "%s: changing priv key for user %sn",
- fname, uptr->secName));
- if (decode_keychange(uptr->authProtocol, uptr->authProtocolLen,
- uptr->privKey, uptr->privKeyLen,
- var_val, var_val_len,
- buf, &buflen) != SNMPERR_SUCCESS) {
- DEBUGMSGTL(("usmUser", "%s: ... failedn", fname));
- return SNMP_ERR_GENERR;
- }
- DEBUGMSGTL(("usmUser", "%s: ... succeededn", fname));
- resetOnFail = 1;
- oldkey = uptr->privKey;
- oldkeylen = uptr->privKeyLen;
- memdup(&uptr->privKey, buf, buflen);
- if (uptr->privKey == NULL) {
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->privKeyLen = buflen;
- } else if (action == COMMIT) {
- SNMP_FREE(oldkey);
- oldkey = NULL;
- } else if (action == UNDO) {
- if ((uptr = usm_parse_user(name, name_len)) != NULL && resetOnFail) {
- SNMP_FREE(uptr->privKey);
- uptr->privKey = oldkey;
- uptr->privKeyLen = oldkeylen;
- }
- }
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserPrivKeyChange() */
- int
- write_usmUserPublic(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)
- {
- struct usmUser *uptr = NULL;
- if (var_val_type != ASN_OCTET_STR) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserPublic not ASN_OCTET_STRn"));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len < 0 || var_val_len > 32) {
- DEBUGMSGTL(("usmUser", "write to usmUserPublic: bad lengthn"));
- return SNMP_ERR_WRONGLENGTH;
- }
- if (action == COMMIT) {
- /*
- * don't allow creations here
- */
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_NOSUCHNAME;
- }
- if (uptr->userPublicString)
- free(uptr->userPublicString);
- uptr->userPublicString = (u_char *) malloc(var_val_len + 1);
- if (uptr->userPublicString == NULL) {
- return SNMP_ERR_GENERR;
- }
- memcpy(uptr->userPublicString, var_val, var_val_len);
- uptr->userPublicString[var_val_len] = 0;
- DEBUGMSG(("usmUser", "setting public string: %d - %sn",
- var_val_len, uptr->userPublicString));
- }
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserPublic() */
- int
- write_usmUserStorageType(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 long_ret = *((long *) var_val);
- static long oldValue;
- struct usmUser *uptr;
- static int resetOnFail;
- if (action == RESERVE1) {
- resetOnFail = 0;
- if (var_val_type != ASN_INTEGER) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserStorageType not ASN_INTEGERn"));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len != sizeof(long)) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserStorageType: bad lengthn"));
- return SNMP_ERR_WRONGLENGTH;
- }
- if (long_ret < 1 || long_ret > 5) {
- return SNMP_ERR_WRONGVALUE;
- }
- } else if (action == RESERVE2) {
- if ((uptr = usm_parse_user(name, name_len)) == NULL) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if ((long_ret == ST_VOLATILE || long_ret == ST_NONVOLATILE) &&
- (uptr->userStorageType == ST_VOLATILE ||
- uptr->userStorageType == ST_NONVOLATILE)) {
- oldValue = uptr->userStorageType;
- uptr->userStorageType = long_ret;
- resetOnFail = 1;
- } else {
- /*
- * From RFC2574:
- *
- * "Note that any user who employs authentication or privacy must
- * allow its secret(s) to be updated and thus cannot be 'readOnly'.
- *
- * If an initial set operation tries to set the value to 'readOnly'
- * for a user who employs authentication or privacy, then an
- * 'inconsistentValue' error must be returned. Note that if the
- * value has been previously set (implicit or explicit) to any
- * value, then the rules as defined in the StorageType Textual
- * Convention apply.
- */
- DEBUGMSGTL(("usmUser",
- "long_ret %d uptr->st %d uptr->status %dn",
- long_ret, uptr->userStorageType,
- uptr->userStatus));
- if (long_ret == ST_READONLY &&
- uptr->userStorageType != ST_READONLY &&
- (uptr->userStatus == RS_ACTIVE ||
- uptr->userStatus == RS_NOTINSERVICE)) {
- return SNMP_ERR_WRONGVALUE;
- } else if (long_ret == ST_READONLY &&
- (snmp_oid_compare
- (uptr->privProtocol, uptr->privProtocolLen,
- usmNoPrivProtocol,
- sizeof(usmNoPrivProtocol) / sizeof(oid)) != 0
- || snmp_oid_compare(uptr->authProtocol,
- uptr->authProtocolLen,
- usmNoAuthProtocol,
- sizeof(usmNoAuthProtocol) /
- sizeof(oid)) != 0)) {
- return SNMP_ERR_INCONSISTENTVALUE;
- } else {
- return SNMP_ERR_WRONGVALUE;
- }
- }
- } else if (action == UNDO || action == FREE) {
- if ((uptr = usm_parse_user(name, name_len)) != NULL && resetOnFail) {
- uptr->userStorageType = oldValue;
- }
- }
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserStorageType() */
- /*
- * Return 1 if enough objects have been set up to transition rowStatus to
- * notInService(2) or active(1).
- */
- int
- usmStatusCheck(struct usmUser *uptr)
- {
- if (uptr == NULL) {
- return 0;
- } else {
- if (uptr->cloneFrom == NULL) {
- return 0;
- }
- }
- return 1;
- }
- /*******************************************************************-o-******
- * write_usmUserStatus
- *
- * Parameters:
- * action
- * *var_val
- * var_val_type
- * var_val_len
- * *statP
- * *name
- * name_len
- *
- * Returns:
- * SNMP_ERR_NOERROR On success.
- * SNMP_ERR_GENERR
- * SNMP_ERR_INCONSISTENTNAME
- * SNMP_ERR_INCONSISTENTVALUE
- * SNMP_ERR_WRONGLENGTH
- * SNMP_ERR_WRONGTYPE
- */
- int
- write_usmUserStatus(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;
- unsigned char *engineID;
- size_t engineIDLen;
- char *newName;
- size_t nameLen;
- struct usmUser *uptr = NULL;
- if (action == RESERVE1) {
- if (var_val_type != ASN_INTEGER) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserStatus not ASN_INTEGERn"));
- return SNMP_ERR_WRONGTYPE;
- }
- if (var_val_len != sizeof(long_ret)) {
- DEBUGMSGTL(("usmUser",
- "write to usmUserStatus: bad lengthn"));
- 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 engineID/name first.
- */
- if (usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
- &engineID, &engineIDLen, (u_char **) & newName,
- &nameLen)) {
- return SNMP_ERR_INCONSISTENTNAME;
- }
- if (engineIDLen < 5 || engineIDLen > 32 || nameLen < 1
- || nameLen > 32) {
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- return SNMP_ERR_NOCREATION;
- }
- /*
- * Now see if a user already exists with these index values.
- */
- uptr = usm_get_user(engineID, engineIDLen, newName);
- if (uptr != NULL) {
- if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- long_ret = RS_NOTREADY;
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- } else {
- if (long_ret == RS_ACTIVE || long_ret == RS_NOTINSERVICE) {
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
- if ((uptr = usm_create_user()) == NULL) {
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->engineID = engineID;
- uptr->name = newName;
- uptr->secName = strdup(uptr->name);
- if (uptr->secName == NULL) {
- usm_free_user(uptr);
- return SNMP_ERR_RESOURCEUNAVAILABLE;
- }
- uptr->engineIDLen = engineIDLen;
- /*
- * Set status to createAndGo or createAndWait so we can tell
- * that this row is under creation.
- */
- uptr->userStatus = long_ret;
- /*
- * Add to the list of users (we will take it off again
- * later if something goes wrong).
- */
- usm_add_user(uptr);
- } else {
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- }
- }
- } else if (action == ACTION) {
- usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
- &engineID, &engineIDLen, (u_char **) & newName,
- &nameLen);
- uptr = usm_get_user(engineID, engineIDLen, newName);
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- if (uptr != NULL) {
- if (long_ret == RS_CREATEANDGO || long_ret == RS_ACTIVE) {
- if (usmStatusCheck(uptr)) {
- uptr->userStatus = RS_ACTIVE;
- } else {
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- } else if (long_ret == RS_CREATEANDWAIT) {
- if (usmStatusCheck(uptr)) {
- uptr->userStatus = RS_NOTINSERVICE;
- } else {
- uptr->userStatus = RS_NOTREADY;
- }
- } else if (long_ret == RS_NOTINSERVICE) {
- if (uptr->userStatus == RS_ACTIVE ||
- uptr->userStatus == RS_NOTINSERVICE) {
- uptr->userStatus = RS_NOTINSERVICE;
- } else {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- }
- }
- } else if (action == COMMIT) {
- usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
- &engineID, &engineIDLen, (u_char **) & newName,
- &nameLen);
- uptr = usm_get_user(engineID, engineIDLen, newName);
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- if (uptr != NULL) {
- if (long_ret == RS_DESTROY) {
- usm_remove_user(uptr);
- usm_free_user(uptr);
- }
- }
- } else if (action == UNDO || action == FREE) {
- usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
- &engineID, &engineIDLen, (u_char **) & newName,
- &nameLen);
- uptr = usm_get_user(engineID, engineIDLen, newName);
- SNMP_FREE(engineID);
- SNMP_FREE(newName);
- if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
- usm_remove_user(uptr);
- usm_free_user(uptr);
- }
- }
- return SNMP_ERR_NOERROR;
- }
- #if 0
- /*
- * see if we can parse the oid for engineID/name first
- */
- if (usm_parse_oid(&name[USM_MIB_LENGTH], name_len - USM_MIB_LENGTH,
- &engineID, &engineIDLen, (u_char **) & newName,
- &nameLen))
- return SNMP_ERR_INCONSISTENTNAME;
- /*
- * Now see if a user already exists with these index values
- */
- uptr = usm_get_user(engineID, engineIDLen, newName);
- if (uptr) { /* If so, we set the appropriate value... */
- free(engineID);
- free(newName);
- if (long_ret == RS_CREATEANDGO || long_ret == RS_CREATEANDWAIT) {
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- if (long_ret == RS_DESTROY) {
- usm_remove_user(uptr);
- usm_free_user(uptr);
- } else {
- uptr->userStatus = long_ret;
- }
- } else { /* ...else we create a new user */
- /*
- * check for a valid status column set
- */
- if (long_ret == RS_ACTIVE || long_ret == RS_NOTINSERVICE) {
- free(engineID);
- free(newName);
- return SNMP_ERR_INCONSISTENTVALUE;
- }
- if (long_ret == RS_DESTROY) {
- /*
- * destroying a non-existent row is actually legal
- */
- free(engineID);
- free(newName);
- return SNMP_ERR_NOERROR;
- }
- /*
- * generate a new user
- */
- if ((uptr = usm_create_user()) == NULL) {
- free(engineID);
- free(newName);
- return SNMP_ERR_GENERR;
- }
- /*
- * copy in the engineID
- */
- uptr->engineID = (unsigned char *) malloc(engineIDLen);
- if (uptr->engineID == NULL) {
- free(engineID);
- free(newName);
- usm_free_user(uptr);
- return SNMP_ERR_GENERR;
- }
- uptr->engineIDLen = engineIDLen;
- memcpy(uptr->engineID, engineID, engineIDLen);
- free(engineID);
- /*
- * copy in the name and secname
- */
- if ((uptr->name = strdup(newName)) == NULL) {
- free(newName);
- usm_free_user(uptr);
- return SNMP_ERR_GENERR;
- }
- free(newName);
- if ((uptr->secName = strdup(uptr->name)) == NULL) {
- usm_free_user(uptr);
- return SNMP_ERR_GENERR;
- }
- /*
- * set the status of the row based on the request
- */
- if (long_ret == RS_CREATEANDGO)
- uptr->userStatus = RS_ACTIVE;
- else if (long_ret == RS_CREATEANDWAIT)
- uptr->userStatus = RS_NOTINSERVICE;
- /*
- * finally, add it to our list of users
- */
- usm_add_user(uptr);
- } /* endif -- uptr */
- } /* endif -- action==COMMIT */
- return SNMP_ERR_NOERROR;
- } /* end write_usmUserStatus() */
- #endif