1216294Ssyrinx/*- 2216294Ssyrinx * Copyright (c) 2010 The FreeBSD Foundation 3216294Ssyrinx * All rights reserved. 4216294Ssyrinx * 5216294Ssyrinx * This software was developed by Shteryana Sotirova Shopova under 6216294Ssyrinx * sponsorship from the FreeBSD Foundation. 7216294Ssyrinx * 8216294Ssyrinx * Redistribution and use in source and binary forms, with or without 9216294Ssyrinx * modification, are permitted provided that the following conditions 10216294Ssyrinx * are met: 11216294Ssyrinx * 1. Redistributions of source code must retain the above copyright 12216294Ssyrinx * notice, this list of conditions and the following disclaimer. 13216294Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 14216294Ssyrinx * notice, this list of conditions and the following disclaimer in the 15216294Ssyrinx * documentation and/or other materials provided with the distribution. 16216294Ssyrinx * 17216294Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18216294Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19216294Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20216294Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21216294Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22216294Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23216294Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24216294Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25216294Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26216294Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27216294Ssyrinx * SUCH DAMAGE. 28216294Ssyrinx * 29216294Ssyrinx * $FreeBSD$ 30216294Ssyrinx */ 31216294Ssyrinx#include <sys/queue.h> 32216294Ssyrinx#include <sys/types.h> 33216294Ssyrinx 34216294Ssyrinx#include <errno.h> 35216294Ssyrinx#include <stdarg.h> 36216294Ssyrinx#include <stdlib.h> 37216294Ssyrinx#include <stdio.h> 38216294Ssyrinx#include <stdint.h> 39216294Ssyrinx#include <string.h> 40216294Ssyrinx#include <syslog.h> 41216294Ssyrinx 42216294Ssyrinx#include "asn1.h" 43216294Ssyrinx#include "snmp.h" 44216294Ssyrinx#include "snmpmod.h" 45216294Ssyrinx 46216294Ssyrinx#include "vacm_tree.h" 47216294Ssyrinx#include "vacm_oid.h" 48216294Ssyrinx 49216294Ssyrinxstatic struct lmodule *vacm_module; 50216294Ssyrinx/* For the registration. */ 51216294Ssyrinxstatic const struct asn_oid oid_vacm = OIDX_snmpVacmMIB; 52216294Ssyrinx 53216294Ssyrinxstatic uint reg_vacm; 54216294Ssyrinx 55216294Ssyrinxstatic int32_t vacm_lock; 56216294Ssyrinx 57216294Ssyrinx/* 58216294Ssyrinx * Internal datastructures and forward declarations. 59216294Ssyrinx */ 60216294Ssyrinxstatic void vacm_append_userindex(struct asn_oid *, 61216294Ssyrinx uint, const struct vacm_user *); 62216294Ssyrinxstatic int vacm_user_index_decode(const struct asn_oid *, 63216294Ssyrinx uint, int32_t *, char *); 64216294Ssyrinxstatic struct vacm_user *vacm_get_user(const struct asn_oid *, 65216294Ssyrinx uint); 66216294Ssyrinxstatic struct vacm_user *vacm_get_next_user(const struct asn_oid *, 67216294Ssyrinx uint); 68216294Ssyrinxstatic void vacm_append_access_rule_index(struct asn_oid *, 69216294Ssyrinx uint, const struct vacm_access *); 70216294Ssyrinxstatic int vacm_access_rule_index_decode(const struct asn_oid *, 71216294Ssyrinx uint, char *, char *, int32_t *, int32_t *); 72216294Ssyrinxstatic struct vacm_access * vacm_get_access_rule(const struct asn_oid *, 73216294Ssyrinx uint); 74216294Ssyrinxstatic struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *, 75216294Ssyrinx uint); 76216294Ssyrinxstatic int vacm_view_index_decode(const struct asn_oid *, uint, 77216294Ssyrinx char *, struct asn_oid *); 78216294Ssyrinxstatic void vacm_append_viewindex(struct asn_oid *, uint, 79216294Ssyrinx const struct vacm_view *); 80216294Ssyrinxstatic struct vacm_view *vacm_get_view(const struct asn_oid *, uint); 81216294Ssyrinxstatic struct vacm_view *vacm_get_next_view(const struct asn_oid *, uint); 82216294Ssyrinxstatic struct vacm_view *vacm_get_view_by_name(u_char *, u_int); 83216294Ssyrinxstatic struct vacm_context *vacm_get_context(const struct asn_oid *, uint); 84216294Ssyrinxstatic struct vacm_context *vacm_get_next_context(const struct asn_oid *, 85216294Ssyrinx uint); 86216294Ssyrinxstatic void vacm_append_ctxindex(struct asn_oid *, uint, 87216294Ssyrinx const struct vacm_context *); 88216294Ssyrinx 89216294Ssyrinxint 90216294Ssyrinxop_vacm_context(struct snmp_context *ctx __unused, struct snmp_value *val, 91216294Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 92216294Ssyrinx{ 93216294Ssyrinx char cname[SNMP_ADM_STR32_SIZ]; 94216294Ssyrinx size_t cnamelen; 95216294Ssyrinx struct vacm_context *vacm_ctx; 96216294Ssyrinx 97216294Ssyrinx if (val->var.subs[sub - 1] != LEAF_vacmContextName) 98216294Ssyrinx abort(); 99216294Ssyrinx 100216294Ssyrinx switch (op) { 101216294Ssyrinx case SNMP_OP_GET: 102216294Ssyrinx if ((vacm_ctx = vacm_get_context(&val->var, sub)) == NULL) 103216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 104216294Ssyrinx break; 105216294Ssyrinx 106216294Ssyrinx case SNMP_OP_GETNEXT: 107216294Ssyrinx if ((vacm_ctx = vacm_get_next_context(&val->var, sub)) == NULL) 108216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 109216294Ssyrinx vacm_append_ctxindex(&val->var, sub, vacm_ctx); 110216294Ssyrinx break; 111216294Ssyrinx 112216294Ssyrinx case SNMP_OP_SET: 113216294Ssyrinx if ((vacm_ctx = vacm_get_context(&val->var, sub)) != NULL) 114216294Ssyrinx return (SNMP_ERR_WRONG_VALUE); 115216294Ssyrinx if (community != COMM_INITIALIZE) 116216294Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 117216294Ssyrinx if (val->var.subs[sub] >= SNMP_ADM_STR32_SIZ) 118216294Ssyrinx return (SNMP_ERR_WRONG_VALUE); 119216294Ssyrinx if (index_decode(&val->var, sub, iidx, &cname, &cnamelen)) 120216294Ssyrinx return (SNMP_ERR_GENERR); 121216294Ssyrinx cname[cnamelen] = '\0'; 122216294Ssyrinx if ((vacm_ctx = vacm_add_context(cname, reg_vacm)) == NULL) 123216294Ssyrinx return (SNMP_ERR_GENERR); 124216294Ssyrinx return (SNMP_ERR_NOERROR); 125216294Ssyrinx 126216294Ssyrinx case SNMP_OP_COMMIT: 127216294Ssyrinx /* FALLTHROUGH*/ 128216294Ssyrinx case SNMP_OP_ROLLBACK: 129216294Ssyrinx return (SNMP_ERR_NOERROR); 130216294Ssyrinx default: 131216294Ssyrinx abort(); 132216294Ssyrinx } 133216294Ssyrinx 134216294Ssyrinx return (string_get(val, vacm_ctx->ctxname, -1)); 135216294Ssyrinx} 136216294Ssyrinx 137216294Ssyrinxint 138216294Ssyrinxop_vacm_security_to_group(struct snmp_context *ctx, struct snmp_value *val, 139216294Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 140216294Ssyrinx{ 141216294Ssyrinx int32_t smodel; 142216294Ssyrinx char uname[SNMP_ADM_STR32_SIZ]; 143216294Ssyrinx struct vacm_user *user; 144216294Ssyrinx 145216294Ssyrinx switch (op) { 146216294Ssyrinx case SNMP_OP_GET: 147216294Ssyrinx if ((user = vacm_get_user(&val->var, sub)) == NULL) 148216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 149216294Ssyrinx break; 150216294Ssyrinx 151216294Ssyrinx case SNMP_OP_GETNEXT: 152216294Ssyrinx if ((user = vacm_get_next_user(&val->var, sub)) == NULL) 153216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 154216294Ssyrinx vacm_append_userindex(&val->var, sub, user); 155216294Ssyrinx break; 156216294Ssyrinx 157216294Ssyrinx case SNMP_OP_SET: 158216294Ssyrinx if ((user = vacm_get_user(&val->var, sub)) == NULL && 159216294Ssyrinx val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus) 160216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 161216294Ssyrinx 162216294Ssyrinx if (user != NULL) { 163216294Ssyrinx if (community != COMM_INITIALIZE && 164216294Ssyrinx user->type == StorageType_readOnly) 165216294Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 166216294Ssyrinx if (user->status == RowStatus_active && 167216294Ssyrinx val->v.integer != RowStatus_destroy) 168216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 169216294Ssyrinx } 170216294Ssyrinx 171216294Ssyrinx switch (val->var.subs[sub - 1]) { 172216294Ssyrinx case LEAF_vacmGroupName: 173216294Ssyrinx ctx->scratch->ptr1 = user->group->groupname; 174216294Ssyrinx ctx->scratch->int1 = strlen(user->group->groupname); 175216294Ssyrinx return (vacm_user_set_group(user, 176216294Ssyrinx val->v.octetstring.octets,val->v.octetstring.len)); 177216294Ssyrinx 178216294Ssyrinx case LEAF_vacmSecurityToGroupStorageType: 179216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 180216294Ssyrinx 181216294Ssyrinx case LEAF_vacmSecurityToGroupStatus: 182216294Ssyrinx if (user == NULL) { 183216294Ssyrinx if (val->v.integer != RowStatus_createAndGo || 184216294Ssyrinx vacm_user_index_decode(&val->var, sub, 185216294Ssyrinx &smodel, uname) < 0) 186216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 187216294Ssyrinx user = vacm_new_user(smodel, uname); 188216294Ssyrinx if (user == NULL) 189216294Ssyrinx return (SNMP_ERR_GENERR); 190216294Ssyrinx user->status = RowStatus_destroy; 191216294Ssyrinx if (community != COMM_INITIALIZE) 192216294Ssyrinx user->type = StorageType_volatile; 193216294Ssyrinx else 194216294Ssyrinx user->type = StorageType_readOnly; 195216294Ssyrinx } else if (val->v.integer != RowStatus_active && 196216294Ssyrinx val->v.integer != RowStatus_destroy) 197216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 198216294Ssyrinx ctx->scratch->int1 = user->status; 199216294Ssyrinx user->status = val->v.integer; 200216294Ssyrinx break; 201216294Ssyrinx } 202216294Ssyrinx return (SNMP_ERR_NOERROR); 203216294Ssyrinx 204216294Ssyrinx case SNMP_OP_COMMIT: 205216294Ssyrinx if (val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus) 206216294Ssyrinx return (SNMP_ERR_NOERROR); 207216294Ssyrinx if ((user = vacm_get_user(&val->var, sub)) == NULL) 208216294Ssyrinx return (SNMP_ERR_GENERR); 209216294Ssyrinx switch (val->v.integer) { 210216294Ssyrinx case RowStatus_destroy: 211216294Ssyrinx return (vacm_delete_user(user)); 212216294Ssyrinx 213216294Ssyrinx case RowStatus_createAndGo: 214216294Ssyrinx user->status = RowStatus_active; 215216294Ssyrinx break; 216216294Ssyrinx 217216294Ssyrinx default: 218216294Ssyrinx break; 219216294Ssyrinx } 220216294Ssyrinx return (SNMP_ERR_NOERROR); 221216294Ssyrinx 222216294Ssyrinx case SNMP_OP_ROLLBACK: 223216294Ssyrinx if ((user = vacm_get_user(&val->var, sub)) == NULL) 224216294Ssyrinx return (SNMP_ERR_GENERR); 225216294Ssyrinx switch (val->var.subs[sub - 1]) { 226216294Ssyrinx case LEAF_vacmGroupName: 227216294Ssyrinx return (vacm_user_set_group(user, ctx->scratch->ptr1, 228216294Ssyrinx ctx->scratch->int1)); 229216294Ssyrinx 230216294Ssyrinx case LEAF_vacmSecurityToGroupStatus: 231216294Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 232216294Ssyrinx return (vacm_delete_user(user)); 233216294Ssyrinx user->status = ctx->scratch->int1; 234216294Ssyrinx break; 235216294Ssyrinx 236216294Ssyrinx default: 237216294Ssyrinx break; 238216294Ssyrinx } 239216294Ssyrinx return (SNMP_ERR_NOERROR); 240216294Ssyrinx 241216294Ssyrinx default: 242216294Ssyrinx abort(); 243216294Ssyrinx } 244216294Ssyrinx 245216294Ssyrinx switch (val->var.subs[sub - 1]) { 246216294Ssyrinx case LEAF_vacmGroupName: 247216294Ssyrinx return (string_get(val, user->group->groupname, -1)); 248216294Ssyrinx case LEAF_vacmSecurityToGroupStorageType: 249216294Ssyrinx val->v.integer = user->type; 250216294Ssyrinx break; 251216294Ssyrinx case LEAF_vacmSecurityToGroupStatus: 252216294Ssyrinx val->v.integer = user->status; 253216294Ssyrinx break; 254216294Ssyrinx default: 255216294Ssyrinx abort(); 256216294Ssyrinx } 257216294Ssyrinx 258216294Ssyrinx return (SNMP_ERR_NOERROR); 259216294Ssyrinx} 260216294Ssyrinx 261216294Ssyrinxint 262216294Ssyrinxop_vacm_access(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub, 263216294Ssyrinx uint32_t iidx __unused, enum snmp_op op) 264216294Ssyrinx{ 265216294Ssyrinx int32_t smodel, slevel; 266216294Ssyrinx char gname[SNMP_ADM_STR32_SIZ], cprefix[SNMP_ADM_STR32_SIZ]; 267216294Ssyrinx struct vacm_access *acl; 268216294Ssyrinx 269216294Ssyrinx switch (op) { 270216294Ssyrinx case SNMP_OP_GET: 271216294Ssyrinx if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) 272216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 273216294Ssyrinx break; 274216294Ssyrinx 275216294Ssyrinx case SNMP_OP_GETNEXT: 276216294Ssyrinx if ((acl = vacm_get_next_access_rule(&val->var, sub)) == NULL) 277216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 278216294Ssyrinx vacm_append_access_rule_index(&val->var, sub, acl); 279216294Ssyrinx break; 280216294Ssyrinx 281216294Ssyrinx case SNMP_OP_SET: 282216294Ssyrinx if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL && 283216294Ssyrinx val->var.subs[sub - 1] != LEAF_vacmAccessStatus) 284216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 285216294Ssyrinx if (acl != NULL && community != COMM_INITIALIZE && 286216294Ssyrinx acl->type == StorageType_readOnly) 287216294Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 288216294Ssyrinx 289216294Ssyrinx switch (val->var.subs[sub - 1]) { 290216294Ssyrinx case LEAF_vacmAccessContextMatch: 291216294Ssyrinx ctx->scratch->int1 = acl->ctx_match; 292216294Ssyrinx if (val->v.integer == vacmAccessContextMatch_exact) 293216294Ssyrinx acl->ctx_match = 1; 294216294Ssyrinx else if (val->v.integer == vacmAccessContextMatch_prefix) 295216294Ssyrinx acl->ctx_match = 0; 296216294Ssyrinx else 297216294Ssyrinx return (SNMP_ERR_WRONG_VALUE); 298216294Ssyrinx break; 299216294Ssyrinx 300216294Ssyrinx case LEAF_vacmAccessReadViewName: 301216294Ssyrinx ctx->scratch->ptr1 = acl->read_view; 302216294Ssyrinx acl->read_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len); 303216294Ssyrinx if (acl->read_view == NULL) { 304216294Ssyrinx acl->read_view = ctx->scratch->ptr1; 305216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 306216294Ssyrinx } 307216294Ssyrinx return (SNMP_ERR_NOERROR); 308216294Ssyrinx 309216294Ssyrinx case LEAF_vacmAccessWriteViewName: 310216294Ssyrinx ctx->scratch->ptr1 = acl->write_view; 311216294Ssyrinx if ((acl->write_view = 312216294Ssyrinx vacm_get_view_by_name(val->v.octetstring.octets, 313216294Ssyrinx val->v.octetstring.len)) == NULL) { 314216294Ssyrinx acl->write_view = ctx->scratch->ptr1; 315216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 316216294Ssyrinx } 317216294Ssyrinx break; 318216294Ssyrinx 319216294Ssyrinx case LEAF_vacmAccessNotifyViewName: 320216294Ssyrinx ctx->scratch->ptr1 = acl->notify_view; 321216294Ssyrinx if ((acl->notify_view = 322216294Ssyrinx vacm_get_view_by_name(val->v.octetstring.octets, 323216294Ssyrinx val->v.octetstring.len)) == NULL) { 324216294Ssyrinx acl->notify_view = ctx->scratch->ptr1; 325216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 326216294Ssyrinx } 327216294Ssyrinx break; 328216294Ssyrinx 329216294Ssyrinx case LEAF_vacmAccessStorageType: 330216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 331216294Ssyrinx 332216294Ssyrinx case LEAF_vacmAccessStatus: 333216294Ssyrinx if (acl == NULL) { 334216294Ssyrinx if (val->v.integer != RowStatus_createAndGo || 335216294Ssyrinx vacm_access_rule_index_decode(&val->var, 336216294Ssyrinx sub, gname, cprefix, &smodel, &slevel) < 0) 337216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 338216294Ssyrinx if ((acl = vacm_new_access_rule(gname, cprefix, 339216294Ssyrinx smodel, slevel)) == NULL) 340216294Ssyrinx return (SNMP_ERR_GENERR); 341216294Ssyrinx acl->status = RowStatus_destroy; 342216294Ssyrinx if (community != COMM_INITIALIZE) 343216294Ssyrinx acl->type = StorageType_volatile; 344216294Ssyrinx else 345216294Ssyrinx acl->type = StorageType_readOnly; 346216294Ssyrinx } else if (val->v.integer != RowStatus_active && 347216294Ssyrinx val->v.integer != RowStatus_destroy) 348216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 349216294Ssyrinx ctx->scratch->int1 = acl->status; 350216294Ssyrinx acl->status = val->v.integer; 351216294Ssyrinx break; 352216294Ssyrinx } 353216294Ssyrinx return (SNMP_ERR_NOERROR); 354216294Ssyrinx 355216294Ssyrinx case SNMP_OP_COMMIT: 356216294Ssyrinx if (val->var.subs[sub - 1] != LEAF_vacmAccessStatus) 357216294Ssyrinx return (SNMP_ERR_NOERROR); 358216294Ssyrinx if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) 359216294Ssyrinx return (SNMP_ERR_GENERR); 360216294Ssyrinx if (val->v.integer == RowStatus_destroy) 361216294Ssyrinx return (vacm_delete_access_rule(acl)); 362216294Ssyrinx else 363216294Ssyrinx acl->status = RowStatus_active; 364216294Ssyrinx return (SNMP_ERR_NOERROR); 365216294Ssyrinx 366216294Ssyrinx case SNMP_OP_ROLLBACK: 367216294Ssyrinx if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL) 368216294Ssyrinx return (SNMP_ERR_GENERR); 369216294Ssyrinx switch (val->var.subs[sub - 1]) { 370216294Ssyrinx case LEAF_vacmAccessContextMatch: 371216294Ssyrinx acl->ctx_match = ctx->scratch->int1; 372216294Ssyrinx break; 373216294Ssyrinx case LEAF_vacmAccessReadViewName: 374216294Ssyrinx acl->read_view = ctx->scratch->ptr1; 375216294Ssyrinx break; 376216294Ssyrinx case LEAF_vacmAccessWriteViewName: 377216294Ssyrinx acl->write_view = ctx->scratch->ptr1; 378216294Ssyrinx break; 379216294Ssyrinx case LEAF_vacmAccessNotifyViewName: 380216294Ssyrinx acl->notify_view = ctx->scratch->ptr1; 381216294Ssyrinx break; 382216294Ssyrinx case LEAF_vacmAccessStatus: 383216294Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 384216294Ssyrinx return (vacm_delete_access_rule(acl)); 385216294Ssyrinx default: 386216294Ssyrinx break; 387216294Ssyrinx } 388216294Ssyrinx return (SNMP_ERR_NOERROR); 389216294Ssyrinx 390216294Ssyrinx default: 391216294Ssyrinx abort(); 392216294Ssyrinx } 393216294Ssyrinx 394216294Ssyrinx switch (val->var.subs[sub - 1]) { 395216294Ssyrinx case LEAF_vacmAccessContextMatch: 396216294Ssyrinx return (string_get(val, acl->ctx_prefix, -1)); 397216294Ssyrinx case LEAF_vacmAccessReadViewName: 398216294Ssyrinx if (acl->read_view != NULL) 399216294Ssyrinx return (string_get(val, acl->read_view->viewname, -1)); 400216294Ssyrinx else 401216294Ssyrinx return (string_get(val, NULL, 0)); 402216294Ssyrinx case LEAF_vacmAccessWriteViewName: 403216294Ssyrinx if (acl->write_view != NULL) 404216294Ssyrinx return (string_get(val, acl->write_view->viewname, -1)); 405216294Ssyrinx else 406216294Ssyrinx return (string_get(val, NULL, 0)); 407216294Ssyrinx case LEAF_vacmAccessNotifyViewName: 408216294Ssyrinx if (acl->notify_view != NULL) 409216294Ssyrinx return (string_get(val, acl->notify_view->viewname, -1)); 410216294Ssyrinx else 411216294Ssyrinx return (string_get(val, NULL, 0)); 412216294Ssyrinx case LEAF_vacmAccessStorageType: 413216294Ssyrinx val->v.integer = acl->type; 414216294Ssyrinx break; 415216294Ssyrinx case LEAF_vacmAccessStatus: 416216294Ssyrinx val->v.integer = acl->status; 417216294Ssyrinx break; 418216294Ssyrinx default: 419216294Ssyrinx abort(); 420216294Ssyrinx } 421216294Ssyrinx 422216294Ssyrinx return (SNMP_ERR_NOERROR); 423216294Ssyrinx} 424216294Ssyrinx 425216294Ssyrinxint 426216294Ssyrinxop_vacm_view_lock(struct snmp_context *ctx __unused, struct snmp_value *val, 427216294Ssyrinx uint32_t sub, uint32_t iidx __unused, enum snmp_op op) 428216294Ssyrinx{ 429216294Ssyrinx if (val->var.subs[sub - 1] != LEAF_vacmViewSpinLock) 430216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 431216294Ssyrinx 432216294Ssyrinx switch (op) { 433216294Ssyrinx case SNMP_OP_GET: 434216294Ssyrinx if (++vacm_lock == INT32_MAX) 435216294Ssyrinx vacm_lock = 0; 436216294Ssyrinx val->v.integer = vacm_lock; 437216294Ssyrinx break; 438216294Ssyrinx 439216294Ssyrinx case SNMP_OP_GETNEXT: 440216294Ssyrinx abort(); 441216294Ssyrinx 442216294Ssyrinx case SNMP_OP_SET: 443216294Ssyrinx if (val->v.integer != vacm_lock) 444216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 445216294Ssyrinx break; 446216294Ssyrinx 447216294Ssyrinx case SNMP_OP_ROLLBACK: 448216294Ssyrinx /* FALLTHROUGH */ 449216294Ssyrinx case SNMP_OP_COMMIT: 450216294Ssyrinx break; 451216294Ssyrinx } 452216294Ssyrinx 453216294Ssyrinx return (SNMP_ERR_NOERROR); 454216294Ssyrinx} 455216294Ssyrinx 456216294Ssyrinxint 457216294Ssyrinxop_vacm_view(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub, 458216294Ssyrinx uint32_t iidx __unused, enum snmp_op op) 459216294Ssyrinx{ 460216294Ssyrinx char vname[SNMP_ADM_STR32_SIZ]; 461216294Ssyrinx struct asn_oid oid; 462216294Ssyrinx struct vacm_view *view; 463216294Ssyrinx 464216294Ssyrinx switch (op) { 465216294Ssyrinx case SNMP_OP_GET: 466216294Ssyrinx if ((view = vacm_get_view(&val->var, sub)) == NULL) 467216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 468216294Ssyrinx break; 469216294Ssyrinx 470216294Ssyrinx case SNMP_OP_GETNEXT: 471216294Ssyrinx if ((view = vacm_get_next_view(&val->var, sub)) == NULL) 472216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 473216294Ssyrinx vacm_append_viewindex(&val->var, sub, view); 474216294Ssyrinx break; 475216294Ssyrinx 476216294Ssyrinx case SNMP_OP_SET: 477216294Ssyrinx if ((view = vacm_get_view(&val->var, sub)) == NULL && 478216294Ssyrinx val->var.subs[sub - 1] != LEAF_vacmViewTreeFamilyStatus) 479216294Ssyrinx return (SNMP_ERR_NOSUCHNAME); 480216294Ssyrinx 481216294Ssyrinx if (view != NULL) { 482216294Ssyrinx if (community != COMM_INITIALIZE && 483216294Ssyrinx view->type == StorageType_readOnly) 484216294Ssyrinx return (SNMP_ERR_NOT_WRITEABLE); 485216294Ssyrinx if (view->status == RowStatus_active && 486216294Ssyrinx val->v.integer != RowStatus_destroy) 487216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 488216294Ssyrinx } 489216294Ssyrinx 490216294Ssyrinx switch (val->var.subs[sub - 1]) { 491216294Ssyrinx case LEAF_vacmViewTreeFamilyMask: 492216294Ssyrinx if (val->v.octetstring.len > sizeof(view->mask)) 493216294Ssyrinx ctx->scratch->ptr1 = malloc(sizeof(view->mask)); 494216294Ssyrinx if (ctx->scratch->ptr1 == NULL) 495216294Ssyrinx return (SNMP_ERR_GENERR); 496216294Ssyrinx memset(ctx->scratch->ptr1, 0, sizeof(view->mask)); 497216294Ssyrinx memcpy(ctx->scratch->ptr1, view->mask, 498216294Ssyrinx sizeof(view->mask)); 499216294Ssyrinx memset(view->mask, 0, sizeof(view->mask)); 500216294Ssyrinx memcpy(view->mask, val->v.octetstring.octets, 501216294Ssyrinx val->v.octetstring.len); 502216294Ssyrinx break; 503216294Ssyrinx 504216294Ssyrinx case LEAF_vacmViewTreeFamilyType: 505216294Ssyrinx ctx->scratch->int1 = view->exclude; 506216294Ssyrinx if (val->v.integer == vacmViewTreeFamilyType_included) 507216294Ssyrinx view->exclude = 0; 508216294Ssyrinx else if (val->v.integer == vacmViewTreeFamilyType_excluded) 509216294Ssyrinx view->exclude = 1; 510216294Ssyrinx else 511216294Ssyrinx return (SNMP_ERR_WRONG_VALUE); 512216294Ssyrinx break; 513216294Ssyrinx 514216294Ssyrinx case LEAF_vacmViewTreeFamilyStorageType: 515216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 516216294Ssyrinx 517216294Ssyrinx case LEAF_vacmViewTreeFamilyStatus: 518216294Ssyrinx if (view == NULL) { 519216294Ssyrinx if (val->v.integer != RowStatus_createAndGo || 520216294Ssyrinx vacm_view_index_decode(&val->var, sub, vname, 521216294Ssyrinx &oid) < 0) 522216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 523216294Ssyrinx if ((view = vacm_new_view(vname, &oid)) == NULL) 524216294Ssyrinx return (SNMP_ERR_GENERR); 525216294Ssyrinx view->status = RowStatus_destroy; 526216294Ssyrinx if (community != COMM_INITIALIZE) 527216294Ssyrinx view->type = StorageType_volatile; 528216294Ssyrinx else 529216294Ssyrinx view->type = StorageType_readOnly; 530216294Ssyrinx } else if (val->v.integer != RowStatus_active && 531216294Ssyrinx val->v.integer != RowStatus_destroy) 532216294Ssyrinx return (SNMP_ERR_INCONS_VALUE); 533216294Ssyrinx ctx->scratch->int1 = view->status; 534216294Ssyrinx view->status = val->v.integer; 535216294Ssyrinx break; 536216294Ssyrinx } 537216294Ssyrinx return (SNMP_ERR_NOERROR); 538216294Ssyrinx 539216294Ssyrinx case SNMP_OP_COMMIT: 540216294Ssyrinx switch (val->var.subs[sub - 1]) { 541216294Ssyrinx case LEAF_vacmViewTreeFamilyMask: 542216294Ssyrinx free(ctx->scratch->ptr1); 543216294Ssyrinx break; 544216294Ssyrinx case LEAF_vacmViewTreeFamilyStatus: 545216294Ssyrinx if ((view = vacm_get_view(&val->var, sub)) == NULL) 546216294Ssyrinx return (SNMP_ERR_GENERR); 547216294Ssyrinx switch (val->v.integer) { 548216294Ssyrinx case RowStatus_destroy: 549216294Ssyrinx return (vacm_delete_view(view)); 550216294Ssyrinx 551216294Ssyrinx case RowStatus_createAndGo: 552216294Ssyrinx view->status = RowStatus_active; 553216294Ssyrinx break; 554216294Ssyrinx 555216294Ssyrinx default: 556216294Ssyrinx /* NOTREACHED*/ 557216294Ssyrinx return (SNMP_ERR_GENERR); 558216294Ssyrinx } 559216294Ssyrinx default: 560216294Ssyrinx break; 561216294Ssyrinx } 562216294Ssyrinx return (SNMP_ERR_NOERROR); 563216294Ssyrinx 564216294Ssyrinx case SNMP_OP_ROLLBACK: 565216294Ssyrinx if ((view = vacm_get_view(&val->var, sub)) == NULL) 566216294Ssyrinx return (SNMP_ERR_GENERR); 567216294Ssyrinx switch (val->var.subs[sub - 1]) { 568216294Ssyrinx case LEAF_vacmViewTreeFamilyMask: 569216294Ssyrinx memcpy(view->mask, ctx->scratch->ptr1, 570216294Ssyrinx sizeof(view->mask)); 571216294Ssyrinx free(ctx->scratch->ptr1); 572216294Ssyrinx break; 573216294Ssyrinx case LEAF_vacmViewTreeFamilyType: 574216294Ssyrinx view->exclude = ctx->scratch->int1; 575216294Ssyrinx break; 576216294Ssyrinx case LEAF_vacmViewTreeFamilyStatus: 577216294Ssyrinx if (ctx->scratch->int1 == RowStatus_destroy) 578216294Ssyrinx return (vacm_delete_view(view)); 579216294Ssyrinx break; 580216294Ssyrinx default: 581216294Ssyrinx break; 582216294Ssyrinx } 583216294Ssyrinx return (SNMP_ERR_NOERROR); 584216294Ssyrinx 585216294Ssyrinx default: 586216294Ssyrinx abort(); 587216294Ssyrinx } 588216294Ssyrinx 589216294Ssyrinx switch (val->var.subs[sub - 1]) { 590216294Ssyrinx case LEAF_vacmViewTreeFamilyMask: 591216294Ssyrinx return (string_get(val, view->mask, sizeof(view->mask))); 592216294Ssyrinx case LEAF_vacmViewTreeFamilyType: 593216294Ssyrinx if (view->exclude) 594216294Ssyrinx val->v.integer = vacmViewTreeFamilyType_excluded; 595216294Ssyrinx else 596216294Ssyrinx val->v.integer = vacmViewTreeFamilyType_included; 597216294Ssyrinx break; 598216294Ssyrinx case LEAF_vacmViewTreeFamilyStorageType: 599216294Ssyrinx val->v.integer = view->type; 600216294Ssyrinx break; 601216294Ssyrinx case LEAF_vacmViewTreeFamilyStatus: 602216294Ssyrinx val->v.integer = view->status; 603216294Ssyrinx break; 604216294Ssyrinx default: 605216294Ssyrinx abort(); 606216294Ssyrinx } 607216294Ssyrinx 608216294Ssyrinx return (SNMP_ERR_NOERROR); 609216294Ssyrinx} 610216294Ssyrinx 611216294Ssyrinxstatic void 612216294Ssyrinxvacm_append_userindex(struct asn_oid *oid, uint sub, 613216294Ssyrinx const struct vacm_user *user) 614216294Ssyrinx{ 615216294Ssyrinx uint32_t i; 616216294Ssyrinx 617216294Ssyrinx oid->len = sub + strlen(user->secname) + 2; 618216294Ssyrinx oid->subs[sub++] = user->sec_model; 619216294Ssyrinx oid->subs[sub] = strlen(user->secname); 620216294Ssyrinx for (i = 1; i <= strlen(user->secname); i++) 621216294Ssyrinx oid->subs[sub + i] = user->secname[i - 1]; 622216294Ssyrinx} 623216294Ssyrinx 624216294Ssyrinxstatic int 625216294Ssyrinxvacm_user_index_decode(const struct asn_oid *oid, uint sub, 626216294Ssyrinx int32_t *smodel, char *uname) 627216294Ssyrinx{ 628216294Ssyrinx uint32_t i; 629216294Ssyrinx 630216294Ssyrinx *smodel = oid->subs[sub++]; 631216294Ssyrinx 632216294Ssyrinx if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) 633216294Ssyrinx return (-1); 634216294Ssyrinx 635216294Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 636216294Ssyrinx uname[i] = oid->subs[sub + i + 1]; 637216294Ssyrinx uname[i] = '\0'; 638216294Ssyrinx 639216294Ssyrinx return (0); 640216294Ssyrinx} 641216294Ssyrinx 642216294Ssyrinxstatic struct vacm_user * 643216294Ssyrinxvacm_get_user(const struct asn_oid *oid, uint sub) 644216294Ssyrinx{ 645216294Ssyrinx int32_t smodel; 646216294Ssyrinx char uname[SNMP_ADM_STR32_SIZ]; 647216294Ssyrinx struct vacm_user *user; 648216294Ssyrinx 649216294Ssyrinx if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0) 650216294Ssyrinx return (NULL); 651216294Ssyrinx 652216294Ssyrinx for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user)) 653216294Ssyrinx if (strcmp(uname, user->secname) == 0 && 654216294Ssyrinx user->sec_model == smodel) 655216294Ssyrinx return (user); 656216294Ssyrinx 657216294Ssyrinx return (NULL); 658216294Ssyrinx} 659216294Ssyrinx 660216294Ssyrinxstatic struct vacm_user * 661216294Ssyrinxvacm_get_next_user(const struct asn_oid *oid, uint sub) 662216294Ssyrinx{ 663216294Ssyrinx int32_t smodel; 664216294Ssyrinx char uname[SNMP_ADM_STR32_SIZ]; 665216294Ssyrinx struct vacm_user *user; 666216294Ssyrinx 667216294Ssyrinx if (oid->len - sub == 0) 668216294Ssyrinx return (vacm_first_user()); 669216294Ssyrinx 670216294Ssyrinx if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0) 671216294Ssyrinx return (NULL); 672216294Ssyrinx 673216294Ssyrinx for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user)) 674216294Ssyrinx if (strcmp(uname, user->secname) == 0 && 675216294Ssyrinx user->sec_model == smodel) 676216294Ssyrinx return (vacm_next_user(user)); 677216294Ssyrinx 678216294Ssyrinx return (NULL); 679216294Ssyrinx} 680216294Ssyrinx 681216294Ssyrinxstatic void 682216294Ssyrinxvacm_append_access_rule_index(struct asn_oid *oid, uint sub, 683216294Ssyrinx const struct vacm_access *acl) 684216294Ssyrinx{ 685216294Ssyrinx uint32_t i; 686216294Ssyrinx 687216294Ssyrinx oid->len = sub + strlen(acl->group->groupname) + 688216294Ssyrinx strlen(acl->ctx_prefix) + 4; 689216294Ssyrinx 690216294Ssyrinx oid->subs[sub] = strlen(acl->group->groupname); 691216294Ssyrinx for (i = 1; i <= strlen(acl->group->groupname); i++) 692216294Ssyrinx oid->subs[sub + i] = acl->group->groupname[i - 1]; 693216294Ssyrinx sub += strlen(acl->group->groupname) + 1; 694216294Ssyrinx 695216294Ssyrinx oid->subs[sub] = strlen(acl->ctx_prefix); 696216294Ssyrinx for (i = 1; i <= strlen(acl->ctx_prefix); i++) 697216294Ssyrinx oid->subs[sub + i] = acl->ctx_prefix[i - 1]; 698216294Ssyrinx sub += strlen(acl->ctx_prefix) + 1; 699216294Ssyrinx oid->subs[sub++] = acl->sec_model; 700216294Ssyrinx oid->subs[sub] = acl->sec_level; 701216294Ssyrinx} 702216294Ssyrinx 703216294Ssyrinxstatic int 704216294Ssyrinxvacm_access_rule_index_decode(const struct asn_oid *oid, uint sub, char *gname, 705216294Ssyrinx char *cprefix, int32_t *smodel, int32_t *slevel) 706216294Ssyrinx{ 707216294Ssyrinx uint32_t i; 708216294Ssyrinx 709216294Ssyrinx if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) 710216294Ssyrinx return (-1); 711216294Ssyrinx 712216294Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 713216294Ssyrinx gname[i] = oid->subs[sub + i + 1]; 714216294Ssyrinx gname[i] = '\0'; 715216294Ssyrinx sub += strlen(gname) + 1; 716216294Ssyrinx 717216294Ssyrinx if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) 718216294Ssyrinx return (-1); 719216294Ssyrinx 720216294Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 721216294Ssyrinx cprefix[i] = oid->subs[sub + i + 1]; 722216294Ssyrinx cprefix[i] = '\0'; 723216294Ssyrinx sub += strlen(cprefix) + 1; 724216294Ssyrinx 725216294Ssyrinx *smodel = oid->subs[sub++]; 726216294Ssyrinx *slevel = oid->subs[sub]; 727216294Ssyrinx 728216294Ssyrinx return (0); 729216294Ssyrinx} 730216294Ssyrinx 731216294Ssyrinxstruct vacm_access * 732216294Ssyrinxvacm_get_access_rule(const struct asn_oid *oid, uint sub) 733216294Ssyrinx{ 734216294Ssyrinx int32_t smodel, slevel; 735216294Ssyrinx char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ]; 736216294Ssyrinx struct vacm_access *acl; 737216294Ssyrinx 738216294Ssyrinx if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel, 739216294Ssyrinx &slevel) < 0) 740216294Ssyrinx return (NULL); 741216294Ssyrinx 742216294Ssyrinx for (acl = vacm_first_access_rule(); acl != NULL; 743216294Ssyrinx acl = vacm_next_access_rule(acl)) 744216294Ssyrinx if (strcmp(gname, acl->group->groupname) == 0 && 745216294Ssyrinx strcmp(prefix, acl->ctx_prefix) == 0 && 746216294Ssyrinx smodel == acl->sec_model && slevel == acl->sec_level) 747216294Ssyrinx return (acl); 748216294Ssyrinx 749216294Ssyrinx return (NULL); 750216294Ssyrinx} 751216294Ssyrinx 752216294Ssyrinxstruct vacm_access * 753216294Ssyrinxvacm_get_next_access_rule(const struct asn_oid *oid __unused, uint sub __unused) 754216294Ssyrinx{ 755216294Ssyrinx int32_t smodel, slevel; 756216294Ssyrinx char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ]; 757216294Ssyrinx struct vacm_access *acl; 758216294Ssyrinx 759216294Ssyrinx if (oid->len - sub == 0) 760216294Ssyrinx return (vacm_first_access_rule()); 761216294Ssyrinx 762216294Ssyrinx if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel, 763216294Ssyrinx &slevel) < 0) 764216294Ssyrinx return (NULL); 765216294Ssyrinx 766216294Ssyrinx for (acl = vacm_first_access_rule(); acl != NULL; 767216294Ssyrinx acl = vacm_next_access_rule(acl)) 768216294Ssyrinx if (strcmp(gname, acl->group->groupname) == 0 && 769216294Ssyrinx strcmp(prefix, acl->ctx_prefix) == 0 && 770216294Ssyrinx smodel == acl->sec_model && slevel == acl->sec_model) 771216294Ssyrinx return (vacm_next_access_rule(acl)); 772216294Ssyrinx 773216294Ssyrinx return (NULL); 774216294Ssyrinx} 775216294Ssyrinx 776216294Ssyrinxstatic int 777216294Ssyrinxvacm_view_index_decode(const struct asn_oid *oid, uint sub, char *vname, 778216294Ssyrinx struct asn_oid *view_oid) 779216294Ssyrinx{ 780216294Ssyrinx uint32_t i; 781216294Ssyrinx int viod_off; 782216294Ssyrinx 783216294Ssyrinx if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) 784216294Ssyrinx return (-1); 785216294Ssyrinx 786216294Ssyrinx for (i = 0; i < oid->subs[sub]; i++) 787216294Ssyrinx vname[i] = oid->subs[sub + i + 1]; 788216294Ssyrinx vname[i] = '\0'; 789216294Ssyrinx 790216294Ssyrinx viod_off = sub + oid->subs[sub] + 1; 791216294Ssyrinx if ((view_oid->len = oid->subs[viod_off]) > ASN_MAXOIDLEN) 792216294Ssyrinx return (-1); 793216294Ssyrinx 794216294Ssyrinx memcpy(&view_oid->subs[0], &oid->subs[viod_off + 1], 795216294Ssyrinx view_oid->len * sizeof(view_oid->subs[0])); 796216294Ssyrinx 797216294Ssyrinx return (0); 798216294Ssyrinx} 799216294Ssyrinx 800216294Ssyrinxstatic void 801216294Ssyrinxvacm_append_viewindex(struct asn_oid *oid, uint sub, const struct vacm_view *view) 802216294Ssyrinx{ 803216294Ssyrinx uint32_t i; 804216294Ssyrinx 805216294Ssyrinx oid->len = sub + strlen(view->viewname) + 1; 806216294Ssyrinx oid->subs[sub] = strlen(view->viewname); 807216294Ssyrinx for (i = 1; i <= strlen(view->viewname); i++) 808216294Ssyrinx oid->subs[sub + i] = view->viewname[i - 1]; 809216294Ssyrinx 810216294Ssyrinx sub += strlen(view->viewname) + 1; 811216294Ssyrinx oid->subs[sub] = view->subtree.len; 812216294Ssyrinx oid->len++; 813216294Ssyrinx asn_append_oid(oid, &view->subtree); 814216294Ssyrinx} 815216294Ssyrinx 816216294Ssyrinxstruct vacm_view * 817216294Ssyrinxvacm_get_view(const struct asn_oid *oid, uint sub) 818216294Ssyrinx{ 819216294Ssyrinx char vname[SNMP_ADM_STR32_SIZ]; 820216294Ssyrinx struct asn_oid subtree; 821216294Ssyrinx struct vacm_view *view; 822216294Ssyrinx 823216294Ssyrinx if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0) 824216294Ssyrinx return (NULL); 825216294Ssyrinx 826216294Ssyrinx for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) 827216294Ssyrinx if (strcmp(vname, view->viewname) == 0 && 828216294Ssyrinx asn_compare_oid(&subtree, &view->subtree)== 0) 829216294Ssyrinx return (view); 830216294Ssyrinx 831216294Ssyrinx return (NULL); 832216294Ssyrinx} 833216294Ssyrinx 834216294Ssyrinxstruct vacm_view * 835216294Ssyrinxvacm_get_next_view(const struct asn_oid *oid, uint sub) 836216294Ssyrinx{ 837216294Ssyrinx char vname[SNMP_ADM_STR32_SIZ]; 838216294Ssyrinx struct asn_oid subtree; 839216294Ssyrinx struct vacm_view *view; 840216294Ssyrinx 841216294Ssyrinx if (oid->len - sub == 0) 842216294Ssyrinx return (vacm_first_view()); 843216294Ssyrinx 844216294Ssyrinx if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0) 845216294Ssyrinx return (NULL); 846216294Ssyrinx 847216294Ssyrinx for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) 848216294Ssyrinx if (strcmp(vname, view->viewname) == 0 && 849216294Ssyrinx asn_compare_oid(&subtree, &view->subtree)== 0) 850216294Ssyrinx return (vacm_next_view(view)); 851216294Ssyrinx 852216294Ssyrinx return (NULL); 853216294Ssyrinx} 854216294Ssyrinx 855216294Ssyrinxstatic struct vacm_view * 856216294Ssyrinxvacm_get_view_by_name(u_char *octets, u_int len) 857216294Ssyrinx{ 858216294Ssyrinx struct vacm_view *view; 859216294Ssyrinx 860216294Ssyrinx for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) 861216294Ssyrinx if (strlen(view->viewname) == len && 862216294Ssyrinx memcmp(octets, view->viewname, len) == 0) 863216294Ssyrinx return (view); 864216294Ssyrinx 865216294Ssyrinx return (NULL); 866216294Ssyrinx} 867216294Ssyrinx 868216294Ssyrinxstatic struct vacm_context * 869216294Ssyrinxvacm_get_context(const struct asn_oid *oid, uint sub) 870216294Ssyrinx{ 871216294Ssyrinx char cname[SNMP_ADM_STR32_SIZ]; 872216294Ssyrinx size_t cnamelen; 873216294Ssyrinx u_int index_count; 874216294Ssyrinx struct vacm_context *vacm_ctx; 875216294Ssyrinx 876216294Ssyrinx if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) 877216294Ssyrinx return (NULL); 878216294Ssyrinx 879216294Ssyrinx index_count = 0; 880216294Ssyrinx index_count = SNMP_INDEX(index_count, 1); 881216294Ssyrinx if (index_decode(oid, sub, index_count, &cname, &cnamelen)) 882216294Ssyrinx return (NULL); 883216294Ssyrinx 884216294Ssyrinx for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL; 885216294Ssyrinx vacm_ctx = vacm_next_context(vacm_ctx)) 886216294Ssyrinx if (strcmp(cname, vacm_ctx->ctxname) == 0) 887216294Ssyrinx return (vacm_ctx); 888216294Ssyrinx 889216294Ssyrinx return (NULL); 890216294Ssyrinx} 891216294Ssyrinx 892216294Ssyrinxstatic struct vacm_context * 893216294Ssyrinxvacm_get_next_context(const struct asn_oid *oid, uint sub) 894216294Ssyrinx{ 895216294Ssyrinx char cname[SNMP_ADM_STR32_SIZ]; 896216294Ssyrinx size_t cnamelen; 897216294Ssyrinx u_int index_count; 898216294Ssyrinx struct vacm_context *vacm_ctx; 899216294Ssyrinx 900216294Ssyrinx if (oid->len - sub == 0) 901216294Ssyrinx return (vacm_first_context()); 902216294Ssyrinx 903216294Ssyrinx if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ) 904216294Ssyrinx return (NULL); 905216294Ssyrinx 906216294Ssyrinx index_count = 0; 907216294Ssyrinx index_count = SNMP_INDEX(index_count, 1); 908216294Ssyrinx if (index_decode(oid, sub, index_count, &cname, &cnamelen)) 909216294Ssyrinx return (NULL); 910216294Ssyrinx 911216294Ssyrinx for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL; 912216294Ssyrinx vacm_ctx = vacm_next_context(vacm_ctx)) 913216294Ssyrinx if (strcmp(cname, vacm_ctx->ctxname) == 0) 914216294Ssyrinx return (vacm_next_context(vacm_ctx)); 915216294Ssyrinx 916216294Ssyrinx return (NULL); 917216294Ssyrinx} 918216294Ssyrinx 919216294Ssyrinxstatic void 920216294Ssyrinxvacm_append_ctxindex(struct asn_oid *oid, uint sub, 921216294Ssyrinx const struct vacm_context *ctx) 922216294Ssyrinx{ 923216294Ssyrinx uint32_t i; 924216294Ssyrinx 925216294Ssyrinx oid->len = sub + strlen(ctx->ctxname) + 1; 926216294Ssyrinx oid->subs[sub] = strlen(ctx->ctxname); 927216294Ssyrinx for (i = 1; i <= strlen(ctx->ctxname); i++) 928216294Ssyrinx oid->subs[sub + i] = ctx->ctxname[i - 1]; 929216294Ssyrinx} 930216294Ssyrinx 931216294Ssyrinx/* 932216294Ssyrinx * VACM snmp module initialization hook. 933216294Ssyrinx * Returns 0 on success, < 0 on error. 934216294Ssyrinx */ 935216294Ssyrinxstatic int 936216294Ssyrinxvacm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused) 937216294Ssyrinx{ 938216294Ssyrinx vacm_module = mod; 939216294Ssyrinx vacm_lock = random(); 940216294Ssyrinx vacm_groups_init(); 941216294Ssyrinx 942216294Ssyrinx /* XXX: TODO - initialize structures */ 943216294Ssyrinx return (0); 944216294Ssyrinx} 945216294Ssyrinx 946216294Ssyrinx/* 947216294Ssyrinx * VACM snmp module finalization hook. 948216294Ssyrinx */ 949216294Ssyrinxstatic int 950216294Ssyrinxvacm_fini(void) 951216294Ssyrinx{ 952216294Ssyrinx /* XXX: TODO - cleanup */ 953216294Ssyrinx vacm_flush_contexts(reg_vacm); 954216294Ssyrinx or_unregister(reg_vacm); 955216294Ssyrinx 956216294Ssyrinx return (0); 957216294Ssyrinx} 958216294Ssyrinx 959216294Ssyrinx/* 960216294Ssyrinx * VACM snmp module start operation. 961216294Ssyrinx */ 962216294Ssyrinxstatic void 963216294Ssyrinxvacm_start(void) 964216294Ssyrinx{ 965216294Ssyrinx static char dflt_ctx[] = ""; 966216294Ssyrinx 967216294Ssyrinx reg_vacm = or_register(&oid_vacm, 968216294Ssyrinx "The MIB module for managing SNMP View-based Access Control Model.", 969216294Ssyrinx vacm_module); 970216294Ssyrinx 971216294Ssyrinx (void)vacm_add_context(dflt_ctx, reg_vacm); 972216294Ssyrinx} 973216294Ssyrinx 974216294Ssyrinxstatic void 975216294Ssyrinxvacm_dump(void) 976216294Ssyrinx{ 977216294Ssyrinx struct vacm_context *vacmctx; 978216294Ssyrinx struct vacm_user *vuser; 979216294Ssyrinx struct vacm_access *vacl; 980216294Ssyrinx struct vacm_view *view; 981216294Ssyrinx static char oidbuf[ASN_OIDSTRLEN]; 982216294Ssyrinx 983216294Ssyrinx syslog(LOG_ERR, "\n"); 984216294Ssyrinx syslog(LOG_ERR, "Context list:"); 985216294Ssyrinx for (vacmctx = vacm_first_context(); vacmctx != NULL; 986216294Ssyrinx vacmctx = vacm_next_context(vacmctx)) 987216294Ssyrinx syslog(LOG_ERR, "Context \"%s\", module id %d", 988216294Ssyrinx vacmctx->ctxname, vacmctx->regid); 989216294Ssyrinx 990216294Ssyrinx syslog(LOG_ERR, "VACM users:"); 991216294Ssyrinx for (vuser = vacm_first_user(); vuser != NULL; 992216294Ssyrinx vuser = vacm_next_user(vuser)) 993216294Ssyrinx syslog(LOG_ERR, "Uname %s, Group %s, model %d", vuser->secname, 994216294Ssyrinx vuser->group!= NULL?vuser->group->groupname:"Unknown", 995216294Ssyrinx vuser->sec_model); 996216294Ssyrinx 997216294Ssyrinx syslog(LOG_ERR, "VACM Access rules:"); 998216294Ssyrinx for (vacl = vacm_first_access_rule(); vacl != NULL; 999216294Ssyrinx vacl = vacm_next_access_rule(vacl)) 1000216294Ssyrinx syslog(LOG_ERR, "Group %s, CtxPrefix %s, Model %d, Level %d, " 1001216294Ssyrinx "RV %s, WR %s, NV %s", vacl->group!=NULL? 1002216294Ssyrinx vacl->group->groupname:"Unknown", vacl->ctx_prefix, 1003216294Ssyrinx vacl->sec_model, vacl->sec_level, vacl->read_view!=NULL? 1004216294Ssyrinx vacl->read_view->viewname:"None", vacl->write_view!=NULL? 1005216294Ssyrinx vacl->write_view->viewname:"None", vacl->notify_view!=NULL? 1006216294Ssyrinx vacl->notify_view->viewname:"None"); 1007216294Ssyrinx 1008216294Ssyrinx syslog(LOG_ERR, "VACM Views:"); 1009216294Ssyrinx for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view)) 1010216294Ssyrinx syslog(LOG_ERR, "View %s, Tree %s - %s", view->viewname, 1011216294Ssyrinx asn_oid2str_r(&view->subtree, oidbuf), view->exclude? 1012216294Ssyrinx "excluded":"included"); 1013216294Ssyrinx} 1014216294Ssyrinx 1015216294Ssyrinxconst char vacm_comment[] = \ 1016216294Ssyrinx"This module implements SNMP View-based Access Control Model defined in RFC 3415."; 1017216294Ssyrinx 1018216294Ssyrinxconst struct snmp_module config = { 1019216294Ssyrinx .comment = vacm_comment, 1020216294Ssyrinx .init = vacm_init, 1021216294Ssyrinx .fini = vacm_fini, 1022216294Ssyrinx .start = vacm_start, 1023216294Ssyrinx .tree = vacm_ctree, 1024216294Ssyrinx .dump = vacm_dump, 1025216294Ssyrinx .tree_size = vacm_CTREE_SIZE, 1026216294Ssyrinx}; 1027