/* * Creates and allocates a clone of the input PDU, * but does NOT copy the variables. * This function should be used with another function, * such as _copy_pdu_vars. * * Returns a pointer to the cloned PDU if successful. * Returns 0 if failure. */ static netsnmp_pdu * _clone_pdu_header(netsnmp_pdu *pdu) { netsnmp_pdu *newpdu; struct snmp_secmod_def *sptr; newpdu = (netsnmp_pdu *) malloc(sizeof(netsnmp_pdu)); if (!newpdu) return 0; memmove(newpdu, pdu, sizeof(netsnmp_pdu)); /* * reset copied pointers if copy fails */ newpdu->variables = 0; newpdu->enterprise = 0; newpdu->community = 0; newpdu->securityEngineID = 0; newpdu->securityName = 0; newpdu->contextEngineID = 0; newpdu->contextName = 0; newpdu->transport_data = 0; /* * copy buffers individually. If any copy fails, all are freed. */ if (snmp_clone_mem((void **) &newpdu->enterprise, pdu->enterprise, sizeof(oid) * pdu->enterprise_length) || snmp_clone_mem((void **) &newpdu->community, pdu->community, pdu->community_len) || snmp_clone_mem((void **) &newpdu->contextEngineID, pdu->contextEngineID, pdu->contextEngineIDLen) || snmp_clone_mem((void **) &newpdu->securityEngineID, pdu->securityEngineID, pdu->securityEngineIDLen) || snmp_clone_mem((void **) &newpdu->contextName, pdu->contextName, pdu->contextNameLen) || snmp_clone_mem((void **) &newpdu->securityName, pdu->securityName, pdu->securityNameLen) || snmp_clone_mem((void **) &newpdu->transport_data, pdu->transport_data, pdu->transport_data_length)) { snmp_free_pdu(newpdu); return 0; } if ((sptr = find_sec_mod(newpdu->securityModel)) != NULL && sptr->pdu_clone != NULL) { /* * call security model if it needs to know about this */ (*sptr->pdu_clone) (pdu, newpdu); } return newpdu; }
int vacm_check_view_contents(netsnmp_pdu *pdu, oid * name, size_t namelen, int check_subtree, int viewtype, int flags) { struct vacm_accessEntry *ap; struct vacm_groupEntry *gp; struct vacm_viewEntry *vp; char vacm_default_context[1] = ""; const char *contextName = vacm_default_context; const char *sn = NULL; char *vn; const char *pdu_community; /* * len defined by the vacmContextName object */ #define CONTEXTNAMEINDEXLEN 32 char contextNameIndex[CONTEXTNAMEINDEXLEN + 1]; #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) #if defined(NETSNMP_DISABLE_SNMPV1) if (pdu->version == SNMP_VERSION_2c) #else #if defined(NETSNMP_DISABLE_SNMPV2C) if (pdu->version == SNMP_VERSION_1) #else if (pdu->version == SNMP_VERSION_1 || pdu->version == SNMP_VERSION_2c) #endif #endif { pdu_community = (const char *) pdu->community; if (!pdu_community) pdu_community = ""; if (snmp_get_do_debugging()) { char *buf; if (pdu->community) { buf = (char *) malloc(1 + pdu->community_len); memcpy(buf, pdu->community, pdu->community_len); buf[pdu->community_len] = '\0'; } else { DEBUGMSGTL(("mibII/vacm_vars", "NULL community")); buf = strdup("NULL"); } DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: ver=%ld, community=%s\n", pdu->version, buf)); free(buf); } /* * Okay, if this PDU was received from a UDP or a TCP transport then * ask the transport abstraction layer to map its source address and * community string to a security name for us. */ if (0) { #ifdef NETSNMP_TRANSPORT_UDP_DOMAIN } else if (pdu->tDomain == netsnmpUDPDomain #ifdef NETSNMP_TRANSPORT_TCP_DOMAIN || pdu->tDomain == netsnmp_snmpTCPDomain #endif ) { if (!netsnmp_udp_getSecName(pdu->transport_data, pdu->transport_data_length, pdu_community, pdu->community_len, &sn, &contextName)) { /* * There are no com2sec entries. */ sn = NULL; } /* force the community -> context name mapping here */ SNMP_FREE(pdu->contextName); pdu->contextName = strdup(contextName); pdu->contextNameLen = strlen(contextName); #endif #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN } else if (pdu->tDomain == netsnmp_UDPIPv6Domain #ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN || pdu->tDomain == netsnmp_TCPIPv6Domain #endif ) { if (!netsnmp_udp6_getSecName(pdu->transport_data, pdu->transport_data_length, pdu_community, pdu->community_len, &sn, &contextName)) { /* * There are no com2sec entries. */ sn = NULL; } /* force the community -> context name mapping here */ SNMP_FREE(pdu->contextName); pdu->contextName = strdup(contextName); pdu->contextNameLen = strlen(contextName); #endif #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN } else if (pdu->tDomain == netsnmp_UnixDomain){ if (!netsnmp_unix_getSecName(pdu->transport_data, pdu->transport_data_length, pdu_community, pdu->community_len, &sn, &contextName)) { sn = NULL; } /* force the community -> context name mapping here */ SNMP_FREE(pdu->contextName); pdu->contextName = strdup(contextName); pdu->contextNameLen = strlen(contextName); #endif } else { /* * Map other <community, transport-address> pairs to security names * here. For now just let non-IPv4 transport always succeed. * * WHAAAATTTT. No, we don't let non-IPv4 transports * succeed! You must fix this to make it usable, sorry. * From a security standpoint this is insane. -- Wes */ /** @todo alternate com2sec mappings for non v4 transports. Should be implemented via registration */ sn = NULL; } } else #endif /* support for community based SNMP */ if (find_sec_mod(pdu->securityModel)) { /* * any legal defined v3 security model */ DEBUGMSG(("mibII/vacm_vars", "vacm_in_view: ver=%ld, model=%d, secName=%s\n", pdu->version, pdu->securityModel, pdu->securityName)); sn = pdu->securityName; contextName = pdu->contextName; } else { sn = NULL; } if (sn == NULL) { #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) snmp_increment_statistic(STAT_SNMPINBADCOMMUNITYNAMES); #endif DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: No security name found\n")); return VACM_NOSECNAME; } if (pdu->contextNameLen > CONTEXTNAMEINDEXLEN) { DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: bad ctxt length %d\n", (int)pdu->contextNameLen)); return VACM_NOSUCHCONTEXT; } /* * NULL termination of the pdu field is ugly here. Do in PDU parsing? */ if (pdu->contextName) memcpy(contextNameIndex, pdu->contextName, pdu->contextNameLen); else contextNameIndex[0] = '\0'; contextNameIndex[pdu->contextNameLen] = '\0'; if (!(flags & VACM_CHECK_VIEW_CONTENTS_DNE_CONTEXT_OK) && !netsnmp_subtree_find_first(contextNameIndex)) { /* * rfc 3415 section 3.2, step 1 * no such context here; return no such context error */ DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: no such ctxt \"%s\"\n", contextNameIndex)); return VACM_NOSUCHCONTEXT; } DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: sn=%s", sn)); gp = vacm_getGroupEntry(pdu->securityModel, sn); if (gp == NULL) { DEBUGMSG(("mibII/vacm_vars", "\n")); return VACM_NOGROUP; } DEBUGMSG(("mibII/vacm_vars", ", gn=%s", gp->groupName)); ap = vacm_getAccessEntry(gp->groupName, contextNameIndex, pdu->securityModel, pdu->securityLevel); if (ap == NULL) { DEBUGMSG(("mibII/vacm_vars", "\n")); return VACM_NOACCESS; } if (name == NULL) { /* only check the setup of the vacm for the request */ DEBUGMSG(("mibII/vacm_vars", ", Done checking setup\n")); return VACM_SUCCESS; } if (viewtype < 0 || viewtype >= VACM_MAX_VIEWS) { DEBUGMSG(("mibII/vacm_vars", " illegal view type\n")); return VACM_NOACCESS; } vn = ap->views[viewtype]; DEBUGMSG(("mibII/vacm_vars", ", vn=%s", vn)); if (check_subtree) { DEBUGMSG(("mibII/vacm_vars", "\n")); return vacm_checkSubtree(vn, name, namelen); } vp = vacm_getViewEntry(vn, name, namelen, VACM_MODE_FIND); if (vp == NULL) { DEBUGMSG(("mibII/vacm_vars", "\n")); return VACM_NOVIEW; } DEBUGMSG(("mibII/vacm_vars", ", vt=%d\n", vp->viewType)); if (vp->viewType == SNMP_VIEW_EXCLUDED) { #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) #if defined(NETSNMP_DISABLE_SNMPV1) if (pdu->version == SNMP_VERSION_2c) #else #if defined(NETSNMP_DISABLE_SNMPV2C) if (pdu->version == SNMP_VERSION_1) #else if (pdu->version == SNMP_VERSION_1 || pdu->version == SNMP_VERSION_2c) #endif #endif { snmp_increment_statistic(STAT_SNMPINBADCOMMUNITYUSES); } #endif return VACM_NOTINVIEW; } return VACM_SUCCESS; } /* end vacm_in_view() */