int vacm_in_view (struct packet_info *pi, oid *name, int namelen) { struct vacm_securityEntry *sp = securityFirst; struct vacm_accessEntry *ap; struct vacm_groupEntry *gp; struct vacm_viewEntry *vp; char *vn; char *sn; if (pi->sec_model == SNMP_SEC_MODEL_SNMPv1 || pi->sec_model == SNMP_SEC_MODEL_SNMPv2c) { DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: ver=%d, source=%.8x, community=%s\n", pi->version, pi->source.sin_addr.s_addr, pi->community)); /* allow running without snmpd.conf */ if (sp == NULL) { DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: accepted with no com2sec entries\n")); switch (pi->pdutype) { case SNMP_MSG_GET: case SNMP_MSG_GETNEXT: case SNMP_MSG_GETBULK: return 1; default: return 0; } } while (sp) { if ((pi->source.sin_addr.s_addr & sp->sourceMask.sin_addr.s_addr) == sp->sourceIp.sin_addr.s_addr && strcmp(sp->community, (char *)pi->community) == 0) break; sp = sp->next; } if (sp == NULL) return 0; sn = sp->securityName; } else { sn = NULL; } if (sn == NULL) return 0; DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: securityName == %s\n", sn)); gp = vacm_getGroupEntry(pi->sec_model, sn); if (gp == NULL) return 0; DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: groupName == %s\n", gp->groupName)); ap = vacm_getAccessEntry(gp->groupName, "", pi->sec_model, pi->sec_level); if (ap == NULL) return 0; switch (pi->pdutype) { case SNMP_MSG_GET: case SNMP_MSG_GETNEXT: case SNMP_MSG_GETBULK: vn = ap->readView; break; case SNMP_MSG_SET: vn = ap->writeView; break; case SNMP_MSG_TRAP: case SNMP_MSG_TRAP2: case SNMP_MSG_INFORM: vn = ap->notifyView; break; default: fprintf(stderr,"bad msg type in vacm_in_view: %d\n", pi->pdutype); vn = ap->readView; } DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: viewName == %s\n", vn)); vp = vacm_getViewEntry (vn, name, namelen); if (vp == NULL) return 0; DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: viewType == %d\n", vp->viewType)); if (vp->viewType == SNMP_VIEW_EXCLUDED) return 0; return 1; }
u_char *var_vacm_sec2group(struct variable *vp, oid *name, int *length, int exact, int *var_len, WriteMethod **write_method) { struct vacm_groupEntry *gp; oid *groupSubtree; int groupSubtreeLen; int secmodel; char secname[32], *cp; write_method = NULL; 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; cp = secname; while (groupSubtreeLen-- > 0) { *cp++ = *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) { *cp++ = *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) 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; } return NULL; }
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() */