1 /* Portions of this file are subject to the following copyright(s). See
2 * the Net-SNMP's COPYING file for more details and other copyrights
3 * that may apply:
4 */
5 /*
6 * Portions of this file are copyrighted by:
7 * Copyright � 2003 Sun Microsystems, Inc. All rights reserved.
8 * Use is subject to license terms specified in the COPYING file
9 * distributed with the Net-SNMP package.
10 *
11 * Portions of this file are copyrighted by:
12 * Copyright (c) 2016 VMware, Inc. All rights reserved.
13 * Use is subject to license terms specified in the COPYING file
14 * distributed with the Net-SNMP package.
15 */
16
17 /*
18 * vacm.c
19 *
20 * SNMPv3 View-based Access Control Model
21 */
22
23 #include <net-snmp/net-snmp-config.h>
24
25 #if HAVE_STDLIB_H
26 #include <stdlib.h>
27 #endif
28 #if HAVE_STRING_H
29 #include <string.h>
30 #else
31 #include <strings.h>
32 #endif
33 #if HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <sys/types.h>
37 #include <stdio.h>
38 #if TIME_WITH_SYS_TIME
39 # include <sys/time.h>
40 # include <time.h>
41 #else
42 # if HAVE_SYS_TIME_H
43 # include <sys/time.h>
44 # else
45 # include <time.h>
46 # endif
47 #endif
48
49 #if HAVE_NETINET_IN_H
50 #include <netinet/in.h>
51 #endif
52
53 #include <ctype.h>
54
55 #include <net-snmp/types.h>
56 #include <net-snmp/output_api.h>
57 #include <net-snmp/config_api.h>
58
59 #include <net-snmp/library/snmp_api.h>
60 #include <net-snmp/library/system.h> /* strlcpy() */
61 #include <net-snmp/library/tools.h>
62 #include <net-snmp/library/vacm.h>
63
64 static struct vacm_viewEntry *viewList = NULL, *viewScanPtr = NULL;
65 static struct vacm_accessEntry *accessList = NULL, *accessScanPtr = NULL;
66 static struct vacm_groupEntry *groupList = NULL, *groupScanPtr = NULL;
67
68 /*
69 * Macro to extend view masks with 1 bits when shorter than subtree lengths
70 * REF: vacmViewTreeFamilyMask [RFC3415], snmpNotifyFilterMask [RFC3413]
71 */
72
73 #define VIEW_MASK(viewPtr, idx, mask) \
74 ((idx >= viewPtr->viewMaskLen) ? mask : (viewPtr->viewMask[idx] & mask))
75
76 /**
77 * Initilizes the VACM code.
78 * Specifically:
79 * - adds a set of enums mapping view numbers to human readable names
80 */
81 void
init_vacm(void)82 init_vacm(void)
83 {
84 /* views for access via get/set/send-notifications */
85 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("read"),
86 VACM_VIEW_READ);
87 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("write"),
88 VACM_VIEW_WRITE);
89 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("notify"),
90 VACM_VIEW_NOTIFY);
91
92 /* views for permissions when receiving notifications */
93 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("log"),
94 VACM_VIEW_LOG);
95 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("execute"),
96 VACM_VIEW_EXECUTE);
97 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("net"),
98 VACM_VIEW_NET);
99 }
100
101 void
vacm_save(const char * token,const char * type)102 vacm_save(const char *token, const char *type)
103 {
104 struct vacm_viewEntry *vptr;
105 struct vacm_accessEntry *aptr;
106 struct vacm_groupEntry *gptr;
107 int i;
108
109 for (vptr = viewList; vptr != NULL; vptr = vptr->next) {
110 if (vptr->viewStorageType == ST_NONVOLATILE)
111 vacm_save_view(vptr, token, type);
112 }
113
114 for (aptr = accessList; aptr != NULL; aptr = aptr->next) {
115 if (aptr->storageType == ST_NONVOLATILE) {
116 /* Store the standard views (if set) */
117 if ( aptr->views[VACM_VIEW_READ ][0] ||
118 aptr->views[VACM_VIEW_WRITE ][0] ||
119 aptr->views[VACM_VIEW_NOTIFY][0] )
120 vacm_save_access(aptr, token, type);
121 /* Store any other (valid) access views */
122 for ( i=VACM_VIEW_NOTIFY+1; i<VACM_MAX_VIEWS; i++ ) {
123 if ( aptr->views[i][0] )
124 vacm_save_auth_access(aptr, token, type, i);
125 }
126 }
127 }
128
129 for (gptr = groupList; gptr != NULL; gptr = gptr->next) {
130 if (gptr->storageType == ST_NONVOLATILE)
131 vacm_save_group(gptr, token, type);
132 }
133 }
134
135 /*
136 * vacm_save_view(): saves a view entry to the persistent cache
137 */
138 void
vacm_save_view(struct vacm_viewEntry * view,const char * token,const char * type)139 vacm_save_view(struct vacm_viewEntry *view, const char *token,
140 const char *type)
141 {
142 char line[4096];
143 char *cptr;
144
145 memset(line, 0, sizeof(line));
146 snprintf(line, sizeof(line), "%s%s %d %d %d ", token, "View",
147 view->viewStatus, view->viewStorageType, view->viewType);
148 line[ sizeof(line)-1 ] = 0;
149 cptr = &line[strlen(line)]; /* the NULL */
150
151 cptr =
152 read_config_save_octet_string(cptr, (u_char *) view->viewName + 1,
153 view->viewName[0]);
154 *cptr++ = ' ';
155 cptr =
156 read_config_save_objid(cptr, view->viewSubtree+1,
157 view->viewSubtreeLen-1);
158 *cptr++ = ' ';
159 cptr = read_config_save_octet_string(cptr, (u_char *) view->viewMask,
160 view->viewMaskLen);
161
162 read_config_store(type, line);
163 }
164
165 void
vacm_parse_config_view(const char * token,const char * line)166 vacm_parse_config_view(const char *token, const char *line)
167 {
168 struct vacm_viewEntry view;
169 struct vacm_viewEntry *vptr;
170 char *viewName = (char *) &view.viewName;
171 oid *viewSubtree = (oid *) & view.viewSubtree;
172 u_char *viewMask;
173 size_t len;
174
175 view.viewStatus = atoi(line);
176 line = skip_token_const(line);
177 view.viewStorageType = atoi(line);
178 line = skip_token_const(line);
179 view.viewType = atoi(line);
180 line = skip_token_const(line);
181 len = sizeof(view.viewName);
182 line =
183 read_config_read_octet_string(line, (u_char **) & viewName, &len);
184 view.viewSubtreeLen = MAX_OID_LEN + 1;
185 line =
186 read_config_read_objid_const(line, (oid **) & viewSubtree,
187 &view.viewSubtreeLen);
188
189 vptr =
190 vacm_createViewEntry(view.viewName, view.viewSubtree,
191 view.viewSubtreeLen);
192 if (!vptr) {
193 return;
194 }
195
196 vptr->viewStatus = view.viewStatus;
197 vptr->viewStorageType = view.viewStorageType;
198 vptr->viewType = view.viewType;
199 viewMask = vptr->viewMask;
200 vptr->viewMaskLen = sizeof(vptr->viewMask);
201 line =
202 read_config_read_octet_string(line, &viewMask, &vptr->viewMaskLen);
203 }
204
205 /*
206 * vacm_save_access(): saves an access entry to the persistent cache
207 */
208 void
vacm_save_access(struct vacm_accessEntry * access_entry,const char * token,const char * type)209 vacm_save_access(struct vacm_accessEntry *access_entry, const char *token,
210 const char *type)
211 {
212 char line[4096];
213 char *cptr;
214
215 memset(line, 0, sizeof(line));
216 snprintf(line, sizeof(line), "%s%s %d %d %d %d %d ",
217 token, "Access", access_entry->status,
218 access_entry->storageType, access_entry->securityModel,
219 access_entry->securityLevel, access_entry->contextMatch);
220 line[ sizeof(line)-1 ] = 0;
221 cptr = &line[strlen(line)]; /* the NULL */
222 cptr =
223 read_config_save_octet_string(cptr,
224 (u_char *) access_entry->groupName + 1,
225 access_entry->groupName[0] + 1);
226 *cptr++ = ' ';
227 cptr =
228 read_config_save_octet_string(cptr,
229 (u_char *) access_entry->contextPrefix + 1,
230 access_entry->contextPrefix[0] + 1);
231
232 *cptr++ = ' ';
233 cptr = read_config_save_octet_string(cptr, (u_char *) access_entry->views[VACM_VIEW_READ],
234 strlen(access_entry->views[VACM_VIEW_READ]) + 1);
235 *cptr++ = ' ';
236 cptr =
237 read_config_save_octet_string(cptr, (u_char *) access_entry->views[VACM_VIEW_WRITE],
238 strlen(access_entry->views[VACM_VIEW_WRITE]) + 1);
239 *cptr++ = ' ';
240 cptr =
241 read_config_save_octet_string(cptr, (u_char *) access_entry->views[VACM_VIEW_NOTIFY],
242 strlen(access_entry->views[VACM_VIEW_NOTIFY]) + 1);
243
244 read_config_store(type, line);
245 }
246
247 void
vacm_save_auth_access(struct vacm_accessEntry * access_entry,const char * token,const char * type,int authtype)248 vacm_save_auth_access(struct vacm_accessEntry *access_entry,
249 const char *token, const char *type, int authtype)
250 {
251 char line[4096];
252 char *cptr;
253
254 memset(line, 0, sizeof(line));
255 snprintf(line, sizeof(line), "%s%s %d %d %d %d %d ",
256 token, "AuthAccess", access_entry->status,
257 access_entry->storageType, access_entry->securityModel,
258 access_entry->securityLevel, access_entry->contextMatch);
259 line[ sizeof(line)-1 ] = 0;
260 cptr = &line[strlen(line)]; /* the NULL */
261 cptr =
262 read_config_save_octet_string(cptr,
263 (u_char *) access_entry->groupName + 1,
264 access_entry->groupName[0] + 1);
265 *cptr++ = ' ';
266 cptr =
267 read_config_save_octet_string(cptr,
268 (u_char *) access_entry->contextPrefix + 1,
269 access_entry->contextPrefix[0] + 1);
270
271 snprintf(cptr, sizeof(line)-(cptr-line), " %d ", authtype);
272 while ( *cptr )
273 cptr++;
274
275 *cptr++ = ' ';
276 cptr = read_config_save_octet_string(cptr,
277 (u_char *)access_entry->views[authtype],
278 strlen(access_entry->views[authtype]) + 1);
279
280 read_config_store(type, line);
281 }
282
283 char *
_vacm_parse_config_access_common(struct vacm_accessEntry ** aptr,const char * line)284 _vacm_parse_config_access_common(struct vacm_accessEntry **aptr,
285 const char *line)
286 {
287 struct vacm_accessEntry access;
288 char *cPrefix = (char *) &access.contextPrefix;
289 char *gName = (char *) &access.groupName;
290 size_t len;
291
292 access.status = atoi(line);
293 line = skip_token_const(line);
294 access.storageType = atoi(line);
295 line = skip_token_const(line);
296 access.securityModel = atoi(line);
297 line = skip_token_const(line);
298 access.securityLevel = atoi(line);
299 line = skip_token_const(line);
300 access.contextMatch = atoi(line);
301 line = skip_token_const(line);
302 len = sizeof(access.groupName);
303 line = read_config_read_octet_string(line, (u_char **) &gName, &len);
304 len = sizeof(access.contextPrefix);
305 line = read_config_read_octet_string(line, (u_char **) &cPrefix, &len);
306
307 *aptr = vacm_getAccessEntry(access.groupName,
308 access.contextPrefix,
309 access.securityModel,
310 access.securityLevel);
311 if (!*aptr)
312 *aptr = vacm_createAccessEntry(access.groupName,
313 access.contextPrefix,
314 access.securityModel,
315 access.securityLevel);
316 if (!*aptr)
317 return NULL;
318
319 (*aptr)->status = access.status;
320 (*aptr)->storageType = access.storageType;
321 (*aptr)->securityModel = access.securityModel;
322 (*aptr)->securityLevel = access.securityLevel;
323 (*aptr)->contextMatch = access.contextMatch;
324 return NETSNMP_REMOVE_CONST(char *, line);
325 }
326
327 void
vacm_parse_config_access(const char * token,const char * line)328 vacm_parse_config_access(const char *token, const char *line)
329 {
330 struct vacm_accessEntry *aptr;
331 char *readView, *writeView, *notifyView;
332 size_t len;
333
334 line = _vacm_parse_config_access_common(&aptr, line);
335 if (!line)
336 return;
337
338 readView = (char *) aptr->views[VACM_VIEW_READ];
339 len = sizeof(aptr->views[VACM_VIEW_READ]);
340 line =
341 read_config_read_octet_string(line, (u_char **) & readView, &len);
342 writeView = (char *) aptr->views[VACM_VIEW_WRITE];
343 len = sizeof(aptr->views[VACM_VIEW_WRITE]);
344 line =
345 read_config_read_octet_string(line, (u_char **) & writeView, &len);
346 notifyView = (char *) aptr->views[VACM_VIEW_NOTIFY];
347 len = sizeof(aptr->views[VACM_VIEW_NOTIFY]);
348 line =
349 read_config_read_octet_string(line, (u_char **) & notifyView,
350 &len);
351 }
352
353 void
vacm_parse_config_auth_access(const char * token,const char * line)354 vacm_parse_config_auth_access(const char *token, const char *line)
355 {
356 struct vacm_accessEntry *aptr;
357 int authtype;
358 char *view;
359 size_t len;
360
361 line = _vacm_parse_config_access_common(&aptr, line);
362 if (!line)
363 return;
364
365 authtype = atoi(line);
366 line = skip_token_const(line);
367
368 view = (char *) aptr->views[authtype];
369 len = sizeof(aptr->views[authtype]);
370 line = read_config_read_octet_string(line, (u_char **) & view, &len);
371 }
372
373 /*
374 * vacm_save_group(): saves a group entry to the persistent cache
375 */
376 void
vacm_save_group(struct vacm_groupEntry * group_entry,const char * token,const char * type)377 vacm_save_group(struct vacm_groupEntry *group_entry, const char *token,
378 const char *type)
379 {
380 char line[4096];
381 char *cptr;
382
383 memset(line, 0, sizeof(line));
384 snprintf(line, sizeof(line), "%s%s %d %d %d ",
385 token, "Group", group_entry->status,
386 group_entry->storageType, group_entry->securityModel);
387 line[ sizeof(line)-1 ] = 0;
388 cptr = &line[strlen(line)]; /* the NULL */
389
390 cptr =
391 read_config_save_octet_string(cptr,
392 (u_char *) group_entry->securityName + 1,
393 group_entry->securityName[0] + 1);
394 *cptr++ = ' ';
395 cptr = read_config_save_octet_string(cptr, (u_char *) group_entry->groupName,
396 strlen(group_entry->groupName) + 1);
397
398 read_config_store(type, line);
399 }
400
401 void
vacm_parse_config_group(const char * token,const char * line)402 vacm_parse_config_group(const char *token, const char *line)
403 {
404 struct vacm_groupEntry group;
405 struct vacm_groupEntry *gptr;
406 char *securityName = (char *) &group.securityName;
407 char *groupName;
408 size_t len;
409
410 group.status = atoi(line);
411 line = skip_token_const(line);
412 group.storageType = atoi(line);
413 line = skip_token_const(line);
414 group.securityModel = atoi(line);
415 line = skip_token_const(line);
416 len = sizeof(group.securityName);
417 line =
418 read_config_read_octet_string(line, (u_char **) & securityName,
419 &len);
420
421 gptr = vacm_createGroupEntry(group.securityModel, group.securityName);
422 if (!gptr)
423 return;
424
425 gptr->status = group.status;
426 gptr->storageType = group.storageType;
427 groupName = (char *) gptr->groupName;
428 len = sizeof(group.groupName);
429 line =
430 read_config_read_octet_string(line, (u_char **) & groupName, &len);
431 }
432
433 struct vacm_viewEntry *
netsnmp_view_get(struct vacm_viewEntry * head,const char * viewName,oid * viewSubtree,size_t viewSubtreeLen,int mode)434 netsnmp_view_get(struct vacm_viewEntry *head, const char *viewName,
435 oid * viewSubtree, size_t viewSubtreeLen, int mode)
436 {
437 struct vacm_viewEntry *vp, *vpret = NULL;
438 char view[VACMSTRINGLEN];
439 int found, glen;
440 int count=0;
441
442 glen = (int) strlen(viewName);
443 if (glen < 0 || glen > VACM_MAX_STRING)
444 return NULL;
445 view[0] = glen;
446 strlcpy(view + 1, viewName, sizeof(view) - 1);
447 for (vp = head; vp; vp = vp->next) {
448 if (!memcmp(view, vp->viewName, glen + 1)
449 && viewSubtreeLen >= (vp->viewSubtreeLen - 1)) {
450 int mask = 0x80;
451 unsigned int oidpos, maskpos = 0;
452 found = 1;
453
454 for (oidpos = 0;
455 found && oidpos < vp->viewSubtreeLen - 1;
456 oidpos++) {
457 if (mode==VACM_MODE_IGNORE_MASK || (VIEW_MASK(vp, maskpos, mask) != 0)) {
458 if (viewSubtree[oidpos] !=
459 vp->viewSubtree[oidpos + 1])
460 found = 0;
461 }
462 if (mask == 1) {
463 mask = 0x80;
464 maskpos++;
465 } else
466 mask >>= 1;
467 }
468
469 if (found) {
470 /*
471 * match successful, keep this node if its longer than
472 * the previous or (equal and lexicographically greater
473 * than the previous).
474 */
475 count++;
476 if (mode == VACM_MODE_CHECK_SUBTREE) {
477 vpret = vp;
478 } else if (vpret == NULL
479 || vp->viewSubtreeLen > vpret->viewSubtreeLen
480 || (vp->viewSubtreeLen == vpret->viewSubtreeLen
481 && snmp_oid_compare(vp->viewSubtree + 1,
482 vp->viewSubtreeLen - 1,
483 vpret->viewSubtree + 1,
484 vpret->viewSubtreeLen - 1) >
485 0)) {
486 vpret = vp;
487 }
488 }
489 }
490 }
491 DEBUGMSGTL(("vacm:getView", ", %s\n", (vpret) ? "found" : "none"));
492 if (mode == VACM_MODE_CHECK_SUBTREE && count > 1) {
493 return NULL;
494 }
495 return vpret;
496 }
497
498 /*******************************************************************o-o******
499 * netsnmp_view_exists
500 *
501 * Check to see if a view with the given name exists.
502 *
503 * Parameters:
504 * viewName - Name of view to check
505 *
506 * Returns 0 if the view does not exist. Otherwise, it returns the number
507 * of OID rows for the given name.
508 */
509 int
netsnmp_view_exists(struct vacm_viewEntry * head,const char * viewName)510 netsnmp_view_exists(struct vacm_viewEntry *head, const char *viewName)
511 {
512 struct vacm_viewEntry *vp;
513 char view[VACMSTRINGLEN];
514 int len, count = 0;
515
516 len = (int) strlen(viewName);
517 if (len < 0 || len > VACM_MAX_STRING)
518 return 0;
519 view[0] = len;
520 strcpy(view + 1, viewName);
521 DEBUGMSGTL(("9:vacm:view_exists", "checking %s\n", viewName));
522 for (vp = head; vp; vp = vp->next) {
523 if (memcmp(view, vp->viewName, len + 1) == 0)
524 ++count;
525 }
526
527 return count;
528 }
529
530 /*******************************************************************o-o******
531 * vacm_checkSubtree
532 *
533 * Check to see if everything within a subtree is in view, not in view,
534 * or possibly both.
535 *
536 * Parameters:
537 * *viewName - Name of view to check
538 * *viewSubtree - OID of subtree
539 * viewSubtreeLen - length of subtree OID
540 *
541 * Returns:
542 * VACM_SUCCESS The OID is included in the view.
543 * VACM_NOTINVIEW If no entry in the view list includes the
544 * provided OID, or the OID is explicitly excluded
545 * from the view.
546 * VACM_SUBTREE_UNKNOWN The entire subtree has both allowed and disallowed
547 * portions.
548 */
549 int
netsnmp_view_subtree_check(struct vacm_viewEntry * head,const char * viewName,oid * viewSubtree,size_t viewSubtreeLen)550 netsnmp_view_subtree_check(struct vacm_viewEntry *head, const char *viewName,
551 oid * viewSubtree, size_t viewSubtreeLen)
552 {
553 struct vacm_viewEntry *vp, *vpShorter = NULL, *vpLonger = NULL;
554 char view[VACMSTRINGLEN];
555 int found, glen;
556
557 glen = (int) strlen(viewName);
558 if (glen < 0 || glen > VACM_MAX_STRING)
559 return VACM_NOTINVIEW;
560 view[0] = glen;
561 strlcpy(view + 1, viewName, sizeof(view) - 1);
562 DEBUGMSGTL(("9:vacm:checkSubtree", "view %s\n", viewName));
563 for (vp = head; vp; vp = vp->next) {
564 if (!memcmp(view, vp->viewName, glen + 1)) {
565 /*
566 * If the subtree defined in the view is shorter than or equal
567 * to the subtree we are comparing, then it might envelop the
568 * subtree we are comparing against.
569 */
570 if (viewSubtreeLen >= (vp->viewSubtreeLen - 1)) {
571 int mask = 0x80;
572 unsigned int oidpos, maskpos = 0;
573 found = 1;
574
575 /*
576 * check the mask
577 */
578 for (oidpos = 0;
579 found && oidpos < vp->viewSubtreeLen - 1;
580 oidpos++) {
581 if (VIEW_MASK(vp, maskpos, mask) != 0) {
582 if (viewSubtree[oidpos] !=
583 vp->viewSubtree[oidpos + 1])
584 found = 0;
585 }
586 if (mask == 1) {
587 mask = 0x80;
588 maskpos++;
589 } else
590 mask >>= 1;
591 }
592
593 if (found) {
594 /*
595 * match successful, keep this node if it's longer than
596 * the previous or (equal and lexicographically greater
597 * than the previous).
598 */
599 DEBUGMSGTL(("9:vacm:checkSubtree", " %s matched?\n", vp->viewName));
600
601 if (vpShorter == NULL
602 || vp->viewSubtreeLen > vpShorter->viewSubtreeLen
603 || (vp->viewSubtreeLen == vpShorter->viewSubtreeLen
604 && snmp_oid_compare(vp->viewSubtree + 1,
605 vp->viewSubtreeLen - 1,
606 vpShorter->viewSubtree + 1,
607 vpShorter->viewSubtreeLen - 1) >
608 0)) {
609 vpShorter = vp;
610 }
611 }
612 }
613 /*
614 * If the subtree defined in the view is longer than the
615 * subtree we are comparing, then it might ambiguate our
616 * response.
617 */
618 else {
619 int mask = 0x80;
620 unsigned int oidpos, maskpos = 0;
621 found = 1;
622
623 /*
624 * check the mask up to the length of the provided subtree
625 */
626 for (oidpos = 0;
627 found && oidpos < viewSubtreeLen;
628 oidpos++) {
629 if (VIEW_MASK(vp, maskpos, mask) != 0) {
630 if (viewSubtree[oidpos] !=
631 vp->viewSubtree[oidpos + 1])
632 found = 0;
633 }
634 if (mask == 1) {
635 mask = 0x80;
636 maskpos++;
637 } else
638 mask >>= 1;
639 }
640
641 if (found) {
642 /*
643 * match successful. If we already found a match
644 * with a different view type, then parts of the subtree
645 * are included and others are excluded, so return UNKNOWN.
646 */
647 DEBUGMSGTL(("9:vacm:checkSubtree", " %s matched?\n", vp->viewName));
648 if (vpLonger != NULL
649 && (vpLonger->viewType != vp->viewType)) {
650 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "unknown"));
651 return VACM_SUBTREE_UNKNOWN;
652 }
653 else if (vpLonger == NULL) {
654 vpLonger = vp;
655 }
656 }
657 }
658 }
659 }
660 DEBUGMSGTL(("9:vacm:checkSubtree", " %s matched\n", viewName));
661
662 /*
663 * If we found a matching view subtree with a longer OID than the provided
664 * OID, check to see if its type is consistent with any matching view
665 * subtree we may have found with a shorter OID than the provided OID.
666 *
667 * The view type of the longer OID is inconsistent with the shorter OID in
668 * either of these two cases:
669 * 1) No matching shorter OID was found and the view type of the longer
670 * OID is INCLUDE.
671 * 2) A matching shorter ID was found and its view type doesn't match
672 * the view type of the longer OID.
673 */
674 if (vpLonger != NULL) {
675 if ((!vpShorter && vpLonger->viewType != SNMP_VIEW_EXCLUDED)
676 || (vpShorter && vpLonger->viewType != vpShorter->viewType)) {
677 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "unknown"));
678 return VACM_SUBTREE_UNKNOWN;
679 }
680 }
681
682 if (vpShorter && vpShorter->viewType != SNMP_VIEW_EXCLUDED) {
683 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "included"));
684 return VACM_SUCCESS;
685 }
686
687 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "excluded"));
688 return VACM_NOTINVIEW;
689 }
690
691 void
vacm_scanViewInit(void)692 vacm_scanViewInit(void)
693 {
694 viewScanPtr = viewList;
695 }
696
697 struct vacm_viewEntry *
vacm_scanViewNext(void)698 vacm_scanViewNext(void)
699 {
700 struct vacm_viewEntry *returnval = viewScanPtr;
701 if (viewScanPtr)
702 viewScanPtr = viewScanPtr->next;
703 return returnval;
704 }
705
706 struct vacm_viewEntry *
netsnmp_view_create(struct vacm_viewEntry ** head,const char * viewName,oid * viewSubtree,size_t viewSubtreeLen)707 netsnmp_view_create(struct vacm_viewEntry **head, const char *viewName,
708 oid * viewSubtree, size_t viewSubtreeLen)
709 {
710 struct vacm_viewEntry *vp, *lp, *op = NULL;
711 int cmp, cmp2, glen;
712
713 glen = (int) strlen(viewName);
714 if (glen < 0 || glen > VACM_MAX_STRING || viewSubtreeLen > MAX_OID_LEN)
715 return NULL;
716 vp = (struct vacm_viewEntry *) calloc(1,
717 sizeof(struct vacm_viewEntry));
718 if (vp == NULL)
719 return NULL;
720 vp->reserved =
721 (struct vacm_viewEntry *) calloc(1, sizeof(struct vacm_viewEntry));
722 if (vp->reserved == NULL) {
723 free(vp);
724 return NULL;
725 }
726
727 vp->viewName[0] = glen;
728 strlcpy(vp->viewName + 1, viewName, sizeof(vp->viewName) - 1);
729 vp->viewSubtree[0] = viewSubtreeLen;
730 memcpy(vp->viewSubtree + 1, viewSubtree, viewSubtreeLen * sizeof(oid));
731 vp->viewSubtreeLen = viewSubtreeLen + 1;
732
733 lp = *head;
734 while (lp) {
735 cmp = memcmp(lp->viewName, vp->viewName, glen + 1);
736 cmp2 = snmp_oid_compare(lp->viewSubtree, lp->viewSubtreeLen,
737 vp->viewSubtree, vp->viewSubtreeLen);
738 if (cmp == 0 && cmp2 > 0)
739 break;
740 if (cmp > 0)
741 break;
742 op = lp;
743 lp = lp->next;
744 }
745 vp->next = lp;
746 if (op)
747 op->next = vp;
748 else
749 *head = vp;
750 return vp;
751 }
752
753 void
netsnmp_view_destroy(struct vacm_viewEntry ** head,const char * viewName,oid * viewSubtree,size_t viewSubtreeLen)754 netsnmp_view_destroy(struct vacm_viewEntry **head, const char *viewName,
755 oid * viewSubtree, size_t viewSubtreeLen)
756 {
757 struct vacm_viewEntry *vp, *lastvp = NULL;
758
759 if ((*head) && !strcmp((*head)->viewName + 1, viewName)
760 && (*head)->viewSubtreeLen == viewSubtreeLen
761 && !memcmp((char *) (*head)->viewSubtree, (char *) viewSubtree,
762 viewSubtreeLen * sizeof(oid))) {
763 vp = (*head);
764 (*head) = (*head)->next;
765 } else {
766 for (vp = (*head); vp; vp = vp->next) {
767 if (!strcmp(vp->viewName + 1, viewName)
768 && vp->viewSubtreeLen == viewSubtreeLen
769 && !memcmp((char *) vp->viewSubtree, (char *) viewSubtree,
770 viewSubtreeLen * sizeof(oid)))
771 break;
772 lastvp = vp;
773 }
774 if (!vp || !lastvp)
775 return;
776 lastvp->next = vp->next;
777 }
778 if (vp->reserved)
779 free(vp->reserved);
780 free(vp);
781 return;
782 }
783
784 void
netsnmp_view_clear(struct vacm_viewEntry ** head)785 netsnmp_view_clear(struct vacm_viewEntry **head)
786 {
787 struct vacm_viewEntry *vp;
788 while ((vp = (*head))) {
789 (*head) = vp->next;
790 if (vp->reserved)
791 free(vp->reserved);
792 free(vp);
793 }
794 }
795
796 struct vacm_groupEntry *
vacm_getGroupEntry(int securityModel,const char * securityName)797 vacm_getGroupEntry(int securityModel, const char *securityName)
798 {
799 struct vacm_groupEntry *vp;
800 char secname[VACMSTRINGLEN];
801 int glen;
802
803 glen = (int) strlen(securityName);
804 if (glen < 0 || glen > VACM_MAX_STRING)
805 return NULL;
806 secname[0] = glen;
807 strlcpy(secname + 1, securityName, sizeof(secname) - 1);
808
809 for (vp = groupList; vp; vp = vp->next) {
810 if ((securityModel == vp->securityModel
811 || vp->securityModel == SNMP_SEC_MODEL_ANY)
812 && !memcmp(vp->securityName, secname, glen + 1))
813 return vp;
814 }
815 return NULL;
816 }
817
818 void
vacm_scanGroupInit(void)819 vacm_scanGroupInit(void)
820 {
821 groupScanPtr = groupList;
822 }
823
824 struct vacm_groupEntry *
vacm_scanGroupNext(void)825 vacm_scanGroupNext(void)
826 {
827 struct vacm_groupEntry *returnval = groupScanPtr;
828 if (groupScanPtr)
829 groupScanPtr = groupScanPtr->next;
830 return returnval;
831 }
832
833 struct vacm_groupEntry *
vacm_createGroupEntry(int securityModel,const char * securityName)834 vacm_createGroupEntry(int securityModel, const char *securityName)
835 {
836 struct vacm_groupEntry *gp, *lg, *og;
837 int cmp, glen;
838
839 glen = (int) strlen(securityName);
840 if (glen < 0 || glen > VACM_MAX_STRING)
841 return NULL;
842 gp = (struct vacm_groupEntry *) calloc(1,
843 sizeof(struct vacm_groupEntry));
844 if (gp == NULL)
845 return NULL;
846 gp->reserved =
847 (struct vacm_groupEntry *) calloc(1,
848 sizeof(struct vacm_groupEntry));
849 if (gp->reserved == NULL) {
850 free(gp);
851 return NULL;
852 }
853
854 gp->securityModel = securityModel;
855 gp->securityName[0] = glen;
856 strlcpy(gp->securityName + 1, securityName, sizeof(gp->securityName) - 1);
857
858 lg = groupList;
859 og = NULL;
860 while (lg) {
861 if (lg->securityModel > securityModel)
862 break;
863 if (lg->securityModel == securityModel &&
864 (cmp =
865 memcmp(lg->securityName, gp->securityName, glen + 1)) > 0)
866 break;
867 /*
868 * if (lg->securityModel == securityModel && cmp == 0) abort();
869 */
870 og = lg;
871 lg = lg->next;
872 }
873 gp->next = lg;
874 if (og == NULL)
875 groupList = gp;
876 else
877 og->next = gp;
878 return gp;
879 }
880
881 void
vacm_destroyGroupEntry(int securityModel,const char * securityName)882 vacm_destroyGroupEntry(int securityModel, const char *securityName)
883 {
884 struct vacm_groupEntry *vp, *lastvp = NULL;
885
886 if (groupList && groupList->securityModel == securityModel
887 && !strcmp(groupList->securityName + 1, securityName)) {
888 vp = groupList;
889 groupList = groupList->next;
890 } else {
891 for (vp = groupList; vp; vp = vp->next) {
892 if (vp->securityModel == securityModel
893 && !strcmp(vp->securityName + 1, securityName))
894 break;
895 lastvp = vp;
896 }
897 if (!vp || !lastvp)
898 return;
899 lastvp->next = vp->next;
900 }
901 if (vp->reserved)
902 free(vp->reserved);
903 free(vp);
904 return;
905 }
906
907
908 void
vacm_destroyAllGroupEntries(void)909 vacm_destroyAllGroupEntries(void)
910 {
911 struct vacm_groupEntry *gp;
912 while ((gp = groupList)) {
913 groupList = gp->next;
914 if (gp->reserved)
915 free(gp->reserved);
916 free(gp);
917 }
918 }
919
920 struct vacm_accessEntry *
_vacm_choose_best(struct vacm_accessEntry * current,struct vacm_accessEntry * candidate)921 _vacm_choose_best( struct vacm_accessEntry *current,
922 struct vacm_accessEntry *candidate)
923 {
924 /*
925 * RFC 3415: vacmAccessTable:
926 * 2) if this set has [more than] one member, ...
927 * it comes down to deciding how to weight the
928 * preferences between ContextPrefixes,
929 * SecurityModels, and SecurityLevels
930 */
931 if (( !current ) ||
932 /* a) if the subset of entries with securityModel
933 * matching the securityModel in the message is
934 * not empty, then discard the rest
935 */
936 ( current->securityModel == SNMP_SEC_MODEL_ANY &&
937 candidate->securityModel != SNMP_SEC_MODEL_ANY ) ||
938 /* b) if the subset of entries with vacmAccessContextPrefix
939 * matching the contextName in the message is
940 * not empty, then discard the rest
941 */
942 ( current->contextMatch == CONTEXT_MATCH_PREFIX &&
943 candidate->contextMatch == CONTEXT_MATCH_EXACT ) ||
944 /* c) discard all entries with ContextPrefixes shorter
945 * than the longest one remaining in the set
946 */
947 ( current->contextMatch == CONTEXT_MATCH_PREFIX &&
948 current->contextPrefix[0] < candidate->contextPrefix[0] ) ||
949 /* d) select the entry with the highest securityLevel
950 */
951 ( current->securityLevel < candidate->securityLevel )) {
952
953 return candidate;
954 }
955
956 return current;
957 }
958
959 struct vacm_accessEntry *
vacm_getAccessEntry(const char * groupName,const char * contextPrefix,int securityModel,int securityLevel)960 vacm_getAccessEntry(const char *groupName,
961 const char *contextPrefix,
962 int securityModel, int securityLevel)
963 {
964 struct vacm_accessEntry *vp, *best=NULL;
965 char group[VACMSTRINGLEN];
966 char context[VACMSTRINGLEN];
967 int glen, clen;
968
969 glen = (int) strlen(groupName);
970 if (glen < 0 || glen > VACM_MAX_STRING)
971 return NULL;
972 clen = (int) strlen(contextPrefix);
973 if (clen < 0 || clen > VACM_MAX_STRING)
974 return NULL;
975
976 group[0] = glen;
977 strlcpy(group + 1, groupName, sizeof(group) - 1);
978 context[0] = clen;
979 strlcpy(context + 1, contextPrefix, sizeof(context) - 1);
980 for (vp = accessList; vp; vp = vp->next) {
981 if ((securityModel == vp->securityModel
982 || vp->securityModel == SNMP_SEC_MODEL_ANY)
983 && securityLevel >= vp->securityLevel
984 && !memcmp(vp->groupName, group, glen + 1)
985 &&
986 ((vp->contextMatch == CONTEXT_MATCH_EXACT
987 && clen == vp->contextPrefix[0]
988 && (memcmp(vp->contextPrefix, context, clen + 1) == 0))
989 || (vp->contextMatch == CONTEXT_MATCH_PREFIX
990 && clen >= vp->contextPrefix[0]
991 && (memcmp(vp->contextPrefix + 1, context + 1,
992 vp->contextPrefix[0]) == 0))))
993 best = _vacm_choose_best( best, vp );
994 }
995 return best;
996 }
997
998 void
vacm_scanAccessInit(void)999 vacm_scanAccessInit(void)
1000 {
1001 accessScanPtr = accessList;
1002 }
1003
1004 struct vacm_accessEntry *
vacm_scanAccessNext(void)1005 vacm_scanAccessNext(void)
1006 {
1007 struct vacm_accessEntry *returnval = accessScanPtr;
1008 if (accessScanPtr)
1009 accessScanPtr = accessScanPtr->next;
1010 return returnval;
1011 }
1012
1013 struct vacm_accessEntry *
vacm_createAccessEntry(const char * groupName,const char * contextPrefix,int securityModel,int securityLevel)1014 vacm_createAccessEntry(const char *groupName,
1015 const char *contextPrefix,
1016 int securityModel, int securityLevel)
1017 {
1018 struct vacm_accessEntry *vp, *lp, *op = NULL;
1019 int cmp, glen, clen;
1020
1021 glen = (int) strlen(groupName);
1022 if (glen < 0 || glen > VACM_MAX_STRING)
1023 return NULL;
1024 clen = (int) strlen(contextPrefix);
1025 if (clen < 0 || clen > VACM_MAX_STRING)
1026 return NULL;
1027 vp = (struct vacm_accessEntry *) calloc(1,
1028 sizeof(struct
1029 vacm_accessEntry));
1030 if (vp == NULL)
1031 return NULL;
1032 vp->reserved =
1033 (struct vacm_accessEntry *) calloc(1,
1034 sizeof(struct
1035 vacm_accessEntry));
1036 if (vp->reserved == NULL) {
1037 free(vp);
1038 return NULL;
1039 }
1040
1041 vp->securityModel = securityModel;
1042 vp->securityLevel = securityLevel;
1043 vp->groupName[0] = glen;
1044 strlcpy(vp->groupName + 1, groupName, sizeof(vp->groupName) - 1);
1045 vp->contextPrefix[0] = clen;
1046 strlcpy(vp->contextPrefix + 1, contextPrefix,
1047 sizeof(vp->contextPrefix) - 1);
1048
1049 lp = accessList;
1050 while (lp) {
1051 cmp = memcmp(lp->groupName, vp->groupName, glen + 1);
1052 if (cmp > 0)
1053 break;
1054 if (cmp < 0)
1055 goto next;
1056 cmp = memcmp(lp->contextPrefix, vp->contextPrefix, clen + 1);
1057 if (cmp > 0)
1058 break;
1059 if (cmp < 0)
1060 goto next;
1061 if (lp->securityModel > securityModel)
1062 break;
1063 if (lp->securityModel < securityModel)
1064 goto next;
1065 if (lp->securityLevel > securityLevel)
1066 break;
1067 next:
1068 op = lp;
1069 lp = lp->next;
1070 }
1071 vp->next = lp;
1072 if (op == NULL)
1073 accessList = vp;
1074 else
1075 op->next = vp;
1076 return vp;
1077 }
1078
1079 void
vacm_destroyAccessEntry(const char * groupName,const char * contextPrefix,int securityModel,int securityLevel)1080 vacm_destroyAccessEntry(const char *groupName,
1081 const char *contextPrefix,
1082 int securityModel, int securityLevel)
1083 {
1084 struct vacm_accessEntry *vp, *lastvp = NULL;
1085
1086 if (accessList && accessList->securityModel == securityModel
1087 && accessList->securityLevel == securityLevel
1088 && !strcmp(accessList->groupName + 1, groupName)
1089 && !strcmp(accessList->contextPrefix + 1, contextPrefix)) {
1090 vp = accessList;
1091 accessList = accessList->next;
1092 } else {
1093 for (vp = accessList; vp; vp = vp->next) {
1094 if (vp->securityModel == securityModel
1095 && vp->securityLevel == securityLevel
1096 && !strcmp(vp->groupName + 1, groupName)
1097 && !strcmp(vp->contextPrefix + 1, contextPrefix))
1098 break;
1099 lastvp = vp;
1100 }
1101 if (!vp || !lastvp)
1102 return;
1103 lastvp->next = vp->next;
1104 }
1105 if (vp->reserved)
1106 free(vp->reserved);
1107 free(vp);
1108 return;
1109 }
1110
1111 void
vacm_destroyAllAccessEntries(void)1112 vacm_destroyAllAccessEntries(void)
1113 {
1114 struct vacm_accessEntry *ap;
1115 while ((ap = accessList)) {
1116 accessList = ap->next;
1117 if (ap->reserved)
1118 free(ap->reserved);
1119 free(ap);
1120 }
1121 }
1122
1123 int
store_vacm(int majorID,int minorID,void * serverarg,void * clientarg)1124 store_vacm(int majorID, int minorID, void *serverarg, void *clientarg)
1125 {
1126 /*
1127 * figure out our application name
1128 */
1129 char *appname = (char *) clientarg;
1130 if (appname == NULL) {
1131 appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
1132 NETSNMP_DS_LIB_APPTYPE);
1133 }
1134
1135 /*
1136 * save the VACM MIB
1137 */
1138 vacm_save("vacm", appname);
1139 return SNMPERR_SUCCESS;
1140 }
1141
1142 /*
1143 * returns 1 if vacm has *any* (non-built-in) configuration entries,
1144 * regardless of whether or not there is enough to make a decision,
1145 * else return 0
1146 */
1147 int
vacm_is_configured(void)1148 vacm_is_configured(void)
1149 {
1150 if (accessList == NULL && groupList == NULL) {
1151 return 0;
1152 }
1153 return 1;
1154 }
1155
1156 /*
1157 * backwards compatability
1158 */
1159 struct vacm_viewEntry *
vacm_getViewEntry(const char * viewName,oid * viewSubtree,size_t viewSubtreeLen,int mode)1160 vacm_getViewEntry(const char *viewName,
1161 oid * viewSubtree, size_t viewSubtreeLen, int mode)
1162 {
1163 return netsnmp_view_get( viewList, viewName, viewSubtree, viewSubtreeLen,
1164 mode);
1165 }
1166
1167 int
vacm_checkSubtree(const char * viewName,oid * viewSubtree,size_t viewSubtreeLen)1168 vacm_checkSubtree(const char *viewName,
1169 oid * viewSubtree, size_t viewSubtreeLen)
1170 {
1171 return netsnmp_view_subtree_check( viewList, viewName, viewSubtree,
1172 viewSubtreeLen);
1173 }
1174
1175 struct vacm_viewEntry *
vacm_createViewEntry(const char * viewName,oid * viewSubtree,size_t viewSubtreeLen)1176 vacm_createViewEntry(const char *viewName,
1177 oid * viewSubtree, size_t viewSubtreeLen)
1178 {
1179 return netsnmp_view_create( &viewList, viewName, viewSubtree,
1180 viewSubtreeLen);
1181 }
1182
1183 void
vacm_destroyViewEntry(const char * viewName,oid * viewSubtree,size_t viewSubtreeLen)1184 vacm_destroyViewEntry(const char *viewName,
1185 oid * viewSubtree, size_t viewSubtreeLen)
1186 {
1187 netsnmp_view_destroy( &viewList, viewName, viewSubtree, viewSubtreeLen);
1188 }
1189
1190 void
vacm_destroyAllViewEntries(void)1191 vacm_destroyAllViewEntries(void)
1192 {
1193 netsnmp_view_clear( &viewList );
1194 }
1195
1196 /*
1197 * vacm simple api
1198 */
1199
1200 int
netsnmp_vacm_simple_usm_add(const char * user,int rw,int authLevel,const char * view,oid * oidView,size_t oidViewLen,const char * context)1201 netsnmp_vacm_simple_usm_add(const char *user, int rw, int authLevel,
1202 const char *view, oid *oidView, size_t oidViewLen,
1203 const char *context)
1204 {
1205 struct vacm_viewEntry *vacmEntry = NULL;
1206 struct vacm_groupEntry *groupEntry = NULL;
1207 struct vacm_accessEntry *accessEntry = NULL;
1208 char *tmp, localContext[VACMSTRINGLEN];
1209 int exact = 1; /* exact context match */
1210
1211 if (NULL == user)
1212 return SNMPERR_GENERR;
1213
1214 if (authLevel < SNMP_SEC_LEVEL_NOAUTH ||
1215 authLevel > SNMP_SEC_LEVEL_AUTHPRIV)
1216 return SNMPERR_GENERR;
1217
1218 if (NULL != view) {
1219 /*
1220 * if we are given a view name, it is an error if
1221 * - it exists and we have an oid
1222 * - it doesn't exist and we don't have an oid
1223 */
1224 if (netsnmp_view_exists(viewList, view) != 0) {
1225 if (NULL != oidView || oidViewLen > 0) {
1226 DEBUGMSGTL(("vacm:simple_usm", "can't modify existing view"));
1227 return SNMPERR_GENERR;
1228 }
1229 } else {
1230 if (NULL == oidView || oidViewLen == 0) {
1231 DEBUGMSGTL(("vacm:simple_usm", "can't create view w/out oid"));
1232 return SNMPERR_GENERR;
1233 }
1234 /** try and create view for oid */
1235 vacmEntry = vacm_createViewEntry(view, oidView, oidViewLen);
1236 if (NULL == vacmEntry) {
1237 DEBUGMSGTL(("vacm:simple_usm", "createViewEntry failed"));
1238 return SNMPERR_GENERR;
1239 }
1240 SNMP_FREE(vacmEntry->reserved);
1241 }
1242 } else if (0 == oidViewLen || NULL == oidView) {
1243 view = "_all_"; /* no oid either, just use _all_ */
1244 } else {
1245 DEBUGMSGTL(("vacm:simple_usm", "need view name for new views"));
1246 return SNMPERR_GENERR;
1247 }
1248
1249 /*
1250 * group
1251 * grpv3user usm \"v3user\"\000prefix\000_all_\000_all_\000_all_\000\060"
1252 * vacm_createGroupEntry() also automatically inserts into group list.
1253 */
1254 groupEntry = vacm_createGroupEntry(SNMP_SEC_MODEL_USM, user);
1255 if (NULL == groupEntry) {
1256 DEBUGMSGTL(("vacm:simple_usm", "createViewEntry failed"));
1257 goto bail;
1258 }
1259 snprintf(groupEntry->groupName, sizeof(groupEntry->groupName)-2,
1260 "grp%.28s", user);
1261 for (tmp=groupEntry->groupName; *tmp; tmp++)
1262 if (!isalnum((unsigned char)(*tmp)))
1263 *tmp = '_';
1264 groupEntry->storageType = SNMP_STORAGE_PERMANENT;
1265 groupEntry->status = SNMP_ROW_ACTIVE;
1266 SNMP_FREE(groupEntry->reserved);
1267
1268 /*
1269 * access
1270 * grpv3user myctx usm noauth exact _all_ none none
1271 */
1272 if (NULL == context) {
1273 localContext[0] = 0;
1274 context = localContext;
1275 } else {
1276 /** check for wildcard in context */
1277 int contextLen = strlen(context);
1278 if ('*' == context[contextLen - 1]) {
1279 strlcpy(localContext, context, sizeof(localContext));
1280 localContext[contextLen - 1] = 0;
1281 context = localContext;
1282 exact = 2; /* not exact, have context prefix */
1283 }
1284 }
1285 accessEntry = vacm_createAccessEntry(groupEntry->groupName, context,
1286 SNMP_SEC_MODEL_USM, authLevel);
1287 if (NULL == accessEntry) {
1288 DEBUGMSGTL(("vacm:simple_usm", "createViewEntry failed"));
1289 goto bail;
1290 }
1291 strlcpy(accessEntry->views[VACM_VIEW_READ], view,
1292 sizeof(accessEntry->views[VACM_VIEW_READ]));
1293 if (0 == rw)
1294 view = "none";
1295 strlcpy(accessEntry->views[VACM_VIEW_WRITE], view,
1296 sizeof(accessEntry->views[VACM_VIEW_WRITE]));
1297 strlcpy(accessEntry->views[VACM_VIEW_NOTIFY], view,
1298 sizeof(accessEntry->views[VACM_VIEW_NOTIFY]));
1299
1300 accessEntry->contextMatch = exact;
1301 accessEntry->storageType = SNMP_STORAGE_PERMANENT;
1302 accessEntry->status = SNMP_ROW_ACTIVE;
1303 SNMP_FREE(accessEntry->reserved);
1304
1305 return SNMPERR_SUCCESS;
1306
1307 bail:
1308 if (NULL != groupEntry)
1309 vacm_destroyGroupEntry(SNMP_SEC_MODEL_USM, user);
1310
1311 if (NULL != vacmEntry)
1312 vacm_destroyViewEntry(vacmEntry->viewName+1, vacmEntry->viewSubtree,
1313 vacmEntry->viewSubtreeLen);
1314
1315 return SNMPERR_GENERR;
1316 }
1317
1318 int
netsnmp_vacm_simple_usm_del(const char * user,int authLevel,const char * view,oid * oidView,size_t oidViewLen,const char * context)1319 netsnmp_vacm_simple_usm_del(const char *user, int authLevel,
1320 const char *view, oid *oidView, size_t oidViewLen,
1321 const char *context)
1322 {
1323 char localContext[VACMSTRINGLEN];
1324 char group[VACMSTRINGLEN];
1325
1326 /*
1327 * only delete simple views (one OID) for which we have an OID.
1328 * never delete '_all_'.
1329 */
1330 if ((NULL != view) && (NULL != oidView) && (oidViewLen > 0) &&
1331 (strcmp(view, "_all_") != 0) &&
1332 (netsnmp_view_exists(viewList, view) == 1)) {
1333 vacm_destroyViewEntry(view, oidView, oidViewLen);
1334 }
1335
1336 vacm_destroyGroupEntry(SNMP_SEC_MODEL_USM, user);
1337
1338 snprintf(group, sizeof(group)-2, "grp%.28s", user);
1339 if (NULL == context) {
1340 localContext[0] = 0;
1341 context = localContext;
1342 } else {
1343 /** check for wildcard in context */
1344 int contextLen = strlen(context);
1345 if ('*' == context[contextLen - 1]) {
1346 strlcpy(localContext, context, sizeof(localContext));
1347 localContext[contextLen - 1] = 0;
1348 context = localContext;
1349 }
1350 }
1351
1352 vacm_destroyAccessEntry(group, context, SNMP_SEC_MODEL_USM, authLevel);
1353
1354 return SNMPERR_SUCCESS;
1355 }
1356