1135f7de5SShteryana Shopova /*-
28e9b3e70SHartmut Brandt * Copyright (c) 2010,2018 The FreeBSD Foundation
3135f7de5SShteryana Shopova *
4135f7de5SShteryana Shopova * This software was developed by Shteryana Sotirova Shopova under
5135f7de5SShteryana Shopova * sponsorship from the FreeBSD Foundation.
6135f7de5SShteryana Shopova *
7135f7de5SShteryana Shopova * Redistribution and use in source and binary forms, with or without
8135f7de5SShteryana Shopova * modification, are permitted provided that the following conditions
9135f7de5SShteryana Shopova * are met:
10135f7de5SShteryana Shopova * 1. Redistributions of source code must retain the above copyright
11135f7de5SShteryana Shopova * notice, this list of conditions and the following disclaimer.
12135f7de5SShteryana Shopova * 2. Redistributions in binary form must reproduce the above copyright
13135f7de5SShteryana Shopova * notice, this list of conditions and the following disclaimer in the
14135f7de5SShteryana Shopova * documentation and/or other materials provided with the distribution.
15135f7de5SShteryana Shopova *
16135f7de5SShteryana Shopova * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17135f7de5SShteryana Shopova * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18135f7de5SShteryana Shopova * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19135f7de5SShteryana Shopova * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20135f7de5SShteryana Shopova * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21135f7de5SShteryana Shopova * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22135f7de5SShteryana Shopova * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23135f7de5SShteryana Shopova * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24135f7de5SShteryana Shopova * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25135f7de5SShteryana Shopova * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26135f7de5SShteryana Shopova * SUCH DAMAGE.
27135f7de5SShteryana Shopova *
28135f7de5SShteryana Shopova * $FreeBSD$
29135f7de5SShteryana Shopova */
30135f7de5SShteryana Shopova #include <sys/queue.h>
31135f7de5SShteryana Shopova #include <sys/types.h>
32135f7de5SShteryana Shopova
33135f7de5SShteryana Shopova #include <errno.h>
34135f7de5SShteryana Shopova #include <stdarg.h>
35135f7de5SShteryana Shopova #include <stdlib.h>
36135f7de5SShteryana Shopova #include <stdio.h>
37135f7de5SShteryana Shopova #include <stdint.h>
38135f7de5SShteryana Shopova #include <string.h>
39135f7de5SShteryana Shopova #include <syslog.h>
40135f7de5SShteryana Shopova
41135f7de5SShteryana Shopova #include "asn1.h"
42135f7de5SShteryana Shopova #include "snmp.h"
43135f7de5SShteryana Shopova #include "snmpmod.h"
44135f7de5SShteryana Shopova
458e9b3e70SHartmut Brandt #define SNMPTREE_TYPES
46135f7de5SShteryana Shopova #include "vacm_tree.h"
47135f7de5SShteryana Shopova #include "vacm_oid.h"
48135f7de5SShteryana Shopova
49135f7de5SShteryana Shopova static struct lmodule *vacm_module;
50135f7de5SShteryana Shopova /* For the registration. */
51135f7de5SShteryana Shopova static const struct asn_oid oid_vacm = OIDX_snmpVacmMIB;
52135f7de5SShteryana Shopova
53135f7de5SShteryana Shopova static uint reg_vacm;
54135f7de5SShteryana Shopova
55135f7de5SShteryana Shopova static int32_t vacm_lock;
56135f7de5SShteryana Shopova
57135f7de5SShteryana Shopova /*
58135f7de5SShteryana Shopova * Internal datastructures and forward declarations.
59135f7de5SShteryana Shopova */
60135f7de5SShteryana Shopova static void vacm_append_userindex(struct asn_oid *,
61135f7de5SShteryana Shopova uint, const struct vacm_user *);
62135f7de5SShteryana Shopova static int vacm_user_index_decode(const struct asn_oid *,
63135f7de5SShteryana Shopova uint, int32_t *, char *);
64135f7de5SShteryana Shopova static struct vacm_user *vacm_get_user(const struct asn_oid *,
65135f7de5SShteryana Shopova uint);
66135f7de5SShteryana Shopova static struct vacm_user *vacm_get_next_user(const struct asn_oid *,
67135f7de5SShteryana Shopova uint);
68135f7de5SShteryana Shopova static void vacm_append_access_rule_index(struct asn_oid *,
69135f7de5SShteryana Shopova uint, const struct vacm_access *);
70135f7de5SShteryana Shopova static int vacm_access_rule_index_decode(const struct asn_oid *,
71135f7de5SShteryana Shopova uint, char *, char *, int32_t *, int32_t *);
72135f7de5SShteryana Shopova static struct vacm_access * vacm_get_access_rule(const struct asn_oid *,
73135f7de5SShteryana Shopova uint);
74135f7de5SShteryana Shopova static struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *,
75135f7de5SShteryana Shopova uint);
76135f7de5SShteryana Shopova static int vacm_view_index_decode(const struct asn_oid *, uint,
77135f7de5SShteryana Shopova char *, struct asn_oid *);
78135f7de5SShteryana Shopova static void vacm_append_viewindex(struct asn_oid *, uint,
79135f7de5SShteryana Shopova const struct vacm_view *);
80135f7de5SShteryana Shopova static struct vacm_view *vacm_get_view(const struct asn_oid *, uint);
81135f7de5SShteryana Shopova static struct vacm_view *vacm_get_next_view(const struct asn_oid *, uint);
82135f7de5SShteryana Shopova static struct vacm_view *vacm_get_view_by_name(u_char *, u_int);
83135f7de5SShteryana Shopova static struct vacm_context *vacm_get_context(const struct asn_oid *, uint);
84135f7de5SShteryana Shopova static struct vacm_context *vacm_get_next_context(const struct asn_oid *,
85135f7de5SShteryana Shopova uint);
86135f7de5SShteryana Shopova static void vacm_append_ctxindex(struct asn_oid *, uint,
87135f7de5SShteryana Shopova const struct vacm_context *);
88135f7de5SShteryana Shopova
89135f7de5SShteryana Shopova int
op_vacm_context(struct snmp_context * ctx __unused,struct snmp_value * val,uint32_t sub,uint32_t iidx __unused,enum snmp_op op)90135f7de5SShteryana Shopova op_vacm_context(struct snmp_context *ctx __unused, struct snmp_value *val,
91135f7de5SShteryana Shopova uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
92135f7de5SShteryana Shopova {
93135f7de5SShteryana Shopova char cname[SNMP_ADM_STR32_SIZ];
94135f7de5SShteryana Shopova size_t cnamelen;
95135f7de5SShteryana Shopova struct vacm_context *vacm_ctx;
96135f7de5SShteryana Shopova
97135f7de5SShteryana Shopova if (val->var.subs[sub - 1] != LEAF_vacmContextName)
98135f7de5SShteryana Shopova abort();
99135f7de5SShteryana Shopova
100135f7de5SShteryana Shopova switch (op) {
101135f7de5SShteryana Shopova case SNMP_OP_GET:
102135f7de5SShteryana Shopova if ((vacm_ctx = vacm_get_context(&val->var, sub)) == NULL)
103135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
104135f7de5SShteryana Shopova break;
105135f7de5SShteryana Shopova
106135f7de5SShteryana Shopova case SNMP_OP_GETNEXT:
107135f7de5SShteryana Shopova if ((vacm_ctx = vacm_get_next_context(&val->var, sub)) == NULL)
108135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
109135f7de5SShteryana Shopova vacm_append_ctxindex(&val->var, sub, vacm_ctx);
110135f7de5SShteryana Shopova break;
111135f7de5SShteryana Shopova
112135f7de5SShteryana Shopova case SNMP_OP_SET:
113135f7de5SShteryana Shopova if ((vacm_ctx = vacm_get_context(&val->var, sub)) != NULL)
114135f7de5SShteryana Shopova return (SNMP_ERR_WRONG_VALUE);
115135f7de5SShteryana Shopova if (community != COMM_INITIALIZE)
116135f7de5SShteryana Shopova return (SNMP_ERR_NOT_WRITEABLE);
117135f7de5SShteryana Shopova if (val->var.subs[sub] >= SNMP_ADM_STR32_SIZ)
118135f7de5SShteryana Shopova return (SNMP_ERR_WRONG_VALUE);
119135f7de5SShteryana Shopova if (index_decode(&val->var, sub, iidx, &cname, &cnamelen))
120135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
121135f7de5SShteryana Shopova cname[cnamelen] = '\0';
122135f7de5SShteryana Shopova if ((vacm_ctx = vacm_add_context(cname, reg_vacm)) == NULL)
123135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
124135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
125135f7de5SShteryana Shopova
126135f7de5SShteryana Shopova case SNMP_OP_COMMIT:
127135f7de5SShteryana Shopova /* FALLTHROUGH*/
128135f7de5SShteryana Shopova case SNMP_OP_ROLLBACK:
129135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
130135f7de5SShteryana Shopova default:
131135f7de5SShteryana Shopova abort();
132135f7de5SShteryana Shopova }
133135f7de5SShteryana Shopova
134135f7de5SShteryana Shopova return (string_get(val, vacm_ctx->ctxname, -1));
135135f7de5SShteryana Shopova }
136135f7de5SShteryana Shopova
137135f7de5SShteryana Shopova int
op_vacm_security_to_group(struct snmp_context * ctx,struct snmp_value * val,uint32_t sub,uint32_t iidx __unused,enum snmp_op op)138135f7de5SShteryana Shopova op_vacm_security_to_group(struct snmp_context *ctx, struct snmp_value *val,
139135f7de5SShteryana Shopova uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
140135f7de5SShteryana Shopova {
141135f7de5SShteryana Shopova int32_t smodel;
142135f7de5SShteryana Shopova char uname[SNMP_ADM_STR32_SIZ];
143135f7de5SShteryana Shopova struct vacm_user *user;
144135f7de5SShteryana Shopova
145135f7de5SShteryana Shopova switch (op) {
146135f7de5SShteryana Shopova case SNMP_OP_GET:
147135f7de5SShteryana Shopova if ((user = vacm_get_user(&val->var, sub)) == NULL)
148135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
149135f7de5SShteryana Shopova break;
150135f7de5SShteryana Shopova
151135f7de5SShteryana Shopova case SNMP_OP_GETNEXT:
152135f7de5SShteryana Shopova if ((user = vacm_get_next_user(&val->var, sub)) == NULL)
153135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
154135f7de5SShteryana Shopova vacm_append_userindex(&val->var, sub, user);
155135f7de5SShteryana Shopova break;
156135f7de5SShteryana Shopova
157135f7de5SShteryana Shopova case SNMP_OP_SET:
158135f7de5SShteryana Shopova if ((user = vacm_get_user(&val->var, sub)) == NULL &&
159135f7de5SShteryana Shopova val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
160135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
161135f7de5SShteryana Shopova
162135f7de5SShteryana Shopova if (user != NULL) {
163135f7de5SShteryana Shopova if (community != COMM_INITIALIZE &&
164135f7de5SShteryana Shopova user->type == StorageType_readOnly)
165135f7de5SShteryana Shopova return (SNMP_ERR_NOT_WRITEABLE);
166135f7de5SShteryana Shopova if (user->status == RowStatus_active &&
167135f7de5SShteryana Shopova val->v.integer != RowStatus_destroy)
168135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
169135f7de5SShteryana Shopova }
170135f7de5SShteryana Shopova
171135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
172135f7de5SShteryana Shopova case LEAF_vacmGroupName:
173135f7de5SShteryana Shopova ctx->scratch->ptr1 = user->group->groupname;
174135f7de5SShteryana Shopova ctx->scratch->int1 = strlen(user->group->groupname);
175135f7de5SShteryana Shopova return (vacm_user_set_group(user,
176135f7de5SShteryana Shopova val->v.octetstring.octets,val->v.octetstring.len));
177135f7de5SShteryana Shopova
178135f7de5SShteryana Shopova case LEAF_vacmSecurityToGroupStorageType:
179135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
180135f7de5SShteryana Shopova
181135f7de5SShteryana Shopova case LEAF_vacmSecurityToGroupStatus:
182135f7de5SShteryana Shopova if (user == NULL) {
183135f7de5SShteryana Shopova if (val->v.integer != RowStatus_createAndGo ||
184135f7de5SShteryana Shopova vacm_user_index_decode(&val->var, sub,
185135f7de5SShteryana Shopova &smodel, uname) < 0)
186135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
187135f7de5SShteryana Shopova user = vacm_new_user(smodel, uname);
188135f7de5SShteryana Shopova if (user == NULL)
189135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
190135f7de5SShteryana Shopova user->status = RowStatus_destroy;
191135f7de5SShteryana Shopova if (community != COMM_INITIALIZE)
192135f7de5SShteryana Shopova user->type = StorageType_volatile;
193135f7de5SShteryana Shopova else
194135f7de5SShteryana Shopova user->type = StorageType_readOnly;
195135f7de5SShteryana Shopova } else if (val->v.integer != RowStatus_active &&
196135f7de5SShteryana Shopova val->v.integer != RowStatus_destroy)
197135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
198135f7de5SShteryana Shopova ctx->scratch->int1 = user->status;
199135f7de5SShteryana Shopova user->status = val->v.integer;
200135f7de5SShteryana Shopova break;
201135f7de5SShteryana Shopova }
202135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
203135f7de5SShteryana Shopova
204135f7de5SShteryana Shopova case SNMP_OP_COMMIT:
205135f7de5SShteryana Shopova if (val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
206135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
207135f7de5SShteryana Shopova if ((user = vacm_get_user(&val->var, sub)) == NULL)
208135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
209135f7de5SShteryana Shopova switch (val->v.integer) {
210135f7de5SShteryana Shopova case RowStatus_destroy:
211135f7de5SShteryana Shopova return (vacm_delete_user(user));
212135f7de5SShteryana Shopova
213135f7de5SShteryana Shopova case RowStatus_createAndGo:
214135f7de5SShteryana Shopova user->status = RowStatus_active;
215135f7de5SShteryana Shopova break;
216135f7de5SShteryana Shopova
217135f7de5SShteryana Shopova default:
218135f7de5SShteryana Shopova break;
219135f7de5SShteryana Shopova }
220135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
221135f7de5SShteryana Shopova
222135f7de5SShteryana Shopova case SNMP_OP_ROLLBACK:
223135f7de5SShteryana Shopova if ((user = vacm_get_user(&val->var, sub)) == NULL)
224135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
225135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
226135f7de5SShteryana Shopova case LEAF_vacmGroupName:
227135f7de5SShteryana Shopova return (vacm_user_set_group(user, ctx->scratch->ptr1,
228135f7de5SShteryana Shopova ctx->scratch->int1));
229135f7de5SShteryana Shopova
230135f7de5SShteryana Shopova case LEAF_vacmSecurityToGroupStatus:
231135f7de5SShteryana Shopova if (ctx->scratch->int1 == RowStatus_destroy)
232135f7de5SShteryana Shopova return (vacm_delete_user(user));
233135f7de5SShteryana Shopova user->status = ctx->scratch->int1;
234135f7de5SShteryana Shopova break;
235135f7de5SShteryana Shopova
236135f7de5SShteryana Shopova default:
237135f7de5SShteryana Shopova break;
238135f7de5SShteryana Shopova }
239135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
240135f7de5SShteryana Shopova
241135f7de5SShteryana Shopova default:
242135f7de5SShteryana Shopova abort();
243135f7de5SShteryana Shopova }
244135f7de5SShteryana Shopova
245135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
246135f7de5SShteryana Shopova case LEAF_vacmGroupName:
247135f7de5SShteryana Shopova return (string_get(val, user->group->groupname, -1));
248135f7de5SShteryana Shopova case LEAF_vacmSecurityToGroupStorageType:
249135f7de5SShteryana Shopova val->v.integer = user->type;
250135f7de5SShteryana Shopova break;
251135f7de5SShteryana Shopova case LEAF_vacmSecurityToGroupStatus:
252135f7de5SShteryana Shopova val->v.integer = user->status;
253135f7de5SShteryana Shopova break;
254135f7de5SShteryana Shopova default:
255135f7de5SShteryana Shopova abort();
256135f7de5SShteryana Shopova }
257135f7de5SShteryana Shopova
258135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
259135f7de5SShteryana Shopova }
260135f7de5SShteryana Shopova
261135f7de5SShteryana Shopova int
op_vacm_access(struct snmp_context * ctx,struct snmp_value * val,uint32_t sub,uint32_t iidx __unused,enum snmp_op op)262135f7de5SShteryana Shopova op_vacm_access(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
263135f7de5SShteryana Shopova uint32_t iidx __unused, enum snmp_op op)
264135f7de5SShteryana Shopova {
265135f7de5SShteryana Shopova int32_t smodel, slevel;
266135f7de5SShteryana Shopova char gname[SNMP_ADM_STR32_SIZ], cprefix[SNMP_ADM_STR32_SIZ];
267135f7de5SShteryana Shopova struct vacm_access *acl;
268135f7de5SShteryana Shopova
269135f7de5SShteryana Shopova switch (op) {
270135f7de5SShteryana Shopova case SNMP_OP_GET:
271135f7de5SShteryana Shopova if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
272135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
273135f7de5SShteryana Shopova break;
274135f7de5SShteryana Shopova
275135f7de5SShteryana Shopova case SNMP_OP_GETNEXT:
276135f7de5SShteryana Shopova if ((acl = vacm_get_next_access_rule(&val->var, sub)) == NULL)
277135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
278135f7de5SShteryana Shopova vacm_append_access_rule_index(&val->var, sub, acl);
279135f7de5SShteryana Shopova break;
280135f7de5SShteryana Shopova
281135f7de5SShteryana Shopova case SNMP_OP_SET:
282135f7de5SShteryana Shopova if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL &&
283135f7de5SShteryana Shopova val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
284135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
285135f7de5SShteryana Shopova if (acl != NULL && community != COMM_INITIALIZE &&
286135f7de5SShteryana Shopova acl->type == StorageType_readOnly)
287135f7de5SShteryana Shopova return (SNMP_ERR_NOT_WRITEABLE);
288135f7de5SShteryana Shopova
289135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
290135f7de5SShteryana Shopova case LEAF_vacmAccessContextMatch:
291135f7de5SShteryana Shopova ctx->scratch->int1 = acl->ctx_match;
292135f7de5SShteryana Shopova if (val->v.integer == vacmAccessContextMatch_exact)
293135f7de5SShteryana Shopova acl->ctx_match = 1;
294135f7de5SShteryana Shopova else if (val->v.integer == vacmAccessContextMatch_prefix)
295135f7de5SShteryana Shopova acl->ctx_match = 0;
296135f7de5SShteryana Shopova else
297135f7de5SShteryana Shopova return (SNMP_ERR_WRONG_VALUE);
298135f7de5SShteryana Shopova break;
299135f7de5SShteryana Shopova
300135f7de5SShteryana Shopova case LEAF_vacmAccessReadViewName:
301135f7de5SShteryana Shopova ctx->scratch->ptr1 = acl->read_view;
302135f7de5SShteryana Shopova acl->read_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len);
303135f7de5SShteryana Shopova if (acl->read_view == NULL) {
304135f7de5SShteryana Shopova acl->read_view = ctx->scratch->ptr1;
305135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
306135f7de5SShteryana Shopova }
307135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
308135f7de5SShteryana Shopova
309135f7de5SShteryana Shopova case LEAF_vacmAccessWriteViewName:
310135f7de5SShteryana Shopova ctx->scratch->ptr1 = acl->write_view;
311135f7de5SShteryana Shopova if ((acl->write_view =
312135f7de5SShteryana Shopova vacm_get_view_by_name(val->v.octetstring.octets,
313135f7de5SShteryana Shopova val->v.octetstring.len)) == NULL) {
314135f7de5SShteryana Shopova acl->write_view = ctx->scratch->ptr1;
315135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
316135f7de5SShteryana Shopova }
317135f7de5SShteryana Shopova break;
318135f7de5SShteryana Shopova
319135f7de5SShteryana Shopova case LEAF_vacmAccessNotifyViewName:
320135f7de5SShteryana Shopova ctx->scratch->ptr1 = acl->notify_view;
321135f7de5SShteryana Shopova if ((acl->notify_view =
322135f7de5SShteryana Shopova vacm_get_view_by_name(val->v.octetstring.octets,
323135f7de5SShteryana Shopova val->v.octetstring.len)) == NULL) {
324135f7de5SShteryana Shopova acl->notify_view = ctx->scratch->ptr1;
325135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
326135f7de5SShteryana Shopova }
327135f7de5SShteryana Shopova break;
328135f7de5SShteryana Shopova
329135f7de5SShteryana Shopova case LEAF_vacmAccessStorageType:
330135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
331135f7de5SShteryana Shopova
332135f7de5SShteryana Shopova case LEAF_vacmAccessStatus:
333135f7de5SShteryana Shopova if (acl == NULL) {
334135f7de5SShteryana Shopova if (val->v.integer != RowStatus_createAndGo ||
335135f7de5SShteryana Shopova vacm_access_rule_index_decode(&val->var,
336135f7de5SShteryana Shopova sub, gname, cprefix, &smodel, &slevel) < 0)
337135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
338135f7de5SShteryana Shopova if ((acl = vacm_new_access_rule(gname, cprefix,
339135f7de5SShteryana Shopova smodel, slevel)) == NULL)
340135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
341135f7de5SShteryana Shopova acl->status = RowStatus_destroy;
342135f7de5SShteryana Shopova if (community != COMM_INITIALIZE)
343135f7de5SShteryana Shopova acl->type = StorageType_volatile;
344135f7de5SShteryana Shopova else
345135f7de5SShteryana Shopova acl->type = StorageType_readOnly;
346135f7de5SShteryana Shopova } else if (val->v.integer != RowStatus_active &&
347135f7de5SShteryana Shopova val->v.integer != RowStatus_destroy)
348135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
349135f7de5SShteryana Shopova ctx->scratch->int1 = acl->status;
350135f7de5SShteryana Shopova acl->status = val->v.integer;
351135f7de5SShteryana Shopova break;
352135f7de5SShteryana Shopova }
353135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
354135f7de5SShteryana Shopova
355135f7de5SShteryana Shopova case SNMP_OP_COMMIT:
356135f7de5SShteryana Shopova if (val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
357135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
358135f7de5SShteryana Shopova if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
359135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
360135f7de5SShteryana Shopova if (val->v.integer == RowStatus_destroy)
361135f7de5SShteryana Shopova return (vacm_delete_access_rule(acl));
362135f7de5SShteryana Shopova else
363135f7de5SShteryana Shopova acl->status = RowStatus_active;
364135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
365135f7de5SShteryana Shopova
366135f7de5SShteryana Shopova case SNMP_OP_ROLLBACK:
367135f7de5SShteryana Shopova if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
368135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
369135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
370135f7de5SShteryana Shopova case LEAF_vacmAccessContextMatch:
371135f7de5SShteryana Shopova acl->ctx_match = ctx->scratch->int1;
372135f7de5SShteryana Shopova break;
373135f7de5SShteryana Shopova case LEAF_vacmAccessReadViewName:
374135f7de5SShteryana Shopova acl->read_view = ctx->scratch->ptr1;
375135f7de5SShteryana Shopova break;
376135f7de5SShteryana Shopova case LEAF_vacmAccessWriteViewName:
377135f7de5SShteryana Shopova acl->write_view = ctx->scratch->ptr1;
378135f7de5SShteryana Shopova break;
379135f7de5SShteryana Shopova case LEAF_vacmAccessNotifyViewName:
380135f7de5SShteryana Shopova acl->notify_view = ctx->scratch->ptr1;
381135f7de5SShteryana Shopova break;
382135f7de5SShteryana Shopova case LEAF_vacmAccessStatus:
383135f7de5SShteryana Shopova if (ctx->scratch->int1 == RowStatus_destroy)
384135f7de5SShteryana Shopova return (vacm_delete_access_rule(acl));
385135f7de5SShteryana Shopova default:
386135f7de5SShteryana Shopova break;
387135f7de5SShteryana Shopova }
388135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
389135f7de5SShteryana Shopova
390135f7de5SShteryana Shopova default:
391135f7de5SShteryana Shopova abort();
392135f7de5SShteryana Shopova }
393135f7de5SShteryana Shopova
394135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
395135f7de5SShteryana Shopova case LEAF_vacmAccessContextMatch:
396135f7de5SShteryana Shopova return (string_get(val, acl->ctx_prefix, -1));
397135f7de5SShteryana Shopova case LEAF_vacmAccessReadViewName:
398135f7de5SShteryana Shopova if (acl->read_view != NULL)
399135f7de5SShteryana Shopova return (string_get(val, acl->read_view->viewname, -1));
400135f7de5SShteryana Shopova else
401135f7de5SShteryana Shopova return (string_get(val, NULL, 0));
402135f7de5SShteryana Shopova case LEAF_vacmAccessWriteViewName:
403135f7de5SShteryana Shopova if (acl->write_view != NULL)
404135f7de5SShteryana Shopova return (string_get(val, acl->write_view->viewname, -1));
405135f7de5SShteryana Shopova else
406135f7de5SShteryana Shopova return (string_get(val, NULL, 0));
407135f7de5SShteryana Shopova case LEAF_vacmAccessNotifyViewName:
408135f7de5SShteryana Shopova if (acl->notify_view != NULL)
409135f7de5SShteryana Shopova return (string_get(val, acl->notify_view->viewname, -1));
410135f7de5SShteryana Shopova else
411135f7de5SShteryana Shopova return (string_get(val, NULL, 0));
412135f7de5SShteryana Shopova case LEAF_vacmAccessStorageType:
413135f7de5SShteryana Shopova val->v.integer = acl->type;
414135f7de5SShteryana Shopova break;
415135f7de5SShteryana Shopova case LEAF_vacmAccessStatus:
416135f7de5SShteryana Shopova val->v.integer = acl->status;
417135f7de5SShteryana Shopova break;
418135f7de5SShteryana Shopova default:
419135f7de5SShteryana Shopova abort();
420135f7de5SShteryana Shopova }
421135f7de5SShteryana Shopova
422135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
423135f7de5SShteryana Shopova }
424135f7de5SShteryana Shopova
425135f7de5SShteryana Shopova int
op_vacm_view_lock(struct snmp_context * ctx __unused,struct snmp_value * val,uint32_t sub,uint32_t iidx __unused,enum snmp_op op)426135f7de5SShteryana Shopova op_vacm_view_lock(struct snmp_context *ctx __unused, struct snmp_value *val,
427135f7de5SShteryana Shopova uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
428135f7de5SShteryana Shopova {
429135f7de5SShteryana Shopova if (val->var.subs[sub - 1] != LEAF_vacmViewSpinLock)
430135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
431135f7de5SShteryana Shopova
432135f7de5SShteryana Shopova switch (op) {
433135f7de5SShteryana Shopova case SNMP_OP_GET:
434135f7de5SShteryana Shopova if (++vacm_lock == INT32_MAX)
435135f7de5SShteryana Shopova vacm_lock = 0;
436135f7de5SShteryana Shopova val->v.integer = vacm_lock;
437135f7de5SShteryana Shopova break;
438135f7de5SShteryana Shopova
439135f7de5SShteryana Shopova case SNMP_OP_GETNEXT:
440135f7de5SShteryana Shopova abort();
441135f7de5SShteryana Shopova
442135f7de5SShteryana Shopova case SNMP_OP_SET:
443135f7de5SShteryana Shopova if (val->v.integer != vacm_lock)
444135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
445135f7de5SShteryana Shopova break;
446135f7de5SShteryana Shopova
447135f7de5SShteryana Shopova case SNMP_OP_ROLLBACK:
448135f7de5SShteryana Shopova /* FALLTHROUGH */
449135f7de5SShteryana Shopova case SNMP_OP_COMMIT:
450135f7de5SShteryana Shopova break;
451135f7de5SShteryana Shopova }
452135f7de5SShteryana Shopova
453135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
454135f7de5SShteryana Shopova }
455135f7de5SShteryana Shopova
456135f7de5SShteryana Shopova int
op_vacm_view(struct snmp_context * ctx,struct snmp_value * val,uint32_t sub,uint32_t iidx __unused,enum snmp_op op)457135f7de5SShteryana Shopova op_vacm_view(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
458135f7de5SShteryana Shopova uint32_t iidx __unused, enum snmp_op op)
459135f7de5SShteryana Shopova {
460135f7de5SShteryana Shopova char vname[SNMP_ADM_STR32_SIZ];
461135f7de5SShteryana Shopova struct asn_oid oid;
462135f7de5SShteryana Shopova struct vacm_view *view;
463135f7de5SShteryana Shopova
464135f7de5SShteryana Shopova switch (op) {
465135f7de5SShteryana Shopova case SNMP_OP_GET:
466135f7de5SShteryana Shopova if ((view = vacm_get_view(&val->var, sub)) == NULL)
467135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
468135f7de5SShteryana Shopova break;
469135f7de5SShteryana Shopova
470135f7de5SShteryana Shopova case SNMP_OP_GETNEXT:
471135f7de5SShteryana Shopova if ((view = vacm_get_next_view(&val->var, sub)) == NULL)
472135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
473135f7de5SShteryana Shopova vacm_append_viewindex(&val->var, sub, view);
474135f7de5SShteryana Shopova break;
475135f7de5SShteryana Shopova
476135f7de5SShteryana Shopova case SNMP_OP_SET:
477135f7de5SShteryana Shopova if ((view = vacm_get_view(&val->var, sub)) == NULL &&
478135f7de5SShteryana Shopova val->var.subs[sub - 1] != LEAF_vacmViewTreeFamilyStatus)
479135f7de5SShteryana Shopova return (SNMP_ERR_NOSUCHNAME);
480135f7de5SShteryana Shopova
481135f7de5SShteryana Shopova if (view != NULL) {
482135f7de5SShteryana Shopova if (community != COMM_INITIALIZE &&
483135f7de5SShteryana Shopova view->type == StorageType_readOnly)
484135f7de5SShteryana Shopova return (SNMP_ERR_NOT_WRITEABLE);
485135f7de5SShteryana Shopova if (view->status == RowStatus_active &&
486135f7de5SShteryana Shopova val->v.integer != RowStatus_destroy)
487135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
488135f7de5SShteryana Shopova }
489135f7de5SShteryana Shopova
490135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
491135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyMask:
492135f7de5SShteryana Shopova if (val->v.octetstring.len > sizeof(view->mask))
493135f7de5SShteryana Shopova ctx->scratch->ptr1 = malloc(sizeof(view->mask));
494135f7de5SShteryana Shopova if (ctx->scratch->ptr1 == NULL)
495135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
496135f7de5SShteryana Shopova memset(ctx->scratch->ptr1, 0, sizeof(view->mask));
497135f7de5SShteryana Shopova memcpy(ctx->scratch->ptr1, view->mask,
498135f7de5SShteryana Shopova sizeof(view->mask));
499135f7de5SShteryana Shopova memset(view->mask, 0, sizeof(view->mask));
500135f7de5SShteryana Shopova memcpy(view->mask, val->v.octetstring.octets,
501135f7de5SShteryana Shopova val->v.octetstring.len);
502135f7de5SShteryana Shopova break;
503135f7de5SShteryana Shopova
504135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyType:
505135f7de5SShteryana Shopova ctx->scratch->int1 = view->exclude;
506135f7de5SShteryana Shopova if (val->v.integer == vacmViewTreeFamilyType_included)
507135f7de5SShteryana Shopova view->exclude = 0;
508135f7de5SShteryana Shopova else if (val->v.integer == vacmViewTreeFamilyType_excluded)
509135f7de5SShteryana Shopova view->exclude = 1;
510135f7de5SShteryana Shopova else
511135f7de5SShteryana Shopova return (SNMP_ERR_WRONG_VALUE);
512135f7de5SShteryana Shopova break;
513135f7de5SShteryana Shopova
514135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyStorageType:
515135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
516135f7de5SShteryana Shopova
517135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyStatus:
518135f7de5SShteryana Shopova if (view == NULL) {
519135f7de5SShteryana Shopova if (val->v.integer != RowStatus_createAndGo ||
520135f7de5SShteryana Shopova vacm_view_index_decode(&val->var, sub, vname,
521135f7de5SShteryana Shopova &oid) < 0)
522135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
523135f7de5SShteryana Shopova if ((view = vacm_new_view(vname, &oid)) == NULL)
524135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
525135f7de5SShteryana Shopova view->status = RowStatus_destroy;
526135f7de5SShteryana Shopova if (community != COMM_INITIALIZE)
527135f7de5SShteryana Shopova view->type = StorageType_volatile;
528135f7de5SShteryana Shopova else
529135f7de5SShteryana Shopova view->type = StorageType_readOnly;
530135f7de5SShteryana Shopova } else if (val->v.integer != RowStatus_active &&
531135f7de5SShteryana Shopova val->v.integer != RowStatus_destroy)
532135f7de5SShteryana Shopova return (SNMP_ERR_INCONS_VALUE);
533135f7de5SShteryana Shopova ctx->scratch->int1 = view->status;
534135f7de5SShteryana Shopova view->status = val->v.integer;
535135f7de5SShteryana Shopova break;
536135f7de5SShteryana Shopova }
537135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
538135f7de5SShteryana Shopova
539135f7de5SShteryana Shopova case SNMP_OP_COMMIT:
540135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
541135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyMask:
542135f7de5SShteryana Shopova free(ctx->scratch->ptr1);
543135f7de5SShteryana Shopova break;
544135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyStatus:
545135f7de5SShteryana Shopova if ((view = vacm_get_view(&val->var, sub)) == NULL)
546135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
547135f7de5SShteryana Shopova switch (val->v.integer) {
548135f7de5SShteryana Shopova case RowStatus_destroy:
549135f7de5SShteryana Shopova return (vacm_delete_view(view));
550135f7de5SShteryana Shopova
551135f7de5SShteryana Shopova case RowStatus_createAndGo:
552135f7de5SShteryana Shopova view->status = RowStatus_active;
553135f7de5SShteryana Shopova break;
554135f7de5SShteryana Shopova
555135f7de5SShteryana Shopova default:
556135f7de5SShteryana Shopova /* NOTREACHED*/
557135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
558135f7de5SShteryana Shopova }
559135f7de5SShteryana Shopova default:
560135f7de5SShteryana Shopova break;
561135f7de5SShteryana Shopova }
562135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
563135f7de5SShteryana Shopova
564135f7de5SShteryana Shopova case SNMP_OP_ROLLBACK:
565135f7de5SShteryana Shopova if ((view = vacm_get_view(&val->var, sub)) == NULL)
566135f7de5SShteryana Shopova return (SNMP_ERR_GENERR);
567135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
568135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyMask:
569135f7de5SShteryana Shopova memcpy(view->mask, ctx->scratch->ptr1,
570135f7de5SShteryana Shopova sizeof(view->mask));
571135f7de5SShteryana Shopova free(ctx->scratch->ptr1);
572135f7de5SShteryana Shopova break;
573135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyType:
574135f7de5SShteryana Shopova view->exclude = ctx->scratch->int1;
575135f7de5SShteryana Shopova break;
576135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyStatus:
577135f7de5SShteryana Shopova if (ctx->scratch->int1 == RowStatus_destroy)
578135f7de5SShteryana Shopova return (vacm_delete_view(view));
579135f7de5SShteryana Shopova break;
580135f7de5SShteryana Shopova default:
581135f7de5SShteryana Shopova break;
582135f7de5SShteryana Shopova }
583135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
584135f7de5SShteryana Shopova
585135f7de5SShteryana Shopova default:
586135f7de5SShteryana Shopova abort();
587135f7de5SShteryana Shopova }
588135f7de5SShteryana Shopova
589135f7de5SShteryana Shopova switch (val->var.subs[sub - 1]) {
590135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyMask:
591135f7de5SShteryana Shopova return (string_get(val, view->mask, sizeof(view->mask)));
592135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyType:
593135f7de5SShteryana Shopova if (view->exclude)
594135f7de5SShteryana Shopova val->v.integer = vacmViewTreeFamilyType_excluded;
595135f7de5SShteryana Shopova else
596135f7de5SShteryana Shopova val->v.integer = vacmViewTreeFamilyType_included;
597135f7de5SShteryana Shopova break;
598135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyStorageType:
599135f7de5SShteryana Shopova val->v.integer = view->type;
600135f7de5SShteryana Shopova break;
601135f7de5SShteryana Shopova case LEAF_vacmViewTreeFamilyStatus:
602135f7de5SShteryana Shopova val->v.integer = view->status;
603135f7de5SShteryana Shopova break;
604135f7de5SShteryana Shopova default:
605135f7de5SShteryana Shopova abort();
606135f7de5SShteryana Shopova }
607135f7de5SShteryana Shopova
608135f7de5SShteryana Shopova return (SNMP_ERR_NOERROR);
609135f7de5SShteryana Shopova }
610135f7de5SShteryana Shopova
611135f7de5SShteryana Shopova static void
vacm_append_userindex(struct asn_oid * oid,uint sub,const struct vacm_user * user)612135f7de5SShteryana Shopova vacm_append_userindex(struct asn_oid *oid, uint sub,
613135f7de5SShteryana Shopova const struct vacm_user *user)
614135f7de5SShteryana Shopova {
615135f7de5SShteryana Shopova uint32_t i;
616135f7de5SShteryana Shopova
617135f7de5SShteryana Shopova oid->len = sub + strlen(user->secname) + 2;
618135f7de5SShteryana Shopova oid->subs[sub++] = user->sec_model;
619135f7de5SShteryana Shopova oid->subs[sub] = strlen(user->secname);
620135f7de5SShteryana Shopova for (i = 1; i <= strlen(user->secname); i++)
621135f7de5SShteryana Shopova oid->subs[sub + i] = user->secname[i - 1];
622135f7de5SShteryana Shopova }
623135f7de5SShteryana Shopova
624135f7de5SShteryana Shopova static int
vacm_user_index_decode(const struct asn_oid * oid,uint sub,int32_t * smodel,char * uname)625135f7de5SShteryana Shopova vacm_user_index_decode(const struct asn_oid *oid, uint sub,
626135f7de5SShteryana Shopova int32_t *smodel, char *uname)
627135f7de5SShteryana Shopova {
628135f7de5SShteryana Shopova uint32_t i;
629135f7de5SShteryana Shopova
630135f7de5SShteryana Shopova *smodel = oid->subs[sub++];
631135f7de5SShteryana Shopova
632135f7de5SShteryana Shopova if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
633135f7de5SShteryana Shopova return (-1);
634135f7de5SShteryana Shopova
635135f7de5SShteryana Shopova for (i = 0; i < oid->subs[sub]; i++)
636135f7de5SShteryana Shopova uname[i] = oid->subs[sub + i + 1];
637135f7de5SShteryana Shopova uname[i] = '\0';
638135f7de5SShteryana Shopova
639135f7de5SShteryana Shopova return (0);
640135f7de5SShteryana Shopova }
641135f7de5SShteryana Shopova
642135f7de5SShteryana Shopova static struct vacm_user *
vacm_get_user(const struct asn_oid * oid,uint sub)643135f7de5SShteryana Shopova vacm_get_user(const struct asn_oid *oid, uint sub)
644135f7de5SShteryana Shopova {
645135f7de5SShteryana Shopova int32_t smodel;
646135f7de5SShteryana Shopova char uname[SNMP_ADM_STR32_SIZ];
647135f7de5SShteryana Shopova struct vacm_user *user;
648135f7de5SShteryana Shopova
649135f7de5SShteryana Shopova if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
650135f7de5SShteryana Shopova return (NULL);
651135f7de5SShteryana Shopova
652135f7de5SShteryana Shopova for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
653135f7de5SShteryana Shopova if (strcmp(uname, user->secname) == 0 &&
654135f7de5SShteryana Shopova user->sec_model == smodel)
655135f7de5SShteryana Shopova return (user);
656135f7de5SShteryana Shopova
657135f7de5SShteryana Shopova return (NULL);
658135f7de5SShteryana Shopova }
659135f7de5SShteryana Shopova
660135f7de5SShteryana Shopova static struct vacm_user *
vacm_get_next_user(const struct asn_oid * oid,uint sub)661135f7de5SShteryana Shopova vacm_get_next_user(const struct asn_oid *oid, uint sub)
662135f7de5SShteryana Shopova {
663135f7de5SShteryana Shopova int32_t smodel;
664135f7de5SShteryana Shopova char uname[SNMP_ADM_STR32_SIZ];
665135f7de5SShteryana Shopova struct vacm_user *user;
666135f7de5SShteryana Shopova
667135f7de5SShteryana Shopova if (oid->len - sub == 0)
668135f7de5SShteryana Shopova return (vacm_first_user());
669135f7de5SShteryana Shopova
670135f7de5SShteryana Shopova if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
671135f7de5SShteryana Shopova return (NULL);
672135f7de5SShteryana Shopova
673135f7de5SShteryana Shopova for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
674135f7de5SShteryana Shopova if (strcmp(uname, user->secname) == 0 &&
675135f7de5SShteryana Shopova user->sec_model == smodel)
676135f7de5SShteryana Shopova return (vacm_next_user(user));
677135f7de5SShteryana Shopova
678135f7de5SShteryana Shopova return (NULL);
679135f7de5SShteryana Shopova }
680135f7de5SShteryana Shopova
681135f7de5SShteryana Shopova static void
vacm_append_access_rule_index(struct asn_oid * oid,uint sub,const struct vacm_access * acl)682135f7de5SShteryana Shopova vacm_append_access_rule_index(struct asn_oid *oid, uint sub,
683135f7de5SShteryana Shopova const struct vacm_access *acl)
684135f7de5SShteryana Shopova {
685135f7de5SShteryana Shopova uint32_t i;
686135f7de5SShteryana Shopova
687135f7de5SShteryana Shopova oid->len = sub + strlen(acl->group->groupname) +
688135f7de5SShteryana Shopova strlen(acl->ctx_prefix) + 4;
689135f7de5SShteryana Shopova
690135f7de5SShteryana Shopova oid->subs[sub] = strlen(acl->group->groupname);
691135f7de5SShteryana Shopova for (i = 1; i <= strlen(acl->group->groupname); i++)
692135f7de5SShteryana Shopova oid->subs[sub + i] = acl->group->groupname[i - 1];
693135f7de5SShteryana Shopova sub += strlen(acl->group->groupname) + 1;
694135f7de5SShteryana Shopova
695135f7de5SShteryana Shopova oid->subs[sub] = strlen(acl->ctx_prefix);
696135f7de5SShteryana Shopova for (i = 1; i <= strlen(acl->ctx_prefix); i++)
697135f7de5SShteryana Shopova oid->subs[sub + i] = acl->ctx_prefix[i - 1];
698135f7de5SShteryana Shopova sub += strlen(acl->ctx_prefix) + 1;
699135f7de5SShteryana Shopova oid->subs[sub++] = acl->sec_model;
700135f7de5SShteryana Shopova oid->subs[sub] = acl->sec_level;
701135f7de5SShteryana Shopova }
702135f7de5SShteryana Shopova
703135f7de5SShteryana Shopova static int
vacm_access_rule_index_decode(const struct asn_oid * oid,uint sub,char * gname,char * cprefix,int32_t * smodel,int32_t * slevel)704135f7de5SShteryana Shopova vacm_access_rule_index_decode(const struct asn_oid *oid, uint sub, char *gname,
705135f7de5SShteryana Shopova char *cprefix, int32_t *smodel, int32_t *slevel)
706135f7de5SShteryana Shopova {
707135f7de5SShteryana Shopova uint32_t i;
708135f7de5SShteryana Shopova
709135f7de5SShteryana Shopova if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
710135f7de5SShteryana Shopova return (-1);
711135f7de5SShteryana Shopova
712135f7de5SShteryana Shopova for (i = 0; i < oid->subs[sub]; i++)
713135f7de5SShteryana Shopova gname[i] = oid->subs[sub + i + 1];
714135f7de5SShteryana Shopova gname[i] = '\0';
715135f7de5SShteryana Shopova sub += strlen(gname) + 1;
716135f7de5SShteryana Shopova
717135f7de5SShteryana Shopova if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
718135f7de5SShteryana Shopova return (-1);
719135f7de5SShteryana Shopova
720135f7de5SShteryana Shopova for (i = 0; i < oid->subs[sub]; i++)
721135f7de5SShteryana Shopova cprefix[i] = oid->subs[sub + i + 1];
722135f7de5SShteryana Shopova cprefix[i] = '\0';
723135f7de5SShteryana Shopova sub += strlen(cprefix) + 1;
724135f7de5SShteryana Shopova
725135f7de5SShteryana Shopova *smodel = oid->subs[sub++];
726135f7de5SShteryana Shopova *slevel = oid->subs[sub];
727135f7de5SShteryana Shopova
728135f7de5SShteryana Shopova return (0);
729135f7de5SShteryana Shopova }
730135f7de5SShteryana Shopova
731135f7de5SShteryana Shopova struct vacm_access *
vacm_get_access_rule(const struct asn_oid * oid,uint sub)732135f7de5SShteryana Shopova vacm_get_access_rule(const struct asn_oid *oid, uint sub)
733135f7de5SShteryana Shopova {
734135f7de5SShteryana Shopova int32_t smodel, slevel;
735135f7de5SShteryana Shopova char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
736135f7de5SShteryana Shopova struct vacm_access *acl;
737135f7de5SShteryana Shopova
738135f7de5SShteryana Shopova if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
739135f7de5SShteryana Shopova &slevel) < 0)
740135f7de5SShteryana Shopova return (NULL);
741135f7de5SShteryana Shopova
742135f7de5SShteryana Shopova for (acl = vacm_first_access_rule(); acl != NULL;
743135f7de5SShteryana Shopova acl = vacm_next_access_rule(acl))
744135f7de5SShteryana Shopova if (strcmp(gname, acl->group->groupname) == 0 &&
745135f7de5SShteryana Shopova strcmp(prefix, acl->ctx_prefix) == 0 &&
746135f7de5SShteryana Shopova smodel == acl->sec_model && slevel == acl->sec_level)
747135f7de5SShteryana Shopova return (acl);
748135f7de5SShteryana Shopova
749135f7de5SShteryana Shopova return (NULL);
750135f7de5SShteryana Shopova }
751135f7de5SShteryana Shopova
752135f7de5SShteryana Shopova struct vacm_access *
vacm_get_next_access_rule(const struct asn_oid * oid __unused,uint sub __unused)753135f7de5SShteryana Shopova vacm_get_next_access_rule(const struct asn_oid *oid __unused, uint sub __unused)
754135f7de5SShteryana Shopova {
755135f7de5SShteryana Shopova int32_t smodel, slevel;
756135f7de5SShteryana Shopova char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
757135f7de5SShteryana Shopova struct vacm_access *acl;
758135f7de5SShteryana Shopova
759135f7de5SShteryana Shopova if (oid->len - sub == 0)
760135f7de5SShteryana Shopova return (vacm_first_access_rule());
761135f7de5SShteryana Shopova
762135f7de5SShteryana Shopova if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
763135f7de5SShteryana Shopova &slevel) < 0)
764135f7de5SShteryana Shopova return (NULL);
765135f7de5SShteryana Shopova
766135f7de5SShteryana Shopova for (acl = vacm_first_access_rule(); acl != NULL;
767135f7de5SShteryana Shopova acl = vacm_next_access_rule(acl))
768135f7de5SShteryana Shopova if (strcmp(gname, acl->group->groupname) == 0 &&
769135f7de5SShteryana Shopova strcmp(prefix, acl->ctx_prefix) == 0 &&
770135f7de5SShteryana Shopova smodel == acl->sec_model && slevel == acl->sec_model)
771135f7de5SShteryana Shopova return (vacm_next_access_rule(acl));
772135f7de5SShteryana Shopova
773135f7de5SShteryana Shopova return (NULL);
774135f7de5SShteryana Shopova }
775135f7de5SShteryana Shopova
776135f7de5SShteryana Shopova static int
vacm_view_index_decode(const struct asn_oid * oid,uint sub,char * vname,struct asn_oid * view_oid)777135f7de5SShteryana Shopova vacm_view_index_decode(const struct asn_oid *oid, uint sub, char *vname,
778135f7de5SShteryana Shopova struct asn_oid *view_oid)
779135f7de5SShteryana Shopova {
780135f7de5SShteryana Shopova uint32_t i;
781135f7de5SShteryana Shopova int viod_off;
782135f7de5SShteryana Shopova
783135f7de5SShteryana Shopova if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
784135f7de5SShteryana Shopova return (-1);
785135f7de5SShteryana Shopova
786135f7de5SShteryana Shopova for (i = 0; i < oid->subs[sub]; i++)
787135f7de5SShteryana Shopova vname[i] = oid->subs[sub + i + 1];
788135f7de5SShteryana Shopova vname[i] = '\0';
789135f7de5SShteryana Shopova
790135f7de5SShteryana Shopova viod_off = sub + oid->subs[sub] + 1;
791135f7de5SShteryana Shopova if ((view_oid->len = oid->subs[viod_off]) > ASN_MAXOIDLEN)
792135f7de5SShteryana Shopova return (-1);
793135f7de5SShteryana Shopova
794135f7de5SShteryana Shopova memcpy(&view_oid->subs[0], &oid->subs[viod_off + 1],
795135f7de5SShteryana Shopova view_oid->len * sizeof(view_oid->subs[0]));
796135f7de5SShteryana Shopova
797135f7de5SShteryana Shopova return (0);
798135f7de5SShteryana Shopova }
799135f7de5SShteryana Shopova
800135f7de5SShteryana Shopova static void
vacm_append_viewindex(struct asn_oid * oid,uint sub,const struct vacm_view * view)801135f7de5SShteryana Shopova vacm_append_viewindex(struct asn_oid *oid, uint sub, const struct vacm_view *view)
802135f7de5SShteryana Shopova {
803135f7de5SShteryana Shopova uint32_t i;
804135f7de5SShteryana Shopova
805135f7de5SShteryana Shopova oid->len = sub + strlen(view->viewname) + 1;
806135f7de5SShteryana Shopova oid->subs[sub] = strlen(view->viewname);
807135f7de5SShteryana Shopova for (i = 1; i <= strlen(view->viewname); i++)
808135f7de5SShteryana Shopova oid->subs[sub + i] = view->viewname[i - 1];
809135f7de5SShteryana Shopova
810135f7de5SShteryana Shopova sub += strlen(view->viewname) + 1;
811135f7de5SShteryana Shopova oid->subs[sub] = view->subtree.len;
812135f7de5SShteryana Shopova oid->len++;
813135f7de5SShteryana Shopova asn_append_oid(oid, &view->subtree);
814135f7de5SShteryana Shopova }
815135f7de5SShteryana Shopova
816135f7de5SShteryana Shopova struct vacm_view *
vacm_get_view(const struct asn_oid * oid,uint sub)817135f7de5SShteryana Shopova vacm_get_view(const struct asn_oid *oid, uint sub)
818135f7de5SShteryana Shopova {
819135f7de5SShteryana Shopova char vname[SNMP_ADM_STR32_SIZ];
820135f7de5SShteryana Shopova struct asn_oid subtree;
821135f7de5SShteryana Shopova struct vacm_view *view;
822135f7de5SShteryana Shopova
823135f7de5SShteryana Shopova if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
824135f7de5SShteryana Shopova return (NULL);
825135f7de5SShteryana Shopova
826135f7de5SShteryana Shopova for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
827135f7de5SShteryana Shopova if (strcmp(vname, view->viewname) == 0 &&
828135f7de5SShteryana Shopova asn_compare_oid(&subtree, &view->subtree)== 0)
829135f7de5SShteryana Shopova return (view);
830135f7de5SShteryana Shopova
831135f7de5SShteryana Shopova return (NULL);
832135f7de5SShteryana Shopova }
833135f7de5SShteryana Shopova
834135f7de5SShteryana Shopova struct vacm_view *
vacm_get_next_view(const struct asn_oid * oid,uint sub)835135f7de5SShteryana Shopova vacm_get_next_view(const struct asn_oid *oid, uint sub)
836135f7de5SShteryana Shopova {
837135f7de5SShteryana Shopova char vname[SNMP_ADM_STR32_SIZ];
838135f7de5SShteryana Shopova struct asn_oid subtree;
839135f7de5SShteryana Shopova struct vacm_view *view;
840135f7de5SShteryana Shopova
841135f7de5SShteryana Shopova if (oid->len - sub == 0)
842135f7de5SShteryana Shopova return (vacm_first_view());
843135f7de5SShteryana Shopova
844135f7de5SShteryana Shopova if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
845135f7de5SShteryana Shopova return (NULL);
846135f7de5SShteryana Shopova
847135f7de5SShteryana Shopova for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
848135f7de5SShteryana Shopova if (strcmp(vname, view->viewname) == 0 &&
849135f7de5SShteryana Shopova asn_compare_oid(&subtree, &view->subtree)== 0)
850135f7de5SShteryana Shopova return (vacm_next_view(view));
851135f7de5SShteryana Shopova
852135f7de5SShteryana Shopova return (NULL);
853135f7de5SShteryana Shopova }
854135f7de5SShteryana Shopova
855135f7de5SShteryana Shopova static struct vacm_view *
vacm_get_view_by_name(u_char * octets,u_int len)856135f7de5SShteryana Shopova vacm_get_view_by_name(u_char *octets, u_int len)
857135f7de5SShteryana Shopova {
858135f7de5SShteryana Shopova struct vacm_view *view;
859135f7de5SShteryana Shopova
860135f7de5SShteryana Shopova for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
861135f7de5SShteryana Shopova if (strlen(view->viewname) == len &&
862135f7de5SShteryana Shopova memcmp(octets, view->viewname, len) == 0)
863135f7de5SShteryana Shopova return (view);
864135f7de5SShteryana Shopova
865135f7de5SShteryana Shopova return (NULL);
866135f7de5SShteryana Shopova }
867135f7de5SShteryana Shopova
868135f7de5SShteryana Shopova static struct vacm_context *
vacm_get_context(const struct asn_oid * oid,uint sub)869135f7de5SShteryana Shopova vacm_get_context(const struct asn_oid *oid, uint sub)
870135f7de5SShteryana Shopova {
871135f7de5SShteryana Shopova char cname[SNMP_ADM_STR32_SIZ];
872135f7de5SShteryana Shopova size_t cnamelen;
873135f7de5SShteryana Shopova u_int index_count;
874135f7de5SShteryana Shopova struct vacm_context *vacm_ctx;
875135f7de5SShteryana Shopova
876135f7de5SShteryana Shopova if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
877135f7de5SShteryana Shopova return (NULL);
878135f7de5SShteryana Shopova
879135f7de5SShteryana Shopova index_count = 0;
880135f7de5SShteryana Shopova index_count = SNMP_INDEX(index_count, 1);
881135f7de5SShteryana Shopova if (index_decode(oid, sub, index_count, &cname, &cnamelen))
882135f7de5SShteryana Shopova return (NULL);
883135f7de5SShteryana Shopova
884135f7de5SShteryana Shopova for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
885135f7de5SShteryana Shopova vacm_ctx = vacm_next_context(vacm_ctx))
886135f7de5SShteryana Shopova if (strcmp(cname, vacm_ctx->ctxname) == 0)
887135f7de5SShteryana Shopova return (vacm_ctx);
888135f7de5SShteryana Shopova
889135f7de5SShteryana Shopova return (NULL);
890135f7de5SShteryana Shopova }
891135f7de5SShteryana Shopova
892135f7de5SShteryana Shopova static struct vacm_context *
vacm_get_next_context(const struct asn_oid * oid,uint sub)893135f7de5SShteryana Shopova vacm_get_next_context(const struct asn_oid *oid, uint sub)
894135f7de5SShteryana Shopova {
895135f7de5SShteryana Shopova char cname[SNMP_ADM_STR32_SIZ];
896135f7de5SShteryana Shopova size_t cnamelen;
897135f7de5SShteryana Shopova u_int index_count;
898135f7de5SShteryana Shopova struct vacm_context *vacm_ctx;
899135f7de5SShteryana Shopova
900135f7de5SShteryana Shopova if (oid->len - sub == 0)
901135f7de5SShteryana Shopova return (vacm_first_context());
902135f7de5SShteryana Shopova
903135f7de5SShteryana Shopova if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
904135f7de5SShteryana Shopova return (NULL);
905135f7de5SShteryana Shopova
906135f7de5SShteryana Shopova index_count = 0;
907135f7de5SShteryana Shopova index_count = SNMP_INDEX(index_count, 1);
908135f7de5SShteryana Shopova if (index_decode(oid, sub, index_count, &cname, &cnamelen))
909135f7de5SShteryana Shopova return (NULL);
910135f7de5SShteryana Shopova
911135f7de5SShteryana Shopova for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
912135f7de5SShteryana Shopova vacm_ctx = vacm_next_context(vacm_ctx))
913135f7de5SShteryana Shopova if (strcmp(cname, vacm_ctx->ctxname) == 0)
914135f7de5SShteryana Shopova return (vacm_next_context(vacm_ctx));
915135f7de5SShteryana Shopova
916135f7de5SShteryana Shopova return (NULL);
917135f7de5SShteryana Shopova }
918135f7de5SShteryana Shopova
919135f7de5SShteryana Shopova static void
vacm_append_ctxindex(struct asn_oid * oid,uint sub,const struct vacm_context * ctx)920135f7de5SShteryana Shopova vacm_append_ctxindex(struct asn_oid *oid, uint sub,
921135f7de5SShteryana Shopova const struct vacm_context *ctx)
922135f7de5SShteryana Shopova {
923135f7de5SShteryana Shopova uint32_t i;
924135f7de5SShteryana Shopova
925135f7de5SShteryana Shopova oid->len = sub + strlen(ctx->ctxname) + 1;
926135f7de5SShteryana Shopova oid->subs[sub] = strlen(ctx->ctxname);
927135f7de5SShteryana Shopova for (i = 1; i <= strlen(ctx->ctxname); i++)
928135f7de5SShteryana Shopova oid->subs[sub + i] = ctx->ctxname[i - 1];
929135f7de5SShteryana Shopova }
930135f7de5SShteryana Shopova
931135f7de5SShteryana Shopova /*
932135f7de5SShteryana Shopova * VACM snmp module initialization hook.
933135f7de5SShteryana Shopova * Returns 0 on success, < 0 on error.
934135f7de5SShteryana Shopova */
935135f7de5SShteryana Shopova static int
vacm_init(struct lmodule * mod,int argc __unused,char * argv[]__unused)936135f7de5SShteryana Shopova vacm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
937135f7de5SShteryana Shopova {
938135f7de5SShteryana Shopova vacm_module = mod;
939135f7de5SShteryana Shopova vacm_lock = random();
940135f7de5SShteryana Shopova vacm_groups_init();
941135f7de5SShteryana Shopova
942135f7de5SShteryana Shopova /* XXX: TODO - initialize structures */
943135f7de5SShteryana Shopova return (0);
944135f7de5SShteryana Shopova }
945135f7de5SShteryana Shopova
946135f7de5SShteryana Shopova /*
947135f7de5SShteryana Shopova * VACM snmp module finalization hook.
948135f7de5SShteryana Shopova */
949135f7de5SShteryana Shopova static int
vacm_fini(void)950135f7de5SShteryana Shopova vacm_fini(void)
951135f7de5SShteryana Shopova {
952135f7de5SShteryana Shopova /* XXX: TODO - cleanup */
953135f7de5SShteryana Shopova vacm_flush_contexts(reg_vacm);
954135f7de5SShteryana Shopova or_unregister(reg_vacm);
955135f7de5SShteryana Shopova
956135f7de5SShteryana Shopova return (0);
957135f7de5SShteryana Shopova }
958135f7de5SShteryana Shopova
959135f7de5SShteryana Shopova /*
960135f7de5SShteryana Shopova * VACM snmp module start operation.
961135f7de5SShteryana Shopova */
962135f7de5SShteryana Shopova static void
vacm_start(void)963135f7de5SShteryana Shopova vacm_start(void)
964135f7de5SShteryana Shopova {
965135f7de5SShteryana Shopova static char dflt_ctx[] = "";
966135f7de5SShteryana Shopova
967135f7de5SShteryana Shopova reg_vacm = or_register(&oid_vacm,
968135f7de5SShteryana Shopova "The MIB module for managing SNMP View-based Access Control Model.",
969135f7de5SShteryana Shopova vacm_module);
970135f7de5SShteryana Shopova
971135f7de5SShteryana Shopova (void)vacm_add_context(dflt_ctx, reg_vacm);
972135f7de5SShteryana Shopova }
973135f7de5SShteryana Shopova
974135f7de5SShteryana Shopova static void
vacm_dump(void)975135f7de5SShteryana Shopova vacm_dump(void)
976135f7de5SShteryana Shopova {
977135f7de5SShteryana Shopova struct vacm_context *vacmctx;
978135f7de5SShteryana Shopova struct vacm_user *vuser;
979135f7de5SShteryana Shopova struct vacm_access *vacl;
980135f7de5SShteryana Shopova struct vacm_view *view;
981135f7de5SShteryana Shopova static char oidbuf[ASN_OIDSTRLEN];
982135f7de5SShteryana Shopova
983135f7de5SShteryana Shopova syslog(LOG_ERR, "\n");
984135f7de5SShteryana Shopova syslog(LOG_ERR, "Context list:");
985135f7de5SShteryana Shopova for (vacmctx = vacm_first_context(); vacmctx != NULL;
986135f7de5SShteryana Shopova vacmctx = vacm_next_context(vacmctx))
987135f7de5SShteryana Shopova syslog(LOG_ERR, "Context \"%s\", module id %d",
988135f7de5SShteryana Shopova vacmctx->ctxname, vacmctx->regid);
989135f7de5SShteryana Shopova
990135f7de5SShteryana Shopova syslog(LOG_ERR, "VACM users:");
991135f7de5SShteryana Shopova for (vuser = vacm_first_user(); vuser != NULL;
992135f7de5SShteryana Shopova vuser = vacm_next_user(vuser))
993135f7de5SShteryana Shopova syslog(LOG_ERR, "Uname %s, Group %s, model %d", vuser->secname,
994135f7de5SShteryana Shopova vuser->group!= NULL?vuser->group->groupname:"Unknown",
995135f7de5SShteryana Shopova vuser->sec_model);
996135f7de5SShteryana Shopova
997135f7de5SShteryana Shopova syslog(LOG_ERR, "VACM Access rules:");
998135f7de5SShteryana Shopova for (vacl = vacm_first_access_rule(); vacl != NULL;
999135f7de5SShteryana Shopova vacl = vacm_next_access_rule(vacl))
1000135f7de5SShteryana Shopova syslog(LOG_ERR, "Group %s, CtxPrefix %s, Model %d, Level %d, "
1001135f7de5SShteryana Shopova "RV %s, WR %s, NV %s", vacl->group!=NULL?
1002135f7de5SShteryana Shopova vacl->group->groupname:"Unknown", vacl->ctx_prefix,
1003135f7de5SShteryana Shopova vacl->sec_model, vacl->sec_level, vacl->read_view!=NULL?
1004135f7de5SShteryana Shopova vacl->read_view->viewname:"None", vacl->write_view!=NULL?
1005135f7de5SShteryana Shopova vacl->write_view->viewname:"None", vacl->notify_view!=NULL?
1006135f7de5SShteryana Shopova vacl->notify_view->viewname:"None");
1007135f7de5SShteryana Shopova
1008135f7de5SShteryana Shopova syslog(LOG_ERR, "VACM Views:");
1009135f7de5SShteryana Shopova for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
1010135f7de5SShteryana Shopova syslog(LOG_ERR, "View %s, Tree %s - %s", view->viewname,
1011135f7de5SShteryana Shopova asn_oid2str_r(&view->subtree, oidbuf), view->exclude?
1012135f7de5SShteryana Shopova "excluded":"included");
1013135f7de5SShteryana Shopova }
1014135f7de5SShteryana Shopova
1015*0bf56da3SHartmut Brandt static const char vacm_comment[] =
1016135f7de5SShteryana Shopova "This module implements SNMP View-based Access Control Model defined in RFC 3415.";
1017135f7de5SShteryana Shopova
10188e9b3e70SHartmut Brandt extern const struct snmp_module config;
1019135f7de5SShteryana Shopova const struct snmp_module config = {
1020135f7de5SShteryana Shopova .comment = vacm_comment,
1021135f7de5SShteryana Shopova .init = vacm_init,
1022135f7de5SShteryana Shopova .fini = vacm_fini,
1023135f7de5SShteryana Shopova .start = vacm_start,
1024135f7de5SShteryana Shopova .tree = vacm_ctree,
1025135f7de5SShteryana Shopova .dump = vacm_dump,
1026135f7de5SShteryana Shopova .tree_size = vacm_CTREE_SIZE,
1027135f7de5SShteryana Shopova };
1028