From: kostas <> Date: Wed, 25 Feb 1998 18:16:37 +0000 (+0000) Subject: snmp per-community access controls (snmp_acl in squid.conf) X-Git-Tag: SQUID_3_0_PRE1~3995 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bdf185240e682239ba3770f729371752a818296e;p=thirdparty%2Fsquid.git snmp per-community access controls (snmp_acl in squid.conf) --- diff --git a/snmplib/snmp_api.c b/snmplib/snmp_api.c index fd63e44499..27936999da 100644 --- a/snmplib/snmp_api.c +++ b/snmplib/snmp_api.c @@ -398,8 +398,8 @@ snmp_build(session, pdu, packet, out_length) session->community, session->community_len, session->Version, pdu); - snmplib_debug(8,"LIBSNMP: snmp_build(): Packet len difference %d, returning %d (requid %d)\n", - (bufp - packet), *out_length, pdu->reqid); + snmplib_debug(8,"LIBSNMP: snmp_build(): Packet len %d (requid %d)\n", + *out_length, pdu->reqid); if (bufp == NULL) return(-1); diff --git a/snmplib/snmp_msg.c b/snmplib/snmp_msg.c index 3e29005f02..d43eef3d18 100644 --- a/snmplib/snmp_msg.c +++ b/snmplib/snmp_msg.c @@ -136,6 +136,7 @@ u_char *snmp_msg_Encode(u_char *Buffer, int *BufLenP, u_char *MsgPtr; int FakeArg = 1024; + snmplib_debug(4, "Buffer=%x BufLenP=%x, buflen=%d\n",*BufLenP); /* Header for the entire thing, with a false, large length */ bufp = asn_build_header(Buffer, BufLenP, (u_char)(ASN_SEQUENCE | diff --git a/src/acl.cc b/src/acl.cc index 4b299eeb9c..0bef317b2c 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -1,6 +1,6 @@ /* - * $Id: acl.cc,v 1.140 1998/02/19 19:27:40 wessels Exp $ + * $Id: acl.cc,v 1.141 1998/02/25 11:16:38 kostas Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -897,6 +897,7 @@ aclParseAccessLine(acl_access ** head) return; } A = xcalloc(1, sizeof(acl_access)); + if (!strcmp(t, "allow")) A->allow = 1; else if (!strcmp(t, "deny")) diff --git a/src/cache_cf.cc b/src/cache_cf.cc index bd8f8820d2..a9427d49b5 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.cc,v 1.250 1998/02/21 00:18:10 wessels Exp $ + * $Id: cache_cf.cc,v 1.251 1998/02/25 11:16:39 kostas Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -436,6 +436,28 @@ free_acl(acl ** acl) aclDestroyAcls(acl); } +static void +dump_snmp_access(StoreEntry * entry, const char *name, communityEntry * Head) +{ + acl_list *l; + communityEntry *cp; + acl_access *head; + + for (cp = Head; cp; cp = cp->next) { + head=cp->acls; + while (head != NULL) { + for (l = head->acl_list; l != NULL; l = l->next) { + storeAppendPrintf(entry, "%s %s %s %s%s\n", + name, cp->name, + head->allow ? "Allow" : "Deny", + l->op ? "" : "!", + l->acl->name); + } + head = head->next; + } + } +} + static void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head) { @@ -452,6 +474,30 @@ dump_acl_access(StoreEntry * entry, const char *name, acl_access * head) } } +static void +parse_snmp_access(communityEntry **head) +{ + char *t; + communityEntry *cp; + + t=strtok(NULL, w_space); + for (cp = *head; cp; cp = cp->next) + if (!strcmp(t, cp->name)) { + aclParseAccessLine(&cp->acls); + return; + } + debug(15,0)("parse_snmp_access: You need to define community %s first!\n",t); +} + +static void +free_snmp_access(communityEntry ** Head) +{ + communityEntry *cp; + + for (cp = *Head; cp; cp = cp->next) + aclDestroyAccessList(&cp->acls); +} + static void parse_acl_access(acl_access ** head) { diff --git a/src/cf.data.pre b/src/cf.data.pre index 415229fd26..128bc5c382 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -2085,6 +2085,20 @@ DOC_START snmp_agent_conf community readwrite all all DOC_END +NAME: snmp_acl +TYPE: snmp_access +LOC: Config.Snmp.communities +DEFAULT: none +IFDEF: SQUID_SNMP +DOC_START + Define access controls per community: + snmp_access communityname allow|deny [!]aclname ... + Example: + snmp_acl public allow adminsubnet + snmp_acl public deny all +DOC_END + + NAME: as_whois_server TYPE: string LOC: Config.as_whois_server diff --git a/src/snmp_agent.cc b/src/snmp_agent.cc index 92a5466cc1..32f7301d61 100644 --- a/src/snmp_agent.cc +++ b/src/snmp_agent.cc @@ -15,66 +15,123 @@ enum { HTTP_SVC, ICP_SVC, DNS_SVC }; +void snmpAclCheckDone(int answer, void *); static struct snmp_pdu *snmp_agent_response(struct snmp_pdu *PDU); static int community_check(char *b, oid *name, int namelen); struct snmp_session *Session; -extern StatCounters *CountHist; extern int get_median_svc(int, int); +extern void snmp_agent_parse_done(int, snmp_request_t *); +void snmpAclCheckStart(snmp_request_t *rq); + /* returns: * 2: no such object in this mib * 1: ok * 0: failed */ -int -snmp_agent_parse(u_char * buf, int len, u_char * outbuf, int *outlen, - u_long from_addr, long *this_reqid) +void +snmp_agent_parse(snmp_request_t *rq) { - struct snmp_pdu *PDU, *RespPDU; + long this_reqid; + u_char *buf=rq->buf; + int len=rq->len; + + struct snmp_pdu *PDU; u_char *Community; - variable_list *VarPtr; - variable_list **VarPtrP; - int ret; + /* Now that we have the data, turn it into a PDU */ PDU = snmp_pdu_create(0); Community = snmp_parse(Session, PDU, buf, len); + rq->community=Community; + rq->PDU=PDU; + this_reqid=PDU->reqid; + debug(49, 5) ("snmp_agent_parse: reqid=%d\n", PDU->reqid); + if (Community == NULL) { debug(49, 8) ("snmp_agent_parse: Community == NULL\n"); snmp_free_pdu(PDU); - return 0; + snmp_agent_parse_done(0, rq); } + snmpAclCheckStart(rq); +} + +void +snmpAclCheckStart(snmp_request_t *rq) +{ + communityEntry *cp; + cbdataAdd(rq,MEM_NONE); + for (cp=Config.Snmp.communities;cp!=NULL;cp=cp->next) + if (!strcmp(rq->community, cp->name) && cp->acls) { + rq->acl_checklist= aclChecklistCreate(cp->acls, + NULL,rq->from.sin_addr, NULL, NULL); + aclNBCheck(rq->acl_checklist,snmpAclCheckDone, rq); + return; + } + snmpAclCheckDone(ACCESS_ALLOWED, rq); +} + +void +snmpAclCheckDone(int answer, void *data) +{ + snmp_request_t *rq=data; + u_char *outbuf=rq->outbuf; + + struct snmp_pdu *PDU, *RespPDU; + u_char *Community; + variable_list *VarPtr; + variable_list **VarPtrP; + int ret; + + debug(49,5)("snmpAclCheckDone: called with answer=%d.\n",answer); + rq->acl_checklist = NULL; + cbdataFree(rq); + PDU=rq->PDU; + Community=rq->community; + if (answer==ACCESS_DENIED) { + xfree(Community); + debug(49,5)("snmpAclCheckDone: failed on acl.\n"); + snmp_agent_parse_done(0, rq); + return; + } + for (VarPtrP = &(PDU->variables); *VarPtrP; VarPtrP = &((*VarPtrP)->next_variable)) { VarPtr = *VarPtrP; + debug(49,5)("snmpAclCheckDone: checking."); + /* access check for each variable */ + if (!community_check(Community, VarPtr->name, VarPtr->name_length)) { xfree(Community); - /* Wrong community! XXXXX */ - return 0; + debug(49,5)("snmpAclCheckDone: failed on community_check.\n"); + snmp_agent_parse_done(0, rq); + return; } } - xfree(Community); - debug(49, 5) ("snmp_agent_parse: reqid=%d\n", PDU->reqid); + xfree(Session->community); + Session->community=xstrdup(Community); + Session->community_len=strlen(Community); RespPDU = snmp_agent_response(PDU); snmp_free_pdu(PDU); if (RespPDU == NULL) { - debug(49, 8) ("snmp_agent_parse: RespPDU == NULL\n"); - return 2; + debug(49, 8) ("snmpAclCheckDone: RespPDU == NULL. Returning code 2.\n"); + xfree(Community); + debug(49,5)("snmpAclCheckDone: failed on RespPDU==NULL.\n"); + snmp_agent_parse_done(2, rq); + return; } - debug(49, 8) ("snmp_agent_parse: Response pdu (%x) errstat=%d reqid=%d.\n", + debug(49, 8) ("snmpAclCheckDone: Response pdu (%x) errstat=%d reqid=%d.\n", RespPDU, RespPDU->errstat, RespPDU->reqid); -#if 0 - if (RespPDU->variables) { - debug(49, 8) ("snmp_agent_parse: len=%d\n", RespPDU->variables->val_len); - } -#endif + /* Encode it */ - ret = snmp_build(Session, RespPDU, outbuf, outlen); + ret = snmp_build(Session, RespPDU, outbuf, &rq->outlen); /* XXXXX Handle failure */ snmp_free_pdu(RespPDU); - return 1; + xfree(Community); + debug(49,5)("snmpAclCheckDone: ok!\n"); + snmp_agent_parse_done(1, rq); } @@ -223,10 +280,6 @@ int init_agent_auth() { Session = (struct snmp_session *) xmalloc(sizeof(struct snmp_session)); - if (Session == NULL) { - perror("malloc"); - return 3; - } Session->Version = SNMP_VERSION_1; Session->authenticator = NULL; Session->community = (u_char *) xstrdup("public"); diff --git a/src/structs.h b/src/structs.h index 8df9bcd061..a4333c13c6 100644 --- a/src/structs.h +++ b/src/structs.h @@ -53,6 +53,19 @@ struct _snmpconf { snmpconf *next; }; +struct _snmp_request_t { + char *buf; + char *outbuf; + int len; + int sock; + long reqid; + int outlen; + struct sockaddr_in from; + struct snmp_pdu *PDU; + aclCheck_t *acl_checklist; + char *community; +}; + typedef struct _viewEntry { char viewName[32]; int viewIndex; @@ -66,6 +79,7 @@ typedef struct _communityEntry { char name[64]; int readView; int writeView; + struct _acl_access *acls; struct _communityEntry *next; } communityEntry; @@ -105,6 +119,7 @@ struct _acl_access { struct _acl_access *next; }; + struct _aclCheck_t { const struct _acl_access *access_list; struct in_addr src_addr; diff --git a/src/typedefs.h b/src/typedefs.h index c7c8214698..262d3b66e6 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -21,6 +21,7 @@ typedef struct _acl_deny_info_list acl_deny_info_list; typedef struct _acl_proxy_auth acl_proxy_auth; typedef struct _acl acl; typedef struct _snmpconf snmpconf; +typedef struct _snmp_request_t snmp_request_t; typedef struct _acl_list acl_list; typedef struct _acl_access acl_access; typedef struct _aclCheck_t aclCheck_t;