2 * Copyright (c) 2010,2018 The FreeBSD Foundation
5 * This software was developed by Shteryana Sotirova Shopova under
6 * sponsorship from the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/queue.h>
32 #include <sys/types.h>
46 #define SNMPTREE_TYPES
47 #include "vacm_tree.h"
50 static struct lmodule *vacm_module;
51 /* For the registration. */
52 static const struct asn_oid oid_vacm = OIDX_snmpVacmMIB;
56 static int32_t vacm_lock;
59 * Internal datastructures and forward declarations.
61 static void vacm_append_userindex(struct asn_oid *,
62 uint, const struct vacm_user *);
63 static int vacm_user_index_decode(const struct asn_oid *,
64 uint, int32_t *, char *);
65 static struct vacm_user *vacm_get_user(const struct asn_oid *,
67 static struct vacm_user *vacm_get_next_user(const struct asn_oid *,
69 static void vacm_append_access_rule_index(struct asn_oid *,
70 uint, const struct vacm_access *);
71 static int vacm_access_rule_index_decode(const struct asn_oid *,
72 uint, char *, char *, int32_t *, int32_t *);
73 static struct vacm_access * vacm_get_access_rule(const struct asn_oid *,
75 static struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *,
77 static int vacm_view_index_decode(const struct asn_oid *, uint,
78 char *, struct asn_oid *);
79 static void vacm_append_viewindex(struct asn_oid *, uint,
80 const struct vacm_view *);
81 static struct vacm_view *vacm_get_view(const struct asn_oid *, uint);
82 static struct vacm_view *vacm_get_next_view(const struct asn_oid *, uint);
83 static struct vacm_view *vacm_get_view_by_name(u_char *, u_int);
84 static struct vacm_context *vacm_get_context(const struct asn_oid *, uint);
85 static struct vacm_context *vacm_get_next_context(const struct asn_oid *,
87 static void vacm_append_ctxindex(struct asn_oid *, uint,
88 const struct vacm_context *);
91 op_vacm_context(struct snmp_context *ctx __unused, struct snmp_value *val,
92 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
94 char cname[SNMP_ADM_STR32_SIZ];
96 struct vacm_context *vacm_ctx;
98 if (val->var.subs[sub - 1] != LEAF_vacmContextName)
103 if ((vacm_ctx = vacm_get_context(&val->var, sub)) == NULL)
104 return (SNMP_ERR_NOSUCHNAME);
107 case SNMP_OP_GETNEXT:
108 if ((vacm_ctx = vacm_get_next_context(&val->var, sub)) == NULL)
109 return (SNMP_ERR_NOSUCHNAME);
110 vacm_append_ctxindex(&val->var, sub, vacm_ctx);
114 if ((vacm_ctx = vacm_get_context(&val->var, sub)) != NULL)
115 return (SNMP_ERR_WRONG_VALUE);
116 if (community != COMM_INITIALIZE)
117 return (SNMP_ERR_NOT_WRITEABLE);
118 if (val->var.subs[sub] >= SNMP_ADM_STR32_SIZ)
119 return (SNMP_ERR_WRONG_VALUE);
120 if (index_decode(&val->var, sub, iidx, &cname, &cnamelen))
121 return (SNMP_ERR_GENERR);
122 cname[cnamelen] = '\0';
123 if ((vacm_ctx = vacm_add_context(cname, reg_vacm)) == NULL)
124 return (SNMP_ERR_GENERR);
125 return (SNMP_ERR_NOERROR);
129 case SNMP_OP_ROLLBACK:
130 return (SNMP_ERR_NOERROR);
135 return (string_get(val, vacm_ctx->ctxname, -1));
139 op_vacm_security_to_group(struct snmp_context *ctx, struct snmp_value *val,
140 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
143 char uname[SNMP_ADM_STR32_SIZ];
144 struct vacm_user *user;
148 if ((user = vacm_get_user(&val->var, sub)) == NULL)
149 return (SNMP_ERR_NOSUCHNAME);
152 case SNMP_OP_GETNEXT:
153 if ((user = vacm_get_next_user(&val->var, sub)) == NULL)
154 return (SNMP_ERR_NOSUCHNAME);
155 vacm_append_userindex(&val->var, sub, user);
159 if ((user = vacm_get_user(&val->var, sub)) == NULL &&
160 val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
161 return (SNMP_ERR_NOSUCHNAME);
164 if (community != COMM_INITIALIZE &&
165 user->type == StorageType_readOnly)
166 return (SNMP_ERR_NOT_WRITEABLE);
167 if (user->status == RowStatus_active &&
168 val->v.integer != RowStatus_destroy)
169 return (SNMP_ERR_INCONS_VALUE);
172 switch (val->var.subs[sub - 1]) {
173 case LEAF_vacmGroupName:
174 ctx->scratch->ptr1 = user->group->groupname;
175 ctx->scratch->int1 = strlen(user->group->groupname);
176 return (vacm_user_set_group(user,
177 val->v.octetstring.octets,val->v.octetstring.len));
179 case LEAF_vacmSecurityToGroupStorageType:
180 return (SNMP_ERR_INCONS_VALUE);
182 case LEAF_vacmSecurityToGroupStatus:
184 if (val->v.integer != RowStatus_createAndGo ||
185 vacm_user_index_decode(&val->var, sub,
187 return (SNMP_ERR_INCONS_VALUE);
188 user = vacm_new_user(smodel, uname);
190 return (SNMP_ERR_GENERR);
191 user->status = RowStatus_destroy;
192 if (community != COMM_INITIALIZE)
193 user->type = StorageType_volatile;
195 user->type = StorageType_readOnly;
196 } else if (val->v.integer != RowStatus_active &&
197 val->v.integer != RowStatus_destroy)
198 return (SNMP_ERR_INCONS_VALUE);
199 ctx->scratch->int1 = user->status;
200 user->status = val->v.integer;
203 return (SNMP_ERR_NOERROR);
206 if (val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
207 return (SNMP_ERR_NOERROR);
208 if ((user = vacm_get_user(&val->var, sub)) == NULL)
209 return (SNMP_ERR_GENERR);
210 switch (val->v.integer) {
211 case RowStatus_destroy:
212 return (vacm_delete_user(user));
214 case RowStatus_createAndGo:
215 user->status = RowStatus_active;
221 return (SNMP_ERR_NOERROR);
223 case SNMP_OP_ROLLBACK:
224 if ((user = vacm_get_user(&val->var, sub)) == NULL)
225 return (SNMP_ERR_GENERR);
226 switch (val->var.subs[sub - 1]) {
227 case LEAF_vacmGroupName:
228 return (vacm_user_set_group(user, ctx->scratch->ptr1,
229 ctx->scratch->int1));
231 case LEAF_vacmSecurityToGroupStatus:
232 if (ctx->scratch->int1 == RowStatus_destroy)
233 return (vacm_delete_user(user));
234 user->status = ctx->scratch->int1;
240 return (SNMP_ERR_NOERROR);
246 switch (val->var.subs[sub - 1]) {
247 case LEAF_vacmGroupName:
248 return (string_get(val, user->group->groupname, -1));
249 case LEAF_vacmSecurityToGroupStorageType:
250 val->v.integer = user->type;
252 case LEAF_vacmSecurityToGroupStatus:
253 val->v.integer = user->status;
259 return (SNMP_ERR_NOERROR);
263 op_vacm_access(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
264 uint32_t iidx __unused, enum snmp_op op)
266 int32_t smodel, slevel;
267 char gname[SNMP_ADM_STR32_SIZ], cprefix[SNMP_ADM_STR32_SIZ];
268 struct vacm_access *acl;
272 if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
273 return (SNMP_ERR_NOSUCHNAME);
276 case SNMP_OP_GETNEXT:
277 if ((acl = vacm_get_next_access_rule(&val->var, sub)) == NULL)
278 return (SNMP_ERR_NOSUCHNAME);
279 vacm_append_access_rule_index(&val->var, sub, acl);
283 if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL &&
284 val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
285 return (SNMP_ERR_NOSUCHNAME);
286 if (acl != NULL && community != COMM_INITIALIZE &&
287 acl->type == StorageType_readOnly)
288 return (SNMP_ERR_NOT_WRITEABLE);
290 switch (val->var.subs[sub - 1]) {
291 case LEAF_vacmAccessContextMatch:
292 ctx->scratch->int1 = acl->ctx_match;
293 if (val->v.integer == vacmAccessContextMatch_exact)
295 else if (val->v.integer == vacmAccessContextMatch_prefix)
298 return (SNMP_ERR_WRONG_VALUE);
301 case LEAF_vacmAccessReadViewName:
302 ctx->scratch->ptr1 = acl->read_view;
303 acl->read_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len);
304 if (acl->read_view == NULL) {
305 acl->read_view = ctx->scratch->ptr1;
306 return (SNMP_ERR_INCONS_VALUE);
308 return (SNMP_ERR_NOERROR);
310 case LEAF_vacmAccessWriteViewName:
311 ctx->scratch->ptr1 = acl->write_view;
312 if ((acl->write_view =
313 vacm_get_view_by_name(val->v.octetstring.octets,
314 val->v.octetstring.len)) == NULL) {
315 acl->write_view = ctx->scratch->ptr1;
316 return (SNMP_ERR_INCONS_VALUE);
320 case LEAF_vacmAccessNotifyViewName:
321 ctx->scratch->ptr1 = acl->notify_view;
322 if ((acl->notify_view =
323 vacm_get_view_by_name(val->v.octetstring.octets,
324 val->v.octetstring.len)) == NULL) {
325 acl->notify_view = ctx->scratch->ptr1;
326 return (SNMP_ERR_INCONS_VALUE);
330 case LEAF_vacmAccessStorageType:
331 return (SNMP_ERR_INCONS_VALUE);
333 case LEAF_vacmAccessStatus:
335 if (val->v.integer != RowStatus_createAndGo ||
336 vacm_access_rule_index_decode(&val->var,
337 sub, gname, cprefix, &smodel, &slevel) < 0)
338 return (SNMP_ERR_INCONS_VALUE);
339 if ((acl = vacm_new_access_rule(gname, cprefix,
340 smodel, slevel)) == NULL)
341 return (SNMP_ERR_GENERR);
342 acl->status = RowStatus_destroy;
343 if (community != COMM_INITIALIZE)
344 acl->type = StorageType_volatile;
346 acl->type = StorageType_readOnly;
347 } else if (val->v.integer != RowStatus_active &&
348 val->v.integer != RowStatus_destroy)
349 return (SNMP_ERR_INCONS_VALUE);
350 ctx->scratch->int1 = acl->status;
351 acl->status = val->v.integer;
354 return (SNMP_ERR_NOERROR);
357 if (val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
358 return (SNMP_ERR_NOERROR);
359 if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
360 return (SNMP_ERR_GENERR);
361 if (val->v.integer == RowStatus_destroy)
362 return (vacm_delete_access_rule(acl));
364 acl->status = RowStatus_active;
365 return (SNMP_ERR_NOERROR);
367 case SNMP_OP_ROLLBACK:
368 if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
369 return (SNMP_ERR_GENERR);
370 switch (val->var.subs[sub - 1]) {
371 case LEAF_vacmAccessContextMatch:
372 acl->ctx_match = ctx->scratch->int1;
374 case LEAF_vacmAccessReadViewName:
375 acl->read_view = ctx->scratch->ptr1;
377 case LEAF_vacmAccessWriteViewName:
378 acl->write_view = ctx->scratch->ptr1;
380 case LEAF_vacmAccessNotifyViewName:
381 acl->notify_view = ctx->scratch->ptr1;
383 case LEAF_vacmAccessStatus:
384 if (ctx->scratch->int1 == RowStatus_destroy)
385 return (vacm_delete_access_rule(acl));
389 return (SNMP_ERR_NOERROR);
395 switch (val->var.subs[sub - 1]) {
396 case LEAF_vacmAccessContextMatch:
397 return (string_get(val, acl->ctx_prefix, -1));
398 case LEAF_vacmAccessReadViewName:
399 if (acl->read_view != NULL)
400 return (string_get(val, acl->read_view->viewname, -1));
402 return (string_get(val, NULL, 0));
403 case LEAF_vacmAccessWriteViewName:
404 if (acl->write_view != NULL)
405 return (string_get(val, acl->write_view->viewname, -1));
407 return (string_get(val, NULL, 0));
408 case LEAF_vacmAccessNotifyViewName:
409 if (acl->notify_view != NULL)
410 return (string_get(val, acl->notify_view->viewname, -1));
412 return (string_get(val, NULL, 0));
413 case LEAF_vacmAccessStorageType:
414 val->v.integer = acl->type;
416 case LEAF_vacmAccessStatus:
417 val->v.integer = acl->status;
423 return (SNMP_ERR_NOERROR);
427 op_vacm_view_lock(struct snmp_context *ctx __unused, struct snmp_value *val,
428 uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
430 if (val->var.subs[sub - 1] != LEAF_vacmViewSpinLock)
431 return (SNMP_ERR_NOSUCHNAME);
435 if (++vacm_lock == INT32_MAX)
437 val->v.integer = vacm_lock;
440 case SNMP_OP_GETNEXT:
444 if (val->v.integer != vacm_lock)
445 return (SNMP_ERR_INCONS_VALUE);
448 case SNMP_OP_ROLLBACK:
454 return (SNMP_ERR_NOERROR);
458 op_vacm_view(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
459 uint32_t iidx __unused, enum snmp_op op)
461 char vname[SNMP_ADM_STR32_SIZ];
463 struct vacm_view *view;
467 if ((view = vacm_get_view(&val->var, sub)) == NULL)
468 return (SNMP_ERR_NOSUCHNAME);
471 case SNMP_OP_GETNEXT:
472 if ((view = vacm_get_next_view(&val->var, sub)) == NULL)
473 return (SNMP_ERR_NOSUCHNAME);
474 vacm_append_viewindex(&val->var, sub, view);
478 if ((view = vacm_get_view(&val->var, sub)) == NULL &&
479 val->var.subs[sub - 1] != LEAF_vacmViewTreeFamilyStatus)
480 return (SNMP_ERR_NOSUCHNAME);
483 if (community != COMM_INITIALIZE &&
484 view->type == StorageType_readOnly)
485 return (SNMP_ERR_NOT_WRITEABLE);
486 if (view->status == RowStatus_active &&
487 val->v.integer != RowStatus_destroy)
488 return (SNMP_ERR_INCONS_VALUE);
491 switch (val->var.subs[sub - 1]) {
492 case LEAF_vacmViewTreeFamilyMask:
493 if (val->v.octetstring.len > sizeof(view->mask))
494 ctx->scratch->ptr1 = malloc(sizeof(view->mask));
495 if (ctx->scratch->ptr1 == NULL)
496 return (SNMP_ERR_GENERR);
497 memset(ctx->scratch->ptr1, 0, sizeof(view->mask));
498 memcpy(ctx->scratch->ptr1, view->mask,
500 memset(view->mask, 0, sizeof(view->mask));
501 memcpy(view->mask, val->v.octetstring.octets,
502 val->v.octetstring.len);
505 case LEAF_vacmViewTreeFamilyType:
506 ctx->scratch->int1 = view->exclude;
507 if (val->v.integer == vacmViewTreeFamilyType_included)
509 else if (val->v.integer == vacmViewTreeFamilyType_excluded)
512 return (SNMP_ERR_WRONG_VALUE);
515 case LEAF_vacmViewTreeFamilyStorageType:
516 return (SNMP_ERR_INCONS_VALUE);
518 case LEAF_vacmViewTreeFamilyStatus:
520 if (val->v.integer != RowStatus_createAndGo ||
521 vacm_view_index_decode(&val->var, sub, vname,
523 return (SNMP_ERR_INCONS_VALUE);
524 if ((view = vacm_new_view(vname, &oid)) == NULL)
525 return (SNMP_ERR_GENERR);
526 view->status = RowStatus_destroy;
527 if (community != COMM_INITIALIZE)
528 view->type = StorageType_volatile;
530 view->type = StorageType_readOnly;
531 } else if (val->v.integer != RowStatus_active &&
532 val->v.integer != RowStatus_destroy)
533 return (SNMP_ERR_INCONS_VALUE);
534 ctx->scratch->int1 = view->status;
535 view->status = val->v.integer;
538 return (SNMP_ERR_NOERROR);
541 switch (val->var.subs[sub - 1]) {
542 case LEAF_vacmViewTreeFamilyMask:
543 free(ctx->scratch->ptr1);
545 case LEAF_vacmViewTreeFamilyStatus:
546 if ((view = vacm_get_view(&val->var, sub)) == NULL)
547 return (SNMP_ERR_GENERR);
548 switch (val->v.integer) {
549 case RowStatus_destroy:
550 return (vacm_delete_view(view));
552 case RowStatus_createAndGo:
553 view->status = RowStatus_active;
558 return (SNMP_ERR_GENERR);
563 return (SNMP_ERR_NOERROR);
565 case SNMP_OP_ROLLBACK:
566 if ((view = vacm_get_view(&val->var, sub)) == NULL)
567 return (SNMP_ERR_GENERR);
568 switch (val->var.subs[sub - 1]) {
569 case LEAF_vacmViewTreeFamilyMask:
570 memcpy(view->mask, ctx->scratch->ptr1,
572 free(ctx->scratch->ptr1);
574 case LEAF_vacmViewTreeFamilyType:
575 view->exclude = ctx->scratch->int1;
577 case LEAF_vacmViewTreeFamilyStatus:
578 if (ctx->scratch->int1 == RowStatus_destroy)
579 return (vacm_delete_view(view));
584 return (SNMP_ERR_NOERROR);
590 switch (val->var.subs[sub - 1]) {
591 case LEAF_vacmViewTreeFamilyMask:
592 return (string_get(val, view->mask, sizeof(view->mask)));
593 case LEAF_vacmViewTreeFamilyType:
595 val->v.integer = vacmViewTreeFamilyType_excluded;
597 val->v.integer = vacmViewTreeFamilyType_included;
599 case LEAF_vacmViewTreeFamilyStorageType:
600 val->v.integer = view->type;
602 case LEAF_vacmViewTreeFamilyStatus:
603 val->v.integer = view->status;
609 return (SNMP_ERR_NOERROR);
613 vacm_append_userindex(struct asn_oid *oid, uint sub,
614 const struct vacm_user *user)
618 oid->len = sub + strlen(user->secname) + 2;
619 oid->subs[sub++] = user->sec_model;
620 oid->subs[sub] = strlen(user->secname);
621 for (i = 1; i <= strlen(user->secname); i++)
622 oid->subs[sub + i] = user->secname[i - 1];
626 vacm_user_index_decode(const struct asn_oid *oid, uint sub,
627 int32_t *smodel, char *uname)
631 *smodel = oid->subs[sub++];
633 if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
636 for (i = 0; i < oid->subs[sub]; i++)
637 uname[i] = oid->subs[sub + i + 1];
643 static struct vacm_user *
644 vacm_get_user(const struct asn_oid *oid, uint sub)
647 char uname[SNMP_ADM_STR32_SIZ];
648 struct vacm_user *user;
650 if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
653 for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
654 if (strcmp(uname, user->secname) == 0 &&
655 user->sec_model == smodel)
661 static struct vacm_user *
662 vacm_get_next_user(const struct asn_oid *oid, uint sub)
665 char uname[SNMP_ADM_STR32_SIZ];
666 struct vacm_user *user;
668 if (oid->len - sub == 0)
669 return (vacm_first_user());
671 if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
674 for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
675 if (strcmp(uname, user->secname) == 0 &&
676 user->sec_model == smodel)
677 return (vacm_next_user(user));
683 vacm_append_access_rule_index(struct asn_oid *oid, uint sub,
684 const struct vacm_access *acl)
688 oid->len = sub + strlen(acl->group->groupname) +
689 strlen(acl->ctx_prefix) + 4;
691 oid->subs[sub] = strlen(acl->group->groupname);
692 for (i = 1; i <= strlen(acl->group->groupname); i++)
693 oid->subs[sub + i] = acl->group->groupname[i - 1];
694 sub += strlen(acl->group->groupname) + 1;
696 oid->subs[sub] = strlen(acl->ctx_prefix);
697 for (i = 1; i <= strlen(acl->ctx_prefix); i++)
698 oid->subs[sub + i] = acl->ctx_prefix[i - 1];
699 sub += strlen(acl->ctx_prefix) + 1;
700 oid->subs[sub++] = acl->sec_model;
701 oid->subs[sub] = acl->sec_level;
705 vacm_access_rule_index_decode(const struct asn_oid *oid, uint sub, char *gname,
706 char *cprefix, int32_t *smodel, int32_t *slevel)
710 if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
713 for (i = 0; i < oid->subs[sub]; i++)
714 gname[i] = oid->subs[sub + i + 1];
716 sub += strlen(gname) + 1;
718 if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
721 for (i = 0; i < oid->subs[sub]; i++)
722 cprefix[i] = oid->subs[sub + i + 1];
724 sub += strlen(cprefix) + 1;
726 *smodel = oid->subs[sub++];
727 *slevel = oid->subs[sub];
733 vacm_get_access_rule(const struct asn_oid *oid, uint sub)
735 int32_t smodel, slevel;
736 char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
737 struct vacm_access *acl;
739 if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
743 for (acl = vacm_first_access_rule(); acl != NULL;
744 acl = vacm_next_access_rule(acl))
745 if (strcmp(gname, acl->group->groupname) == 0 &&
746 strcmp(prefix, acl->ctx_prefix) == 0 &&
747 smodel == acl->sec_model && slevel == acl->sec_level)
754 vacm_get_next_access_rule(const struct asn_oid *oid __unused, uint sub __unused)
756 int32_t smodel, slevel;
757 char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
758 struct vacm_access *acl;
760 if (oid->len - sub == 0)
761 return (vacm_first_access_rule());
763 if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
767 for (acl = vacm_first_access_rule(); acl != NULL;
768 acl = vacm_next_access_rule(acl))
769 if (strcmp(gname, acl->group->groupname) == 0 &&
770 strcmp(prefix, acl->ctx_prefix) == 0 &&
771 smodel == acl->sec_model && slevel == acl->sec_model)
772 return (vacm_next_access_rule(acl));
778 vacm_view_index_decode(const struct asn_oid *oid, uint sub, char *vname,
779 struct asn_oid *view_oid)
784 if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
787 for (i = 0; i < oid->subs[sub]; i++)
788 vname[i] = oid->subs[sub + i + 1];
791 viod_off = sub + oid->subs[sub] + 1;
792 if ((view_oid->len = oid->subs[viod_off]) > ASN_MAXOIDLEN)
795 memcpy(&view_oid->subs[0], &oid->subs[viod_off + 1],
796 view_oid->len * sizeof(view_oid->subs[0]));
802 vacm_append_viewindex(struct asn_oid *oid, uint sub, const struct vacm_view *view)
806 oid->len = sub + strlen(view->viewname) + 1;
807 oid->subs[sub] = strlen(view->viewname);
808 for (i = 1; i <= strlen(view->viewname); i++)
809 oid->subs[sub + i] = view->viewname[i - 1];
811 sub += strlen(view->viewname) + 1;
812 oid->subs[sub] = view->subtree.len;
814 asn_append_oid(oid, &view->subtree);
818 vacm_get_view(const struct asn_oid *oid, uint sub)
820 char vname[SNMP_ADM_STR32_SIZ];
821 struct asn_oid subtree;
822 struct vacm_view *view;
824 if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
827 for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
828 if (strcmp(vname, view->viewname) == 0 &&
829 asn_compare_oid(&subtree, &view->subtree)== 0)
836 vacm_get_next_view(const struct asn_oid *oid, uint sub)
838 char vname[SNMP_ADM_STR32_SIZ];
839 struct asn_oid subtree;
840 struct vacm_view *view;
842 if (oid->len - sub == 0)
843 return (vacm_first_view());
845 if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
848 for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
849 if (strcmp(vname, view->viewname) == 0 &&
850 asn_compare_oid(&subtree, &view->subtree)== 0)
851 return (vacm_next_view(view));
856 static struct vacm_view *
857 vacm_get_view_by_name(u_char *octets, u_int len)
859 struct vacm_view *view;
861 for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
862 if (strlen(view->viewname) == len &&
863 memcmp(octets, view->viewname, len) == 0)
869 static struct vacm_context *
870 vacm_get_context(const struct asn_oid *oid, uint sub)
872 char cname[SNMP_ADM_STR32_SIZ];
875 struct vacm_context *vacm_ctx;
877 if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
881 index_count = SNMP_INDEX(index_count, 1);
882 if (index_decode(oid, sub, index_count, &cname, &cnamelen))
885 for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
886 vacm_ctx = vacm_next_context(vacm_ctx))
887 if (strcmp(cname, vacm_ctx->ctxname) == 0)
893 static struct vacm_context *
894 vacm_get_next_context(const struct asn_oid *oid, uint sub)
896 char cname[SNMP_ADM_STR32_SIZ];
899 struct vacm_context *vacm_ctx;
901 if (oid->len - sub == 0)
902 return (vacm_first_context());
904 if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
908 index_count = SNMP_INDEX(index_count, 1);
909 if (index_decode(oid, sub, index_count, &cname, &cnamelen))
912 for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
913 vacm_ctx = vacm_next_context(vacm_ctx))
914 if (strcmp(cname, vacm_ctx->ctxname) == 0)
915 return (vacm_next_context(vacm_ctx));
921 vacm_append_ctxindex(struct asn_oid *oid, uint sub,
922 const struct vacm_context *ctx)
926 oid->len = sub + strlen(ctx->ctxname) + 1;
927 oid->subs[sub] = strlen(ctx->ctxname);
928 for (i = 1; i <= strlen(ctx->ctxname); i++)
929 oid->subs[sub + i] = ctx->ctxname[i - 1];
933 * VACM snmp module initialization hook.
934 * Returns 0 on success, < 0 on error.
937 vacm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
940 vacm_lock = random();
943 /* XXX: TODO - initialize structures */
948 * VACM snmp module finalization hook.
953 /* XXX: TODO - cleanup */
954 vacm_flush_contexts(reg_vacm);
955 or_unregister(reg_vacm);
961 * VACM snmp module start operation.
966 static char dflt_ctx[] = "";
968 reg_vacm = or_register(&oid_vacm,
969 "The MIB module for managing SNMP View-based Access Control Model.",
972 (void)vacm_add_context(dflt_ctx, reg_vacm);
978 struct vacm_context *vacmctx;
979 struct vacm_user *vuser;
980 struct vacm_access *vacl;
981 struct vacm_view *view;
982 static char oidbuf[ASN_OIDSTRLEN];
984 syslog(LOG_ERR, "\n");
985 syslog(LOG_ERR, "Context list:");
986 for (vacmctx = vacm_first_context(); vacmctx != NULL;
987 vacmctx = vacm_next_context(vacmctx))
988 syslog(LOG_ERR, "Context \"%s\", module id %d",
989 vacmctx->ctxname, vacmctx->regid);
991 syslog(LOG_ERR, "VACM users:");
992 for (vuser = vacm_first_user(); vuser != NULL;
993 vuser = vacm_next_user(vuser))
994 syslog(LOG_ERR, "Uname %s, Group %s, model %d", vuser->secname,
995 vuser->group!= NULL?vuser->group->groupname:"Unknown",
998 syslog(LOG_ERR, "VACM Access rules:");
999 for (vacl = vacm_first_access_rule(); vacl != NULL;
1000 vacl = vacm_next_access_rule(vacl))
1001 syslog(LOG_ERR, "Group %s, CtxPrefix %s, Model %d, Level %d, "
1002 "RV %s, WR %s, NV %s", vacl->group!=NULL?
1003 vacl->group->groupname:"Unknown", vacl->ctx_prefix,
1004 vacl->sec_model, vacl->sec_level, vacl->read_view!=NULL?
1005 vacl->read_view->viewname:"None", vacl->write_view!=NULL?
1006 vacl->write_view->viewname:"None", vacl->notify_view!=NULL?
1007 vacl->notify_view->viewname:"None");
1009 syslog(LOG_ERR, "VACM Views:");
1010 for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
1011 syslog(LOG_ERR, "View %s, Tree %s - %s", view->viewname,
1012 asn_oid2str_r(&view->subtree, oidbuf), view->exclude?
1013 "excluded":"included");
1016 static const char vacm_comment[] = \
1017 "This module implements SNMP View-based Access Control Model defined in RFC 3415.";
1019 extern const struct snmp_module config;
1020 const struct snmp_module config = {
1021 .comment = vacm_comment,
1024 .start = vacm_start,
1027 .tree_size = vacm_CTREE_SIZE,