/contrib/bsnmp/snmp_vacm/vacm_snmp.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1026 lines · 825 code · 152 blank · 49 comment · 252 complexity · 0ad31082f915f1767a92a63044ac544a MD5 · raw file

  1. /*-
  2. * Copyright (c) 2010 The FreeBSD Foundation
  3. * All rights reserved.
  4. *
  5. * This software was developed by Shteryana Sotirova Shopova under
  6. * sponsorship from the FreeBSD Foundation.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  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.
  16. *
  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
  27. * SUCH DAMAGE.
  28. *
  29. * $FreeBSD$
  30. */
  31. #include <sys/queue.h>
  32. #include <sys/types.h>
  33. #include <errno.h>
  34. #include <stdarg.h>
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <stdint.h>
  38. #include <string.h>
  39. #include <syslog.h>
  40. #include "asn1.h"
  41. #include "snmp.h"
  42. #include "snmpmod.h"
  43. #include "vacm_tree.h"
  44. #include "vacm_oid.h"
  45. static struct lmodule *vacm_module;
  46. /* For the registration. */
  47. static const struct asn_oid oid_vacm = OIDX_snmpVacmMIB;
  48. static uint reg_vacm;
  49. static int32_t vacm_lock;
  50. /*
  51. * Internal datastructures and forward declarations.
  52. */
  53. static void vacm_append_userindex(struct asn_oid *,
  54. uint, const struct vacm_user *);
  55. static int vacm_user_index_decode(const struct asn_oid *,
  56. uint, int32_t *, char *);
  57. static struct vacm_user *vacm_get_user(const struct asn_oid *,
  58. uint);
  59. static struct vacm_user *vacm_get_next_user(const struct asn_oid *,
  60. uint);
  61. static void vacm_append_access_rule_index(struct asn_oid *,
  62. uint, const struct vacm_access *);
  63. static int vacm_access_rule_index_decode(const struct asn_oid *,
  64. uint, char *, char *, int32_t *, int32_t *);
  65. static struct vacm_access * vacm_get_access_rule(const struct asn_oid *,
  66. uint);
  67. static struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *,
  68. uint);
  69. static int vacm_view_index_decode(const struct asn_oid *, uint,
  70. char *, struct asn_oid *);
  71. static void vacm_append_viewindex(struct asn_oid *, uint,
  72. const struct vacm_view *);
  73. static struct vacm_view *vacm_get_view(const struct asn_oid *, uint);
  74. static struct vacm_view *vacm_get_next_view(const struct asn_oid *, uint);
  75. static struct vacm_view *vacm_get_view_by_name(u_char *, u_int);
  76. static struct vacm_context *vacm_get_context(const struct asn_oid *, uint);
  77. static struct vacm_context *vacm_get_next_context(const struct asn_oid *,
  78. uint);
  79. static void vacm_append_ctxindex(struct asn_oid *, uint,
  80. const struct vacm_context *);
  81. int
  82. op_vacm_context(struct snmp_context *ctx __unused, struct snmp_value *val,
  83. uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
  84. {
  85. char cname[SNMP_ADM_STR32_SIZ];
  86. size_t cnamelen;
  87. struct vacm_context *vacm_ctx;
  88. if (val->var.subs[sub - 1] != LEAF_vacmContextName)
  89. abort();
  90. switch (op) {
  91. case SNMP_OP_GET:
  92. if ((vacm_ctx = vacm_get_context(&val->var, sub)) == NULL)
  93. return (SNMP_ERR_NOSUCHNAME);
  94. break;
  95. case SNMP_OP_GETNEXT:
  96. if ((vacm_ctx = vacm_get_next_context(&val->var, sub)) == NULL)
  97. return (SNMP_ERR_NOSUCHNAME);
  98. vacm_append_ctxindex(&val->var, sub, vacm_ctx);
  99. break;
  100. case SNMP_OP_SET:
  101. if ((vacm_ctx = vacm_get_context(&val->var, sub)) != NULL)
  102. return (SNMP_ERR_WRONG_VALUE);
  103. if (community != COMM_INITIALIZE)
  104. return (SNMP_ERR_NOT_WRITEABLE);
  105. if (val->var.subs[sub] >= SNMP_ADM_STR32_SIZ)
  106. return (SNMP_ERR_WRONG_VALUE);
  107. if (index_decode(&val->var, sub, iidx, &cname, &cnamelen))
  108. return (SNMP_ERR_GENERR);
  109. cname[cnamelen] = '\0';
  110. if ((vacm_ctx = vacm_add_context(cname, reg_vacm)) == NULL)
  111. return (SNMP_ERR_GENERR);
  112. return (SNMP_ERR_NOERROR);
  113. case SNMP_OP_COMMIT:
  114. /* FALLTHROUGH*/
  115. case SNMP_OP_ROLLBACK:
  116. return (SNMP_ERR_NOERROR);
  117. default:
  118. abort();
  119. }
  120. return (string_get(val, vacm_ctx->ctxname, -1));
  121. }
  122. int
  123. op_vacm_security_to_group(struct snmp_context *ctx, struct snmp_value *val,
  124. uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
  125. {
  126. int32_t smodel;
  127. char uname[SNMP_ADM_STR32_SIZ];
  128. struct vacm_user *user;
  129. switch (op) {
  130. case SNMP_OP_GET:
  131. if ((user = vacm_get_user(&val->var, sub)) == NULL)
  132. return (SNMP_ERR_NOSUCHNAME);
  133. break;
  134. case SNMP_OP_GETNEXT:
  135. if ((user = vacm_get_next_user(&val->var, sub)) == NULL)
  136. return (SNMP_ERR_NOSUCHNAME);
  137. vacm_append_userindex(&val->var, sub, user);
  138. break;
  139. case SNMP_OP_SET:
  140. if ((user = vacm_get_user(&val->var, sub)) == NULL &&
  141. val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
  142. return (SNMP_ERR_NOSUCHNAME);
  143. if (user != NULL) {
  144. if (community != COMM_INITIALIZE &&
  145. user->type == StorageType_readOnly)
  146. return (SNMP_ERR_NOT_WRITEABLE);
  147. if (user->status == RowStatus_active &&
  148. val->v.integer != RowStatus_destroy)
  149. return (SNMP_ERR_INCONS_VALUE);
  150. }
  151. switch (val->var.subs[sub - 1]) {
  152. case LEAF_vacmGroupName:
  153. ctx->scratch->ptr1 = user->group->groupname;
  154. ctx->scratch->int1 = strlen(user->group->groupname);
  155. return (vacm_user_set_group(user,
  156. val->v.octetstring.octets,val->v.octetstring.len));
  157. case LEAF_vacmSecurityToGroupStorageType:
  158. return (SNMP_ERR_INCONS_VALUE);
  159. case LEAF_vacmSecurityToGroupStatus:
  160. if (user == NULL) {
  161. if (val->v.integer != RowStatus_createAndGo ||
  162. vacm_user_index_decode(&val->var, sub,
  163. &smodel, uname) < 0)
  164. return (SNMP_ERR_INCONS_VALUE);
  165. user = vacm_new_user(smodel, uname);
  166. if (user == NULL)
  167. return (SNMP_ERR_GENERR);
  168. user->status = RowStatus_destroy;
  169. if (community != COMM_INITIALIZE)
  170. user->type = StorageType_volatile;
  171. else
  172. user->type = StorageType_readOnly;
  173. } else if (val->v.integer != RowStatus_active &&
  174. val->v.integer != RowStatus_destroy)
  175. return (SNMP_ERR_INCONS_VALUE);
  176. ctx->scratch->int1 = user->status;
  177. user->status = val->v.integer;
  178. break;
  179. }
  180. return (SNMP_ERR_NOERROR);
  181. case SNMP_OP_COMMIT:
  182. if (val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
  183. return (SNMP_ERR_NOERROR);
  184. if ((user = vacm_get_user(&val->var, sub)) == NULL)
  185. return (SNMP_ERR_GENERR);
  186. switch (val->v.integer) {
  187. case RowStatus_destroy:
  188. return (vacm_delete_user(user));
  189. case RowStatus_createAndGo:
  190. user->status = RowStatus_active;
  191. break;
  192. default:
  193. break;
  194. }
  195. return (SNMP_ERR_NOERROR);
  196. case SNMP_OP_ROLLBACK:
  197. if ((user = vacm_get_user(&val->var, sub)) == NULL)
  198. return (SNMP_ERR_GENERR);
  199. switch (val->var.subs[sub - 1]) {
  200. case LEAF_vacmGroupName:
  201. return (vacm_user_set_group(user, ctx->scratch->ptr1,
  202. ctx->scratch->int1));
  203. case LEAF_vacmSecurityToGroupStatus:
  204. if (ctx->scratch->int1 == RowStatus_destroy)
  205. return (vacm_delete_user(user));
  206. user->status = ctx->scratch->int1;
  207. break;
  208. default:
  209. break;
  210. }
  211. return (SNMP_ERR_NOERROR);
  212. default:
  213. abort();
  214. }
  215. switch (val->var.subs[sub - 1]) {
  216. case LEAF_vacmGroupName:
  217. return (string_get(val, user->group->groupname, -1));
  218. case LEAF_vacmSecurityToGroupStorageType:
  219. val->v.integer = user->type;
  220. break;
  221. case LEAF_vacmSecurityToGroupStatus:
  222. val->v.integer = user->status;
  223. break;
  224. default:
  225. abort();
  226. }
  227. return (SNMP_ERR_NOERROR);
  228. }
  229. int
  230. op_vacm_access(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
  231. uint32_t iidx __unused, enum snmp_op op)
  232. {
  233. int32_t smodel, slevel;
  234. char gname[SNMP_ADM_STR32_SIZ], cprefix[SNMP_ADM_STR32_SIZ];
  235. struct vacm_access *acl;
  236. switch (op) {
  237. case SNMP_OP_GET:
  238. if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
  239. return (SNMP_ERR_NOSUCHNAME);
  240. break;
  241. case SNMP_OP_GETNEXT:
  242. if ((acl = vacm_get_next_access_rule(&val->var, sub)) == NULL)
  243. return (SNMP_ERR_NOSUCHNAME);
  244. vacm_append_access_rule_index(&val->var, sub, acl);
  245. break;
  246. case SNMP_OP_SET:
  247. if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL &&
  248. val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
  249. return (SNMP_ERR_NOSUCHNAME);
  250. if (acl != NULL && community != COMM_INITIALIZE &&
  251. acl->type == StorageType_readOnly)
  252. return (SNMP_ERR_NOT_WRITEABLE);
  253. switch (val->var.subs[sub - 1]) {
  254. case LEAF_vacmAccessContextMatch:
  255. ctx->scratch->int1 = acl->ctx_match;
  256. if (val->v.integer == vacmAccessContextMatch_exact)
  257. acl->ctx_match = 1;
  258. else if (val->v.integer == vacmAccessContextMatch_prefix)
  259. acl->ctx_match = 0;
  260. else
  261. return (SNMP_ERR_WRONG_VALUE);
  262. break;
  263. case LEAF_vacmAccessReadViewName:
  264. ctx->scratch->ptr1 = acl->read_view;
  265. acl->read_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len);
  266. if (acl->read_view == NULL) {
  267. acl->read_view = ctx->scratch->ptr1;
  268. return (SNMP_ERR_INCONS_VALUE);
  269. }
  270. return (SNMP_ERR_NOERROR);
  271. case LEAF_vacmAccessWriteViewName:
  272. ctx->scratch->ptr1 = acl->write_view;
  273. if ((acl->write_view =
  274. vacm_get_view_by_name(val->v.octetstring.octets,
  275. val->v.octetstring.len)) == NULL) {
  276. acl->write_view = ctx->scratch->ptr1;
  277. return (SNMP_ERR_INCONS_VALUE);
  278. }
  279. break;
  280. case LEAF_vacmAccessNotifyViewName:
  281. ctx->scratch->ptr1 = acl->notify_view;
  282. if ((acl->notify_view =
  283. vacm_get_view_by_name(val->v.octetstring.octets,
  284. val->v.octetstring.len)) == NULL) {
  285. acl->notify_view = ctx->scratch->ptr1;
  286. return (SNMP_ERR_INCONS_VALUE);
  287. }
  288. break;
  289. case LEAF_vacmAccessStorageType:
  290. return (SNMP_ERR_INCONS_VALUE);
  291. case LEAF_vacmAccessStatus:
  292. if (acl == NULL) {
  293. if (val->v.integer != RowStatus_createAndGo ||
  294. vacm_access_rule_index_decode(&val->var,
  295. sub, gname, cprefix, &smodel, &slevel) < 0)
  296. return (SNMP_ERR_INCONS_VALUE);
  297. if ((acl = vacm_new_access_rule(gname, cprefix,
  298. smodel, slevel)) == NULL)
  299. return (SNMP_ERR_GENERR);
  300. acl->status = RowStatus_destroy;
  301. if (community != COMM_INITIALIZE)
  302. acl->type = StorageType_volatile;
  303. else
  304. acl->type = StorageType_readOnly;
  305. } else if (val->v.integer != RowStatus_active &&
  306. val->v.integer != RowStatus_destroy)
  307. return (SNMP_ERR_INCONS_VALUE);
  308. ctx->scratch->int1 = acl->status;
  309. acl->status = val->v.integer;
  310. break;
  311. }
  312. return (SNMP_ERR_NOERROR);
  313. case SNMP_OP_COMMIT:
  314. if (val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
  315. return (SNMP_ERR_NOERROR);
  316. if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
  317. return (SNMP_ERR_GENERR);
  318. if (val->v.integer == RowStatus_destroy)
  319. return (vacm_delete_access_rule(acl));
  320. else
  321. acl->status = RowStatus_active;
  322. return (SNMP_ERR_NOERROR);
  323. case SNMP_OP_ROLLBACK:
  324. if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
  325. return (SNMP_ERR_GENERR);
  326. switch (val->var.subs[sub - 1]) {
  327. case LEAF_vacmAccessContextMatch:
  328. acl->ctx_match = ctx->scratch->int1;
  329. break;
  330. case LEAF_vacmAccessReadViewName:
  331. acl->read_view = ctx->scratch->ptr1;
  332. break;
  333. case LEAF_vacmAccessWriteViewName:
  334. acl->write_view = ctx->scratch->ptr1;
  335. break;
  336. case LEAF_vacmAccessNotifyViewName:
  337. acl->notify_view = ctx->scratch->ptr1;
  338. break;
  339. case LEAF_vacmAccessStatus:
  340. if (ctx->scratch->int1 == RowStatus_destroy)
  341. return (vacm_delete_access_rule(acl));
  342. default:
  343. break;
  344. }
  345. return (SNMP_ERR_NOERROR);
  346. default:
  347. abort();
  348. }
  349. switch (val->var.subs[sub - 1]) {
  350. case LEAF_vacmAccessContextMatch:
  351. return (string_get(val, acl->ctx_prefix, -1));
  352. case LEAF_vacmAccessReadViewName:
  353. if (acl->read_view != NULL)
  354. return (string_get(val, acl->read_view->viewname, -1));
  355. else
  356. return (string_get(val, NULL, 0));
  357. case LEAF_vacmAccessWriteViewName:
  358. if (acl->write_view != NULL)
  359. return (string_get(val, acl->write_view->viewname, -1));
  360. else
  361. return (string_get(val, NULL, 0));
  362. case LEAF_vacmAccessNotifyViewName:
  363. if (acl->notify_view != NULL)
  364. return (string_get(val, acl->notify_view->viewname, -1));
  365. else
  366. return (string_get(val, NULL, 0));
  367. case LEAF_vacmAccessStorageType:
  368. val->v.integer = acl->type;
  369. break;
  370. case LEAF_vacmAccessStatus:
  371. val->v.integer = acl->status;
  372. break;
  373. default:
  374. abort();
  375. }
  376. return (SNMP_ERR_NOERROR);
  377. }
  378. int
  379. op_vacm_view_lock(struct snmp_context *ctx __unused, struct snmp_value *val,
  380. uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
  381. {
  382. if (val->var.subs[sub - 1] != LEAF_vacmViewSpinLock)
  383. return (SNMP_ERR_NOSUCHNAME);
  384. switch (op) {
  385. case SNMP_OP_GET:
  386. if (++vacm_lock == INT32_MAX)
  387. vacm_lock = 0;
  388. val->v.integer = vacm_lock;
  389. break;
  390. case SNMP_OP_GETNEXT:
  391. abort();
  392. case SNMP_OP_SET:
  393. if (val->v.integer != vacm_lock)
  394. return (SNMP_ERR_INCONS_VALUE);
  395. break;
  396. case SNMP_OP_ROLLBACK:
  397. /* FALLTHROUGH */
  398. case SNMP_OP_COMMIT:
  399. break;
  400. }
  401. return (SNMP_ERR_NOERROR);
  402. }
  403. int
  404. op_vacm_view(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
  405. uint32_t iidx __unused, enum snmp_op op)
  406. {
  407. char vname[SNMP_ADM_STR32_SIZ];
  408. struct asn_oid oid;
  409. struct vacm_view *view;
  410. switch (op) {
  411. case SNMP_OP_GET:
  412. if ((view = vacm_get_view(&val->var, sub)) == NULL)
  413. return (SNMP_ERR_NOSUCHNAME);
  414. break;
  415. case SNMP_OP_GETNEXT:
  416. if ((view = vacm_get_next_view(&val->var, sub)) == NULL)
  417. return (SNMP_ERR_NOSUCHNAME);
  418. vacm_append_viewindex(&val->var, sub, view);
  419. break;
  420. case SNMP_OP_SET:
  421. if ((view = vacm_get_view(&val->var, sub)) == NULL &&
  422. val->var.subs[sub - 1] != LEAF_vacmViewTreeFamilyStatus)
  423. return (SNMP_ERR_NOSUCHNAME);
  424. if (view != NULL) {
  425. if (community != COMM_INITIALIZE &&
  426. view->type == StorageType_readOnly)
  427. return (SNMP_ERR_NOT_WRITEABLE);
  428. if (view->status == RowStatus_active &&
  429. val->v.integer != RowStatus_destroy)
  430. return (SNMP_ERR_INCONS_VALUE);
  431. }
  432. switch (val->var.subs[sub - 1]) {
  433. case LEAF_vacmViewTreeFamilyMask:
  434. if (val->v.octetstring.len > sizeof(view->mask))
  435. ctx->scratch->ptr1 = malloc(sizeof(view->mask));
  436. if (ctx->scratch->ptr1 == NULL)
  437. return (SNMP_ERR_GENERR);
  438. memset(ctx->scratch->ptr1, 0, sizeof(view->mask));
  439. memcpy(ctx->scratch->ptr1, view->mask,
  440. sizeof(view->mask));
  441. memset(view->mask, 0, sizeof(view->mask));
  442. memcpy(view->mask, val->v.octetstring.octets,
  443. val->v.octetstring.len);
  444. break;
  445. case LEAF_vacmViewTreeFamilyType:
  446. ctx->scratch->int1 = view->exclude;
  447. if (val->v.integer == vacmViewTreeFamilyType_included)
  448. view->exclude = 0;
  449. else if (val->v.integer == vacmViewTreeFamilyType_excluded)
  450. view->exclude = 1;
  451. else
  452. return (SNMP_ERR_WRONG_VALUE);
  453. break;
  454. case LEAF_vacmViewTreeFamilyStorageType:
  455. return (SNMP_ERR_INCONS_VALUE);
  456. case LEAF_vacmViewTreeFamilyStatus:
  457. if (view == NULL) {
  458. if (val->v.integer != RowStatus_createAndGo ||
  459. vacm_view_index_decode(&val->var, sub, vname,
  460. &oid) < 0)
  461. return (SNMP_ERR_INCONS_VALUE);
  462. if ((view = vacm_new_view(vname, &oid)) == NULL)
  463. return (SNMP_ERR_GENERR);
  464. view->status = RowStatus_destroy;
  465. if (community != COMM_INITIALIZE)
  466. view->type = StorageType_volatile;
  467. else
  468. view->type = StorageType_readOnly;
  469. } else if (val->v.integer != RowStatus_active &&
  470. val->v.integer != RowStatus_destroy)
  471. return (SNMP_ERR_INCONS_VALUE);
  472. ctx->scratch->int1 = view->status;
  473. view->status = val->v.integer;
  474. break;
  475. }
  476. return (SNMP_ERR_NOERROR);
  477. case SNMP_OP_COMMIT:
  478. switch (val->var.subs[sub - 1]) {
  479. case LEAF_vacmViewTreeFamilyMask:
  480. free(ctx->scratch->ptr1);
  481. break;
  482. case LEAF_vacmViewTreeFamilyStatus:
  483. if ((view = vacm_get_view(&val->var, sub)) == NULL)
  484. return (SNMP_ERR_GENERR);
  485. switch (val->v.integer) {
  486. case RowStatus_destroy:
  487. return (vacm_delete_view(view));
  488. case RowStatus_createAndGo:
  489. view->status = RowStatus_active;
  490. break;
  491. default:
  492. /* NOTREACHED*/
  493. return (SNMP_ERR_GENERR);
  494. }
  495. default:
  496. break;
  497. }
  498. return (SNMP_ERR_NOERROR);
  499. case SNMP_OP_ROLLBACK:
  500. if ((view = vacm_get_view(&val->var, sub)) == NULL)
  501. return (SNMP_ERR_GENERR);
  502. switch (val->var.subs[sub - 1]) {
  503. case LEAF_vacmViewTreeFamilyMask:
  504. memcpy(view->mask, ctx->scratch->ptr1,
  505. sizeof(view->mask));
  506. free(ctx->scratch->ptr1);
  507. break;
  508. case LEAF_vacmViewTreeFamilyType:
  509. view->exclude = ctx->scratch->int1;
  510. break;
  511. case LEAF_vacmViewTreeFamilyStatus:
  512. if (ctx->scratch->int1 == RowStatus_destroy)
  513. return (vacm_delete_view(view));
  514. break;
  515. default:
  516. break;
  517. }
  518. return (SNMP_ERR_NOERROR);
  519. default:
  520. abort();
  521. }
  522. switch (val->var.subs[sub - 1]) {
  523. case LEAF_vacmViewTreeFamilyMask:
  524. return (string_get(val, view->mask, sizeof(view->mask)));
  525. case LEAF_vacmViewTreeFamilyType:
  526. if (view->exclude)
  527. val->v.integer = vacmViewTreeFamilyType_excluded;
  528. else
  529. val->v.integer = vacmViewTreeFamilyType_included;
  530. break;
  531. case LEAF_vacmViewTreeFamilyStorageType:
  532. val->v.integer = view->type;
  533. break;
  534. case LEAF_vacmViewTreeFamilyStatus:
  535. val->v.integer = view->status;
  536. break;
  537. default:
  538. abort();
  539. }
  540. return (SNMP_ERR_NOERROR);
  541. }
  542. static void
  543. vacm_append_userindex(struct asn_oid *oid, uint sub,
  544. const struct vacm_user *user)
  545. {
  546. uint32_t i;
  547. oid->len = sub + strlen(user->secname) + 2;
  548. oid->subs[sub++] = user->sec_model;
  549. oid->subs[sub] = strlen(user->secname);
  550. for (i = 1; i <= strlen(user->secname); i++)
  551. oid->subs[sub + i] = user->secname[i - 1];
  552. }
  553. static int
  554. vacm_user_index_decode(const struct asn_oid *oid, uint sub,
  555. int32_t *smodel, char *uname)
  556. {
  557. uint32_t i;
  558. *smodel = oid->subs[sub++];
  559. if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
  560. return (-1);
  561. for (i = 0; i < oid->subs[sub]; i++)
  562. uname[i] = oid->subs[sub + i + 1];
  563. uname[i] = '\0';
  564. return (0);
  565. }
  566. static struct vacm_user *
  567. vacm_get_user(const struct asn_oid *oid, uint sub)
  568. {
  569. int32_t smodel;
  570. char uname[SNMP_ADM_STR32_SIZ];
  571. struct vacm_user *user;
  572. if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
  573. return (NULL);
  574. for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
  575. if (strcmp(uname, user->secname) == 0 &&
  576. user->sec_model == smodel)
  577. return (user);
  578. return (NULL);
  579. }
  580. static struct vacm_user *
  581. vacm_get_next_user(const struct asn_oid *oid, uint sub)
  582. {
  583. int32_t smodel;
  584. char uname[SNMP_ADM_STR32_SIZ];
  585. struct vacm_user *user;
  586. if (oid->len - sub == 0)
  587. return (vacm_first_user());
  588. if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
  589. return (NULL);
  590. for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
  591. if (strcmp(uname, user->secname) == 0 &&
  592. user->sec_model == smodel)
  593. return (vacm_next_user(user));
  594. return (NULL);
  595. }
  596. static void
  597. vacm_append_access_rule_index(struct asn_oid *oid, uint sub,
  598. const struct vacm_access *acl)
  599. {
  600. uint32_t i;
  601. oid->len = sub + strlen(acl->group->groupname) +
  602. strlen(acl->ctx_prefix) + 4;
  603. oid->subs[sub] = strlen(acl->group->groupname);
  604. for (i = 1; i <= strlen(acl->group->groupname); i++)
  605. oid->subs[sub + i] = acl->group->groupname[i - 1];
  606. sub += strlen(acl->group->groupname) + 1;
  607. oid->subs[sub] = strlen(acl->ctx_prefix);
  608. for (i = 1; i <= strlen(acl->ctx_prefix); i++)
  609. oid->subs[sub + i] = acl->ctx_prefix[i - 1];
  610. sub += strlen(acl->ctx_prefix) + 1;
  611. oid->subs[sub++] = acl->sec_model;
  612. oid->subs[sub] = acl->sec_level;
  613. }
  614. static int
  615. vacm_access_rule_index_decode(const struct asn_oid *oid, uint sub, char *gname,
  616. char *cprefix, int32_t *smodel, int32_t *slevel)
  617. {
  618. uint32_t i;
  619. if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
  620. return (-1);
  621. for (i = 0; i < oid->subs[sub]; i++)
  622. gname[i] = oid->subs[sub + i + 1];
  623. gname[i] = '\0';
  624. sub += strlen(gname) + 1;
  625. if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
  626. return (-1);
  627. for (i = 0; i < oid->subs[sub]; i++)
  628. cprefix[i] = oid->subs[sub + i + 1];
  629. cprefix[i] = '\0';
  630. sub += strlen(cprefix) + 1;
  631. *smodel = oid->subs[sub++];
  632. *slevel = oid->subs[sub];
  633. return (0);
  634. }
  635. struct vacm_access *
  636. vacm_get_access_rule(const struct asn_oid *oid, uint sub)
  637. {
  638. int32_t smodel, slevel;
  639. char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
  640. struct vacm_access *acl;
  641. if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
  642. &slevel) < 0)
  643. return (NULL);
  644. for (acl = vacm_first_access_rule(); acl != NULL;
  645. acl = vacm_next_access_rule(acl))
  646. if (strcmp(gname, acl->group->groupname) == 0 &&
  647. strcmp(prefix, acl->ctx_prefix) == 0 &&
  648. smodel == acl->sec_model && slevel == acl->sec_level)
  649. return (acl);
  650. return (NULL);
  651. }
  652. struct vacm_access *
  653. vacm_get_next_access_rule(const struct asn_oid *oid __unused, uint sub __unused)
  654. {
  655. int32_t smodel, slevel;
  656. char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
  657. struct vacm_access *acl;
  658. if (oid->len - sub == 0)
  659. return (vacm_first_access_rule());
  660. if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
  661. &slevel) < 0)
  662. return (NULL);
  663. for (acl = vacm_first_access_rule(); acl != NULL;
  664. acl = vacm_next_access_rule(acl))
  665. if (strcmp(gname, acl->group->groupname) == 0 &&
  666. strcmp(prefix, acl->ctx_prefix) == 0 &&
  667. smodel == acl->sec_model && slevel == acl->sec_model)
  668. return (vacm_next_access_rule(acl));
  669. return (NULL);
  670. }
  671. static int
  672. vacm_view_index_decode(const struct asn_oid *oid, uint sub, char *vname,
  673. struct asn_oid *view_oid)
  674. {
  675. uint32_t i;
  676. int viod_off;
  677. if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
  678. return (-1);
  679. for (i = 0; i < oid->subs[sub]; i++)
  680. vname[i] = oid->subs[sub + i + 1];
  681. vname[i] = '\0';
  682. viod_off = sub + oid->subs[sub] + 1;
  683. if ((view_oid->len = oid->subs[viod_off]) > ASN_MAXOIDLEN)
  684. return (-1);
  685. memcpy(&view_oid->subs[0], &oid->subs[viod_off + 1],
  686. view_oid->len * sizeof(view_oid->subs[0]));
  687. return (0);
  688. }
  689. static void
  690. vacm_append_viewindex(struct asn_oid *oid, uint sub, const struct vacm_view *view)
  691. {
  692. uint32_t i;
  693. oid->len = sub + strlen(view->viewname) + 1;
  694. oid->subs[sub] = strlen(view->viewname);
  695. for (i = 1; i <= strlen(view->viewname); i++)
  696. oid->subs[sub + i] = view->viewname[i - 1];
  697. sub += strlen(view->viewname) + 1;
  698. oid->subs[sub] = view->subtree.len;
  699. oid->len++;
  700. asn_append_oid(oid, &view->subtree);
  701. }
  702. struct vacm_view *
  703. vacm_get_view(const struct asn_oid *oid, uint sub)
  704. {
  705. char vname[SNMP_ADM_STR32_SIZ];
  706. struct asn_oid subtree;
  707. struct vacm_view *view;
  708. if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
  709. return (NULL);
  710. for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
  711. if (strcmp(vname, view->viewname) == 0 &&
  712. asn_compare_oid(&subtree, &view->subtree)== 0)
  713. return (view);
  714. return (NULL);
  715. }
  716. struct vacm_view *
  717. vacm_get_next_view(const struct asn_oid *oid, uint sub)
  718. {
  719. char vname[SNMP_ADM_STR32_SIZ];
  720. struct asn_oid subtree;
  721. struct vacm_view *view;
  722. if (oid->len - sub == 0)
  723. return (vacm_first_view());
  724. if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
  725. return (NULL);
  726. for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
  727. if (strcmp(vname, view->viewname) == 0 &&
  728. asn_compare_oid(&subtree, &view->subtree)== 0)
  729. return (vacm_next_view(view));
  730. return (NULL);
  731. }
  732. static struct vacm_view *
  733. vacm_get_view_by_name(u_char *octets, u_int len)
  734. {
  735. struct vacm_view *view;
  736. for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
  737. if (strlen(view->viewname) == len &&
  738. memcmp(octets, view->viewname, len) == 0)
  739. return (view);
  740. return (NULL);
  741. }
  742. static struct vacm_context *
  743. vacm_get_context(const struct asn_oid *oid, uint sub)
  744. {
  745. char cname[SNMP_ADM_STR32_SIZ];
  746. size_t cnamelen;
  747. u_int index_count;
  748. struct vacm_context *vacm_ctx;
  749. if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
  750. return (NULL);
  751. index_count = 0;
  752. index_count = SNMP_INDEX(index_count, 1);
  753. if (index_decode(oid, sub, index_count, &cname, &cnamelen))
  754. return (NULL);
  755. for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
  756. vacm_ctx = vacm_next_context(vacm_ctx))
  757. if (strcmp(cname, vacm_ctx->ctxname) == 0)
  758. return (vacm_ctx);
  759. return (NULL);
  760. }
  761. static struct vacm_context *
  762. vacm_get_next_context(const struct asn_oid *oid, uint sub)
  763. {
  764. char cname[SNMP_ADM_STR32_SIZ];
  765. size_t cnamelen;
  766. u_int index_count;
  767. struct vacm_context *vacm_ctx;
  768. if (oid->len - sub == 0)
  769. return (vacm_first_context());
  770. if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
  771. return (NULL);
  772. index_count = 0;
  773. index_count = SNMP_INDEX(index_count, 1);
  774. if (index_decode(oid, sub, index_count, &cname, &cnamelen))
  775. return (NULL);
  776. for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
  777. vacm_ctx = vacm_next_context(vacm_ctx))
  778. if (strcmp(cname, vacm_ctx->ctxname) == 0)
  779. return (vacm_next_context(vacm_ctx));
  780. return (NULL);
  781. }
  782. static void
  783. vacm_append_ctxindex(struct asn_oid *oid, uint sub,
  784. const struct vacm_context *ctx)
  785. {
  786. uint32_t i;
  787. oid->len = sub + strlen(ctx->ctxname) + 1;
  788. oid->subs[sub] = strlen(ctx->ctxname);
  789. for (i = 1; i <= strlen(ctx->ctxname); i++)
  790. oid->subs[sub + i] = ctx->ctxname[i - 1];
  791. }
  792. /*
  793. * VACM snmp module initialization hook.
  794. * Returns 0 on success, < 0 on error.
  795. */
  796. static int
  797. vacm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
  798. {
  799. vacm_module = mod;
  800. vacm_lock = random();
  801. vacm_groups_init();
  802. /* XXX: TODO - initialize structures */
  803. return (0);
  804. }
  805. /*
  806. * VACM snmp module finalization hook.
  807. */
  808. static int
  809. vacm_fini(void)
  810. {
  811. /* XXX: TODO - cleanup */
  812. vacm_flush_contexts(reg_vacm);
  813. or_unregister(reg_vacm);
  814. return (0);
  815. }
  816. /*
  817. * VACM snmp module start operation.
  818. */
  819. static void
  820. vacm_start(void)
  821. {
  822. static char dflt_ctx[] = "";
  823. reg_vacm = or_register(&oid_vacm,
  824. "The MIB module for managing SNMP View-based Access Control Model.",
  825. vacm_module);
  826. (void)vacm_add_context(dflt_ctx, reg_vacm);
  827. }
  828. static void
  829. vacm_dump(void)
  830. {
  831. struct vacm_context *vacmctx;
  832. struct vacm_user *vuser;
  833. struct vacm_access *vacl;
  834. struct vacm_view *view;
  835. static char oidbuf[ASN_OIDSTRLEN];
  836. syslog(LOG_ERR, "\n");
  837. syslog(LOG_ERR, "Context list:");
  838. for (vacmctx = vacm_first_context(); vacmctx != NULL;
  839. vacmctx = vacm_next_context(vacmctx))
  840. syslog(LOG_ERR, "Context \"%s\", module id %d",
  841. vacmctx->ctxname, vacmctx->regid);
  842. syslog(LOG_ERR, "VACM users:");
  843. for (vuser = vacm_first_user(); vuser != NULL;
  844. vuser = vacm_next_user(vuser))
  845. syslog(LOG_ERR, "Uname %s, Group %s, model %d", vuser->secname,
  846. vuser->group!= NULL?vuser->group->groupname:"Unknown",
  847. vuser->sec_model);
  848. syslog(LOG_ERR, "VACM Access rules:");
  849. for (vacl = vacm_first_access_rule(); vacl != NULL;
  850. vacl = vacm_next_access_rule(vacl))
  851. syslog(LOG_ERR, "Group %s, CtxPrefix %s, Model %d, Level %d, "
  852. "RV %s, WR %s, NV %s", vacl->group!=NULL?
  853. vacl->group->groupname:"Unknown", vacl->ctx_prefix,
  854. vacl->sec_model, vacl->sec_level, vacl->read_view!=NULL?
  855. vacl->read_view->viewname:"None", vacl->write_view!=NULL?
  856. vacl->write_view->viewname:"None", vacl->notify_view!=NULL?
  857. vacl->notify_view->viewname:"None");
  858. syslog(LOG_ERR, "VACM Views:");
  859. for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
  860. syslog(LOG_ERR, "View %s, Tree %s - %s", view->viewname,
  861. asn_oid2str_r(&view->subtree, oidbuf), view->exclude?
  862. "excluded":"included");
  863. }
  864. const char vacm_comment[] = \
  865. "This module implements SNMP View-based Access Control Model defined in RFC 3415.";
  866. const struct snmp_module config = {
  867. .comment = vacm_comment,
  868. .init = vacm_init,
  869. .fini = vacm_fini,
  870. .start = vacm_start,
  871. .tree = vacm_ctree,
  872. .dump = vacm_dump,
  873. .tree_size = vacm_CTREE_SIZE,
  874. };