net-snmp 5.7
|
00001 /* Portions of this file are subject to the following copyright(s). See 00002 * the Net-SNMP's COPYING file for more details and other copyrights 00003 * that may apply: 00004 */ 00005 /* 00006 * Portions of this file are copyrighted by: 00007 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00008 * Use is subject to license terms specified in the COPYING file 00009 * distributed with the Net-SNMP package. 00010 */ 00011 00012 /* 00013 * vacm.c 00014 * 00015 * SNMPv3 View-based Access Control Model 00016 */ 00017 00018 #include <net-snmp/net-snmp-config.h> 00019 00020 #if HAVE_STDLIB_H 00021 #include <stdlib.h> 00022 #endif 00023 #if HAVE_STRING_H 00024 #include <string.h> 00025 #else 00026 #include <strings.h> 00027 #endif 00028 #if HAVE_UNISTD_H 00029 #include <unistd.h> 00030 #endif 00031 #include <sys/types.h> 00032 #include <stdio.h> 00033 #if TIME_WITH_SYS_TIME 00034 # include <sys/time.h> 00035 # include <time.h> 00036 #else 00037 # if HAVE_SYS_TIME_H 00038 # include <sys/time.h> 00039 # else 00040 # include <time.h> 00041 # endif 00042 #endif 00043 00044 #if HAVE_NETINET_IN_H 00045 #include <netinet/in.h> 00046 #endif 00047 00048 #if HAVE_DMALLOC_H 00049 #include <dmalloc.h> 00050 #endif 00051 00052 #include <net-snmp/types.h> 00053 #include <net-snmp/output_api.h> 00054 #include <net-snmp/config_api.h> 00055 00056 #include <net-snmp/library/snmp_api.h> 00057 #include <net-snmp/library/tools.h> 00058 #include <net-snmp/library/vacm.h> 00059 00060 static struct vacm_viewEntry *viewList = NULL, *viewScanPtr = NULL; 00061 static struct vacm_accessEntry *accessList = NULL, *accessScanPtr = NULL; 00062 static struct vacm_groupEntry *groupList = NULL, *groupScanPtr = NULL; 00063 00064 /* 00065 * Macro to extend view masks with 1 bits when shorter than subtree lengths 00066 * REF: vacmViewTreeFamilyMask [RFC3415], snmpNotifyFilterMask [RFC3413] 00067 */ 00068 00069 #define VIEW_MASK(viewPtr, idx, mask) \ 00070 ((idx >= viewPtr->viewMaskLen) ? mask : (viewPtr->viewMask[idx] & mask)) 00071 00077 void 00078 init_vacm(void) 00079 { 00080 /* views for access via get/set/send-notifications */ 00081 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("read"), 00082 VACM_VIEW_READ); 00083 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("write"), 00084 VACM_VIEW_WRITE); 00085 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("notify"), 00086 VACM_VIEW_NOTIFY); 00087 00088 /* views for permissions when receiving notifications */ 00089 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("log"), 00090 VACM_VIEW_LOG); 00091 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("execute"), 00092 VACM_VIEW_EXECUTE); 00093 se_add_pair_to_slist(VACM_VIEW_ENUM_NAME, strdup("net"), 00094 VACM_VIEW_NET); 00095 } 00096 00097 void 00098 vacm_save(const char *token, const char *type) 00099 { 00100 struct vacm_viewEntry *vptr; 00101 struct vacm_accessEntry *aptr; 00102 struct vacm_groupEntry *gptr; 00103 int i; 00104 00105 for (vptr = viewList; vptr != NULL; vptr = vptr->next) { 00106 if (vptr->viewStorageType == ST_NONVOLATILE) 00107 vacm_save_view(vptr, token, type); 00108 } 00109 00110 for (aptr = accessList; aptr != NULL; aptr = aptr->next) { 00111 if (aptr->storageType == ST_NONVOLATILE) { 00112 /* Store the standard views (if set) */ 00113 if ( aptr->views[VACM_VIEW_READ ][0] || 00114 aptr->views[VACM_VIEW_WRITE ][0] || 00115 aptr->views[VACM_VIEW_NOTIFY][0] ) 00116 vacm_save_access(aptr, token, type); 00117 /* Store any other (valid) access views */ 00118 for ( i=VACM_VIEW_NOTIFY+1; i<VACM_MAX_VIEWS; i++ ) { 00119 if ( aptr->views[i][0] ) 00120 vacm_save_auth_access(aptr, token, type, i); 00121 } 00122 } 00123 } 00124 00125 for (gptr = groupList; gptr != NULL; gptr = gptr->next) { 00126 if (gptr->storageType == ST_NONVOLATILE) 00127 vacm_save_group(gptr, token, type); 00128 } 00129 } 00130 00131 /* 00132 * vacm_save_view(): saves a view entry to the persistent cache 00133 */ 00134 void 00135 vacm_save_view(struct vacm_viewEntry *view, const char *token, 00136 const char *type) 00137 { 00138 char line[4096]; 00139 char *cptr; 00140 00141 memset(line, 0, sizeof(line)); 00142 snprintf(line, sizeof(line), "%s%s %d %d %d ", token, "View", 00143 view->viewStatus, view->viewStorageType, view->viewType); 00144 line[ sizeof(line)-1 ] = 0; 00145 cptr = &line[strlen(line)]; /* the NULL */ 00146 00147 cptr = 00148 read_config_save_octet_string(cptr, (u_char *) view->viewName + 1, 00149 view->viewName[0]); 00150 *cptr++ = ' '; 00151 cptr = 00152 read_config_save_objid(cptr, view->viewSubtree+1, 00153 view->viewSubtreeLen-1); 00154 *cptr++ = ' '; 00155 cptr = read_config_save_octet_string(cptr, (u_char *) view->viewMask, 00156 view->viewMaskLen); 00157 00158 read_config_store(type, line); 00159 } 00160 00161 void 00162 vacm_parse_config_view(const char *token, const char *line) 00163 { 00164 struct vacm_viewEntry view; 00165 struct vacm_viewEntry *vptr; 00166 char *viewName = (char *) &view.viewName; 00167 oid *viewSubtree = (oid *) & view.viewSubtree; 00168 u_char *viewMask; 00169 size_t len; 00170 00171 view.viewStatus = atoi(line); 00172 line = skip_token_const(line); 00173 view.viewStorageType = atoi(line); 00174 line = skip_token_const(line); 00175 view.viewType = atoi(line); 00176 line = skip_token_const(line); 00177 len = sizeof(view.viewName); 00178 line = 00179 read_config_read_octet_string(line, (u_char **) & viewName, &len); 00180 view.viewSubtreeLen = MAX_OID_LEN; 00181 line = 00182 read_config_read_objid_const(line, (oid **) & viewSubtree, 00183 &view.viewSubtreeLen); 00184 00185 vptr = 00186 vacm_createViewEntry(view.viewName, view.viewSubtree, 00187 view.viewSubtreeLen); 00188 if (!vptr) { 00189 return; 00190 } 00191 00192 vptr->viewStatus = view.viewStatus; 00193 vptr->viewStorageType = view.viewStorageType; 00194 vptr->viewType = view.viewType; 00195 viewMask = vptr->viewMask; 00196 vptr->viewMaskLen = sizeof(vptr->viewMask); 00197 line = 00198 read_config_read_octet_string(line, &viewMask, &vptr->viewMaskLen); 00199 } 00200 00201 /* 00202 * vacm_save_access(): saves an access entry to the persistent cache 00203 */ 00204 void 00205 vacm_save_access(struct vacm_accessEntry *access_entry, const char *token, 00206 const char *type) 00207 { 00208 char line[4096]; 00209 char *cptr; 00210 00211 memset(line, 0, sizeof(line)); 00212 snprintf(line, sizeof(line), "%s%s %d %d %d %d %d ", 00213 token, "Access", access_entry->status, 00214 access_entry->storageType, access_entry->securityModel, 00215 access_entry->securityLevel, access_entry->contextMatch); 00216 line[ sizeof(line)-1 ] = 0; 00217 cptr = &line[strlen(line)]; /* the NULL */ 00218 cptr = 00219 read_config_save_octet_string(cptr, 00220 (u_char *) access_entry->groupName + 1, 00221 access_entry->groupName[0] + 1); 00222 *cptr++ = ' '; 00223 cptr = 00224 read_config_save_octet_string(cptr, 00225 (u_char *) access_entry->contextPrefix + 1, 00226 access_entry->contextPrefix[0] + 1); 00227 00228 *cptr++ = ' '; 00229 cptr = read_config_save_octet_string(cptr, (u_char *) access_entry->views[VACM_VIEW_READ], 00230 strlen(access_entry->views[VACM_VIEW_READ]) + 1); 00231 *cptr++ = ' '; 00232 cptr = 00233 read_config_save_octet_string(cptr, (u_char *) access_entry->views[VACM_VIEW_WRITE], 00234 strlen(access_entry->views[VACM_VIEW_WRITE]) + 1); 00235 *cptr++ = ' '; 00236 cptr = 00237 read_config_save_octet_string(cptr, (u_char *) access_entry->views[VACM_VIEW_NOTIFY], 00238 strlen(access_entry->views[VACM_VIEW_NOTIFY]) + 1); 00239 00240 read_config_store(type, line); 00241 } 00242 00243 void 00244 vacm_save_auth_access(struct vacm_accessEntry *access_entry, 00245 const char *token, const char *type, int authtype) 00246 { 00247 char line[4096]; 00248 char *cptr; 00249 00250 memset(line, 0, sizeof(line)); 00251 snprintf(line, sizeof(line), "%s%s %d %d %d %d %d ", 00252 token, "AuthAccess", access_entry->status, 00253 access_entry->storageType, access_entry->securityModel, 00254 access_entry->securityLevel, access_entry->contextMatch); 00255 line[ sizeof(line)-1 ] = 0; 00256 cptr = &line[strlen(line)]; /* the NULL */ 00257 cptr = 00258 read_config_save_octet_string(cptr, 00259 (u_char *) access_entry->groupName + 1, 00260 access_entry->groupName[0] + 1); 00261 *cptr++ = ' '; 00262 cptr = 00263 read_config_save_octet_string(cptr, 00264 (u_char *) access_entry->contextPrefix + 1, 00265 access_entry->contextPrefix[0] + 1); 00266 00267 snprintf(cptr, sizeof(line)-(cptr-line), " %d ", authtype); 00268 while ( *cptr ) 00269 cptr++; 00270 00271 *cptr++ = ' '; 00272 cptr = read_config_save_octet_string(cptr, 00273 (u_char *)access_entry->views[authtype], 00274 strlen(access_entry->views[authtype]) + 1); 00275 00276 read_config_store(type, line); 00277 } 00278 00279 char * 00280 _vacm_parse_config_access_common(struct vacm_accessEntry **aptr, 00281 const char *line) 00282 { 00283 struct vacm_accessEntry access; 00284 char *cPrefix = (char *) &access.contextPrefix; 00285 char *gName = (char *) &access.groupName; 00286 size_t len; 00287 00288 access.status = atoi(line); 00289 line = skip_token_const(line); 00290 access.storageType = atoi(line); 00291 line = skip_token_const(line); 00292 access.securityModel = atoi(line); 00293 line = skip_token_const(line); 00294 access.securityLevel = atoi(line); 00295 line = skip_token_const(line); 00296 access.contextMatch = atoi(line); 00297 line = skip_token_const(line); 00298 len = sizeof(access.groupName); 00299 line = read_config_read_octet_string(line, (u_char **) &gName, &len); 00300 len = sizeof(access.contextPrefix); 00301 line = read_config_read_octet_string(line, (u_char **) &cPrefix, &len); 00302 00303 *aptr = vacm_getAccessEntry(access.groupName, 00304 access.contextPrefix, 00305 access.securityModel, 00306 access.securityLevel); 00307 if (!*aptr) 00308 *aptr = vacm_createAccessEntry(access.groupName, 00309 access.contextPrefix, 00310 access.securityModel, 00311 access.securityLevel); 00312 if (!*aptr) 00313 return NULL; 00314 00315 (*aptr)->status = access.status; 00316 (*aptr)->storageType = access.storageType; 00317 (*aptr)->securityModel = access.securityModel; 00318 (*aptr)->securityLevel = access.securityLevel; 00319 (*aptr)->contextMatch = access.contextMatch; 00320 return NETSNMP_REMOVE_CONST(char *, line); 00321 } 00322 00323 void 00324 vacm_parse_config_access(const char *token, const char *line) 00325 { 00326 struct vacm_accessEntry *aptr; 00327 char *readView, *writeView, *notifyView; 00328 size_t len; 00329 00330 line = _vacm_parse_config_access_common(&aptr, line); 00331 if (!line) 00332 return; 00333 00334 readView = (char *) aptr->views[VACM_VIEW_READ]; 00335 len = sizeof(aptr->views[VACM_VIEW_READ]); 00336 line = 00337 read_config_read_octet_string(line, (u_char **) & readView, &len); 00338 writeView = (char *) aptr->views[VACM_VIEW_WRITE]; 00339 len = sizeof(aptr->views[VACM_VIEW_WRITE]); 00340 line = 00341 read_config_read_octet_string(line, (u_char **) & writeView, &len); 00342 notifyView = (char *) aptr->views[VACM_VIEW_NOTIFY]; 00343 len = sizeof(aptr->views[VACM_VIEW_NOTIFY]); 00344 line = 00345 read_config_read_octet_string(line, (u_char **) & notifyView, 00346 &len); 00347 } 00348 00349 void 00350 vacm_parse_config_auth_access(const char *token, const char *line) 00351 { 00352 struct vacm_accessEntry *aptr; 00353 int authtype; 00354 char *view; 00355 size_t len; 00356 00357 line = _vacm_parse_config_access_common(&aptr, line); 00358 if (!line) 00359 return; 00360 00361 authtype = atoi(line); 00362 line = skip_token_const(line); 00363 00364 view = (char *) aptr->views[authtype]; 00365 len = sizeof(aptr->views[authtype]); 00366 line = read_config_read_octet_string(line, (u_char **) & view, &len); 00367 } 00368 00369 /* 00370 * vacm_save_group(): saves a group entry to the persistent cache 00371 */ 00372 void 00373 vacm_save_group(struct vacm_groupEntry *group_entry, const char *token, 00374 const char *type) 00375 { 00376 char line[4096]; 00377 char *cptr; 00378 00379 memset(line, 0, sizeof(line)); 00380 snprintf(line, sizeof(line), "%s%s %d %d %d ", 00381 token, "Group", group_entry->status, 00382 group_entry->storageType, group_entry->securityModel); 00383 line[ sizeof(line)-1 ] = 0; 00384 cptr = &line[strlen(line)]; /* the NULL */ 00385 00386 cptr = 00387 read_config_save_octet_string(cptr, 00388 (u_char *) group_entry->securityName + 1, 00389 group_entry->securityName[0] + 1); 00390 *cptr++ = ' '; 00391 cptr = read_config_save_octet_string(cptr, (u_char *) group_entry->groupName, 00392 strlen(group_entry->groupName) + 1); 00393 00394 read_config_store(type, line); 00395 } 00396 00397 void 00398 vacm_parse_config_group(const char *token, const char *line) 00399 { 00400 struct vacm_groupEntry group; 00401 struct vacm_groupEntry *gptr; 00402 char *securityName = (char *) &group.securityName; 00403 char *groupName; 00404 size_t len; 00405 00406 group.status = atoi(line); 00407 line = skip_token_const(line); 00408 group.storageType = atoi(line); 00409 line = skip_token_const(line); 00410 group.securityModel = atoi(line); 00411 line = skip_token_const(line); 00412 len = sizeof(group.securityName); 00413 line = 00414 read_config_read_octet_string(line, (u_char **) & securityName, 00415 &len); 00416 00417 gptr = vacm_createGroupEntry(group.securityModel, group.securityName); 00418 if (!gptr) 00419 return; 00420 00421 gptr->status = group.status; 00422 gptr->storageType = group.storageType; 00423 groupName = (char *) gptr->groupName; 00424 len = sizeof(group.groupName); 00425 line = 00426 read_config_read_octet_string(line, (u_char **) & groupName, &len); 00427 } 00428 00429 struct vacm_viewEntry * 00430 netsnmp_view_get(struct vacm_viewEntry *head, const char *viewName, 00431 oid * viewSubtree, size_t viewSubtreeLen, int mode) 00432 { 00433 struct vacm_viewEntry *vp, *vpret = NULL; 00434 char view[VACMSTRINGLEN]; 00435 int found, glen; 00436 int count=0; 00437 00438 glen = (int) strlen(viewName); 00439 if (glen < 0 || glen >= VACM_MAX_STRING) 00440 return NULL; 00441 view[0] = glen; 00442 strcpy(view + 1, viewName); 00443 for (vp = head; vp; vp = vp->next) { 00444 if (!memcmp(view, vp->viewName, glen + 1) 00445 && viewSubtreeLen >= (vp->viewSubtreeLen - 1)) { 00446 int mask = 0x80; 00447 unsigned int oidpos, maskpos = 0; 00448 found = 1; 00449 00450 for (oidpos = 0; 00451 found && oidpos < vp->viewSubtreeLen - 1; 00452 oidpos++) { 00453 if (mode==VACM_MODE_IGNORE_MASK || (VIEW_MASK(vp, maskpos, mask) != 0)) { 00454 if (viewSubtree[oidpos] != 00455 vp->viewSubtree[oidpos + 1]) 00456 found = 0; 00457 } 00458 if (mask == 1) { 00459 mask = 0x80; 00460 maskpos++; 00461 } else 00462 mask >>= 1; 00463 } 00464 00465 if (found) { 00466 /* 00467 * match successful, keep this node if its longer than 00468 * the previous or (equal and lexicographically greater 00469 * than the previous). 00470 */ 00471 count++; 00472 if (mode == VACM_MODE_CHECK_SUBTREE) { 00473 vpret = vp; 00474 } else if (vpret == NULL 00475 || vp->viewSubtreeLen > vpret->viewSubtreeLen 00476 || (vp->viewSubtreeLen == vpret->viewSubtreeLen 00477 && snmp_oid_compare(vp->viewSubtree + 1, 00478 vp->viewSubtreeLen - 1, 00479 vpret->viewSubtree + 1, 00480 vpret->viewSubtreeLen - 1) > 00481 0)) { 00482 vpret = vp; 00483 } 00484 } 00485 } 00486 } 00487 DEBUGMSGTL(("vacm:getView", ", %s\n", (vpret) ? "found" : "none")); 00488 if (mode == VACM_MODE_CHECK_SUBTREE && count > 1) { 00489 return NULL; 00490 } 00491 return vpret; 00492 } 00493 00494 /*******************************************************************o-o****** 00495 * vacm_checkSubtree 00496 * 00497 * Check to see if everything within a subtree is in view, not in view, 00498 * or possibly both. 00499 * 00500 * Parameters: 00501 * *viewName - Name of view to check 00502 * *viewSubtree - OID of subtree 00503 * viewSubtreeLen - length of subtree OID 00504 * 00505 * Returns: 00506 * VACM_SUCCESS The OID is included in the view. 00507 * VACM_NOTINVIEW If no entry in the view list includes the 00508 * provided OID, or the OID is explicitly excluded 00509 * from the view. 00510 * VACM_SUBTREE_UNKNOWN The entire subtree has both allowed and disallowed 00511 * portions. 00512 */ 00513 int 00514 netsnmp_view_subtree_check(struct vacm_viewEntry *head, const char *viewName, 00515 oid * viewSubtree, size_t viewSubtreeLen) 00516 { 00517 struct vacm_viewEntry *vp, *vpShorter = NULL, *vpLonger = NULL; 00518 char view[VACMSTRINGLEN]; 00519 int found, glen; 00520 00521 glen = (int) strlen(viewName); 00522 if (glen < 0 || glen >= VACM_MAX_STRING) 00523 return VACM_NOTINVIEW; 00524 view[0] = glen; 00525 strcpy(view + 1, viewName); 00526 DEBUGMSGTL(("9:vacm:checkSubtree", "view %s\n", viewName)); 00527 for (vp = head; vp; vp = vp->next) { 00528 if (!memcmp(view, vp->viewName, glen + 1)) { 00529 /* 00530 * If the subtree defined in the view is shorter than or equal 00531 * to the subtree we are comparing, then it might envelop the 00532 * subtree we are comparing against. 00533 */ 00534 if (viewSubtreeLen >= (vp->viewSubtreeLen - 1)) { 00535 int mask = 0x80; 00536 unsigned int oidpos, maskpos = 0; 00537 found = 1; 00538 00539 /* 00540 * check the mask 00541 */ 00542 for (oidpos = 0; 00543 found && oidpos < vp->viewSubtreeLen - 1; 00544 oidpos++) { 00545 if (VIEW_MASK(vp, maskpos, mask) != 0) { 00546 if (viewSubtree[oidpos] != 00547 vp->viewSubtree[oidpos + 1]) 00548 found = 0; 00549 } 00550 if (mask == 1) { 00551 mask = 0x80; 00552 maskpos++; 00553 } else 00554 mask >>= 1; 00555 } 00556 00557 if (found) { 00558 /* 00559 * match successful, keep this node if it's longer than 00560 * the previous or (equal and lexicographically greater 00561 * than the previous). 00562 */ 00563 DEBUGMSGTL(("9:vacm:checkSubtree", " %s matched?\n", vp->viewName)); 00564 00565 if (vpShorter == NULL 00566 || vp->viewSubtreeLen > vpShorter->viewSubtreeLen 00567 || (vp->viewSubtreeLen == vpShorter->viewSubtreeLen 00568 && snmp_oid_compare(vp->viewSubtree + 1, 00569 vp->viewSubtreeLen - 1, 00570 vpShorter->viewSubtree + 1, 00571 vpShorter->viewSubtreeLen - 1) > 00572 0)) { 00573 vpShorter = vp; 00574 } 00575 } 00576 } 00577 /* 00578 * If the subtree defined in the view is longer than the 00579 * subtree we are comparing, then it might ambiguate our 00580 * response. 00581 */ 00582 else { 00583 int mask = 0x80; 00584 unsigned int oidpos, maskpos = 0; 00585 found = 1; 00586 00587 /* 00588 * check the mask up to the length of the provided subtree 00589 */ 00590 for (oidpos = 0; 00591 found && oidpos < viewSubtreeLen; 00592 oidpos++) { 00593 if (VIEW_MASK(vp, maskpos, mask) != 0) { 00594 if (viewSubtree[oidpos] != 00595 vp->viewSubtree[oidpos + 1]) 00596 found = 0; 00597 } 00598 if (mask == 1) { 00599 mask = 0x80; 00600 maskpos++; 00601 } else 00602 mask >>= 1; 00603 } 00604 00605 if (found) { 00606 /* 00607 * match successful. If we already found a match 00608 * with a different view type, then parts of the subtree 00609 * are included and others are excluded, so return UNKNOWN. 00610 */ 00611 DEBUGMSGTL(("9:vacm:checkSubtree", " %s matched?\n", vp->viewName)); 00612 if (vpLonger != NULL 00613 && (vpLonger->viewType != vp->viewType)) { 00614 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "unknown")); 00615 return VACM_SUBTREE_UNKNOWN; 00616 } 00617 else if (vpLonger == NULL) { 00618 vpLonger = vp; 00619 } 00620 } 00621 } 00622 } 00623 } 00624 DEBUGMSGTL(("9:vacm:checkSubtree", " %s matched\n", viewName)); 00625 00626 /* 00627 * If we found a matching view subtree with a longer OID than the provided 00628 * OID, check to see if its type is consistent with any matching view 00629 * subtree we may have found with a shorter OID than the provided OID. 00630 * 00631 * The view type of the longer OID is inconsistent with the shorter OID in 00632 * either of these two cases: 00633 * 1) No matching shorter OID was found and the view type of the longer 00634 * OID is INCLUDE. 00635 * 2) A matching shorter ID was found and its view type doesn't match 00636 * the view type of the longer OID. 00637 */ 00638 if (vpLonger != NULL) { 00639 if ((!vpShorter && vpLonger->viewType != SNMP_VIEW_EXCLUDED) 00640 || (vpShorter && vpLonger->viewType != vpShorter->viewType)) { 00641 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "unknown")); 00642 return VACM_SUBTREE_UNKNOWN; 00643 } 00644 } 00645 00646 if (vpShorter && vpShorter->viewType != SNMP_VIEW_EXCLUDED) { 00647 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "included")); 00648 return VACM_SUCCESS; 00649 } 00650 00651 DEBUGMSGTL(("vacm:checkSubtree", ", %s\n", "excluded")); 00652 return VACM_NOTINVIEW; 00653 } 00654 00655 void 00656 vacm_scanViewInit(void) 00657 { 00658 viewScanPtr = viewList; 00659 } 00660 00661 struct vacm_viewEntry * 00662 vacm_scanViewNext(void) 00663 { 00664 struct vacm_viewEntry *returnval = viewScanPtr; 00665 if (viewScanPtr) 00666 viewScanPtr = viewScanPtr->next; 00667 return returnval; 00668 } 00669 00670 struct vacm_viewEntry * 00671 netsnmp_view_create(struct vacm_viewEntry **head, const char *viewName, 00672 oid * viewSubtree, size_t viewSubtreeLen) 00673 { 00674 struct vacm_viewEntry *vp, *lp, *op = NULL; 00675 int cmp, cmp2, glen; 00676 00677 glen = (int) strlen(viewName); 00678 if (glen < 0 || glen >= VACM_MAX_STRING) 00679 return NULL; 00680 vp = (struct vacm_viewEntry *) calloc(1, 00681 sizeof(struct vacm_viewEntry)); 00682 if (vp == NULL) 00683 return NULL; 00684 vp->reserved = 00685 (struct vacm_viewEntry *) calloc(1, sizeof(struct vacm_viewEntry)); 00686 if (vp->reserved == NULL) { 00687 free(vp); 00688 return NULL; 00689 } 00690 00691 vp->viewName[0] = glen; 00692 strcpy(vp->viewName + 1, viewName); 00693 vp->viewSubtree[0] = viewSubtreeLen; 00694 memcpy(vp->viewSubtree + 1, viewSubtree, viewSubtreeLen * sizeof(oid)); 00695 vp->viewSubtreeLen = viewSubtreeLen + 1; 00696 00697 lp = *head; 00698 while (lp) { 00699 cmp = memcmp(lp->viewName, vp->viewName, glen + 1); 00700 cmp2 = snmp_oid_compare(lp->viewSubtree, lp->viewSubtreeLen, 00701 vp->viewSubtree, vp->viewSubtreeLen); 00702 if (cmp == 0 && cmp2 > 0) 00703 break; 00704 if (cmp > 0) 00705 break; 00706 op = lp; 00707 lp = lp->next; 00708 } 00709 vp->next = lp; 00710 if (op) 00711 op->next = vp; 00712 else 00713 *head = vp; 00714 return vp; 00715 } 00716 00717 void 00718 netsnmp_view_destroy(struct vacm_viewEntry **head, const char *viewName, 00719 oid * viewSubtree, size_t viewSubtreeLen) 00720 { 00721 struct vacm_viewEntry *vp, *lastvp = NULL; 00722 00723 if ((*head) && !strcmp((*head)->viewName + 1, viewName) 00724 && (*head)->viewSubtreeLen == viewSubtreeLen 00725 && !memcmp((char *) (*head)->viewSubtree, (char *) viewSubtree, 00726 viewSubtreeLen * sizeof(oid))) { 00727 vp = (*head); 00728 (*head) = (*head)->next; 00729 } else { 00730 for (vp = (*head); vp; vp = vp->next) { 00731 if (!strcmp(vp->viewName + 1, viewName) 00732 && vp->viewSubtreeLen == viewSubtreeLen 00733 && !memcmp((char *) vp->viewSubtree, (char *) viewSubtree, 00734 viewSubtreeLen * sizeof(oid))) 00735 break; 00736 lastvp = vp; 00737 } 00738 if (!vp || !lastvp) 00739 return; 00740 lastvp->next = vp->next; 00741 } 00742 if (vp->reserved) 00743 free(vp->reserved); 00744 free(vp); 00745 return; 00746 } 00747 00748 void 00749 netsnmp_view_clear(struct vacm_viewEntry **head) 00750 { 00751 struct vacm_viewEntry *vp; 00752 while ((vp = (*head))) { 00753 (*head) = vp->next; 00754 if (vp->reserved) 00755 free(vp->reserved); 00756 free(vp); 00757 } 00758 } 00759 00760 struct vacm_groupEntry * 00761 vacm_getGroupEntry(int securityModel, const char *securityName) 00762 { 00763 struct vacm_groupEntry *vp; 00764 char secname[VACMSTRINGLEN]; 00765 int glen; 00766 00767 glen = (int) strlen(securityName); 00768 if (glen < 0 || glen >= VACM_MAX_STRING) 00769 return NULL; 00770 secname[0] = glen; 00771 strcpy(secname + 1, securityName); 00772 00773 for (vp = groupList; vp; vp = vp->next) { 00774 if ((securityModel == vp->securityModel 00775 || vp->securityModel == SNMP_SEC_MODEL_ANY) 00776 && !memcmp(vp->securityName, secname, glen + 1)) 00777 return vp; 00778 } 00779 return NULL; 00780 } 00781 00782 void 00783 vacm_scanGroupInit(void) 00784 { 00785 groupScanPtr = groupList; 00786 } 00787 00788 struct vacm_groupEntry * 00789 vacm_scanGroupNext(void) 00790 { 00791 struct vacm_groupEntry *returnval = groupScanPtr; 00792 if (groupScanPtr) 00793 groupScanPtr = groupScanPtr->next; 00794 return returnval; 00795 } 00796 00797 struct vacm_groupEntry * 00798 vacm_createGroupEntry(int securityModel, const char *securityName) 00799 { 00800 struct vacm_groupEntry *gp, *lg, *og; 00801 int cmp, glen; 00802 00803 glen = (int) strlen(securityName); 00804 if (glen < 0 || glen >= VACM_MAX_STRING) 00805 return NULL; 00806 gp = (struct vacm_groupEntry *) calloc(1, 00807 sizeof(struct vacm_groupEntry)); 00808 if (gp == NULL) 00809 return NULL; 00810 gp->reserved = 00811 (struct vacm_groupEntry *) calloc(1, 00812 sizeof(struct vacm_groupEntry)); 00813 if (gp->reserved == NULL) { 00814 free(gp); 00815 return NULL; 00816 } 00817 00818 gp->securityModel = securityModel; 00819 gp->securityName[0] = glen; 00820 strcpy(gp->securityName + 1, securityName); 00821 00822 lg = groupList; 00823 og = NULL; 00824 while (lg) { 00825 if (lg->securityModel > securityModel) 00826 break; 00827 if (lg->securityModel == securityModel && 00828 (cmp = 00829 memcmp(lg->securityName, gp->securityName, glen + 1)) > 0) 00830 break; 00831 /* 00832 * if (lg->securityModel == securityModel && cmp == 0) abort(); 00833 */ 00834 og = lg; 00835 lg = lg->next; 00836 } 00837 gp->next = lg; 00838 if (og == NULL) 00839 groupList = gp; 00840 else 00841 og->next = gp; 00842 return gp; 00843 } 00844 00845 #ifndef NETSNMP_NO_WRITE_SUPPORT 00846 void 00847 vacm_destroyGroupEntry(int securityModel, const char *securityName) 00848 { 00849 struct vacm_groupEntry *vp, *lastvp = NULL; 00850 00851 if (groupList && groupList->securityModel == securityModel 00852 && !strcmp(groupList->securityName + 1, securityName)) { 00853 vp = groupList; 00854 groupList = groupList->next; 00855 } else { 00856 for (vp = groupList; vp; vp = vp->next) { 00857 if (vp->securityModel == securityModel 00858 && !strcmp(vp->securityName + 1, securityName)) 00859 break; 00860 lastvp = vp; 00861 } 00862 if (!vp || !lastvp) 00863 return; 00864 lastvp->next = vp->next; 00865 } 00866 if (vp->reserved) 00867 free(vp->reserved); 00868 free(vp); 00869 return; 00870 } 00871 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 00872 00873 void 00874 vacm_destroyAllGroupEntries(void) 00875 { 00876 struct vacm_groupEntry *gp; 00877 while ((gp = groupList)) { 00878 groupList = gp->next; 00879 if (gp->reserved) 00880 free(gp->reserved); 00881 free(gp); 00882 } 00883 } 00884 00885 struct vacm_accessEntry * 00886 _vacm_choose_best( struct vacm_accessEntry *current, 00887 struct vacm_accessEntry *candidate) 00888 { 00889 /* 00890 * RFC 3415: vacmAccessTable: 00891 * 2) if this set has [more than] one member, ... 00892 * it comes down to deciding how to weight the 00893 * preferences between ContextPrefixes, 00894 * SecurityModels, and SecurityLevels 00895 */ 00896 if (( !current ) || 00897 /* a) if the subset of entries with securityModel 00898 * matching the securityModel in the message is 00899 * not empty, then discard the rest 00900 */ 00901 ( current->securityModel == SNMP_SEC_MODEL_ANY && 00902 candidate->securityModel != SNMP_SEC_MODEL_ANY ) || 00903 /* b) if the subset of entries with vacmAccessContextPrefix 00904 * matching the contextName in the message is 00905 * not empty, then discard the rest 00906 */ 00907 ( current->contextMatch == CONTEXT_MATCH_PREFIX && 00908 candidate->contextMatch == CONTEXT_MATCH_EXACT ) || 00909 /* c) discard all entries with ContextPrefixes shorter 00910 * than the longest one remaining in the set 00911 */ 00912 ( current->contextMatch == CONTEXT_MATCH_PREFIX && 00913 current->contextPrefix[0] < candidate->contextPrefix[0] ) || 00914 /* d) select the entry with the highest securityLevel 00915 */ 00916 ( current->securityLevel < candidate->securityLevel )) { 00917 00918 return candidate; 00919 } 00920 00921 return current; 00922 } 00923 00924 struct vacm_accessEntry * 00925 vacm_getAccessEntry(const char *groupName, 00926 const char *contextPrefix, 00927 int securityModel, int securityLevel) 00928 { 00929 struct vacm_accessEntry *vp, *best=NULL; 00930 char group[VACMSTRINGLEN]; 00931 char context[VACMSTRINGLEN]; 00932 int glen, clen; 00933 00934 glen = (int) strlen(groupName); 00935 if (glen < 0 || glen >= VACM_MAX_STRING) 00936 return NULL; 00937 clen = (int) strlen(contextPrefix); 00938 if (clen < 0 || clen >= VACM_MAX_STRING) 00939 return NULL; 00940 00941 group[0] = glen; 00942 strcpy(group + 1, groupName); 00943 context[0] = clen; 00944 strcpy(context + 1, contextPrefix); 00945 for (vp = accessList; vp; vp = vp->next) { 00946 if ((securityModel == vp->securityModel 00947 || vp->securityModel == SNMP_SEC_MODEL_ANY) 00948 && securityLevel >= vp->securityLevel 00949 && !memcmp(vp->groupName, group, glen + 1) 00950 && 00951 ((vp->contextMatch == CONTEXT_MATCH_EXACT 00952 && clen == vp->contextPrefix[0] 00953 && (memcmp(vp->contextPrefix, context, clen + 1) == 0)) 00954 || (vp->contextMatch == CONTEXT_MATCH_PREFIX 00955 && clen >= vp->contextPrefix[0] 00956 && (memcmp(vp->contextPrefix + 1, context + 1, 00957 vp->contextPrefix[0]) == 0)))) 00958 best = _vacm_choose_best( best, vp ); 00959 } 00960 return best; 00961 } 00962 00963 void 00964 vacm_scanAccessInit(void) 00965 { 00966 accessScanPtr = accessList; 00967 } 00968 00969 struct vacm_accessEntry * 00970 vacm_scanAccessNext(void) 00971 { 00972 struct vacm_accessEntry *returnval = accessScanPtr; 00973 if (accessScanPtr) 00974 accessScanPtr = accessScanPtr->next; 00975 return returnval; 00976 } 00977 00978 struct vacm_accessEntry * 00979 vacm_createAccessEntry(const char *groupName, 00980 const char *contextPrefix, 00981 int securityModel, int securityLevel) 00982 { 00983 struct vacm_accessEntry *vp, *lp, *op = NULL; 00984 int cmp, glen, clen; 00985 00986 glen = (int) strlen(groupName); 00987 if (glen < 0 || glen >= VACM_MAX_STRING) 00988 return NULL; 00989 clen = (int) strlen(contextPrefix); 00990 if (clen < 0 || clen >= VACM_MAX_STRING) 00991 return NULL; 00992 vp = (struct vacm_accessEntry *) calloc(1, 00993 sizeof(struct 00994 vacm_accessEntry)); 00995 if (vp == NULL) 00996 return NULL; 00997 vp->reserved = 00998 (struct vacm_accessEntry *) calloc(1, 00999 sizeof(struct 01000 vacm_accessEntry)); 01001 if (vp->reserved == NULL) { 01002 free(vp); 01003 return NULL; 01004 } 01005 01006 vp->securityModel = securityModel; 01007 vp->securityLevel = securityLevel; 01008 vp->groupName[0] = glen; 01009 strcpy(vp->groupName + 1, groupName); 01010 vp->contextPrefix[0] = clen; 01011 strcpy(vp->contextPrefix + 1, contextPrefix); 01012 01013 lp = accessList; 01014 while (lp) { 01015 cmp = memcmp(lp->groupName, vp->groupName, glen + 1); 01016 if (cmp > 0) 01017 break; 01018 if (cmp < 0) 01019 goto next; 01020 cmp = memcmp(lp->contextPrefix, vp->contextPrefix, clen + 1); 01021 if (cmp > 0) 01022 break; 01023 if (cmp < 0) 01024 goto next; 01025 if (lp->securityModel > securityModel) 01026 break; 01027 if (lp->securityModel < securityModel) 01028 goto next; 01029 if (lp->securityLevel > securityLevel) 01030 break; 01031 next: 01032 op = lp; 01033 lp = lp->next; 01034 } 01035 vp->next = lp; 01036 if (op == NULL) 01037 accessList = vp; 01038 else 01039 op->next = vp; 01040 return vp; 01041 } 01042 01043 #ifndef NETSNMP_NO_WRITE_SUPPORT 01044 void 01045 vacm_destroyAccessEntry(const char *groupName, 01046 const char *contextPrefix, 01047 int securityModel, int securityLevel) 01048 { 01049 struct vacm_accessEntry *vp, *lastvp = NULL; 01050 01051 if (accessList && accessList->securityModel == securityModel 01052 && accessList->securityLevel == securityLevel 01053 && !strcmp(accessList->groupName + 1, groupName) 01054 && !strcmp(accessList->contextPrefix + 1, contextPrefix)) { 01055 vp = accessList; 01056 accessList = accessList->next; 01057 } else { 01058 for (vp = accessList; vp; vp = vp->next) { 01059 if (vp->securityModel == securityModel 01060 && vp->securityLevel == securityLevel 01061 && !strcmp(vp->groupName + 1, groupName) 01062 && !strcmp(vp->contextPrefix + 1, contextPrefix)) 01063 break; 01064 lastvp = vp; 01065 } 01066 if (!vp || !lastvp) 01067 return; 01068 lastvp->next = vp->next; 01069 } 01070 if (vp->reserved) 01071 free(vp->reserved); 01072 free(vp); 01073 return; 01074 } 01075 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 01076 01077 void 01078 vacm_destroyAllAccessEntries(void) 01079 { 01080 struct vacm_accessEntry *ap; 01081 while ((ap = accessList)) { 01082 accessList = ap->next; 01083 if (ap->reserved) 01084 free(ap->reserved); 01085 free(ap); 01086 } 01087 } 01088 01089 int 01090 store_vacm(int majorID, int minorID, void *serverarg, void *clientarg) 01091 { 01092 /* 01093 * figure out our application name 01094 */ 01095 char *appname = (char *) clientarg; 01096 if (appname == NULL) { 01097 appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 01098 NETSNMP_DS_LIB_APPTYPE); 01099 } 01100 01101 /* 01102 * save the VACM MIB 01103 */ 01104 vacm_save("vacm", appname); 01105 return SNMPERR_SUCCESS; 01106 } 01107 01108 /* 01109 * returns 1 if vacm has *any* (non-built-in) configuration entries, 01110 * regardless of whether or not there is enough to make a decision, 01111 * else return 0 01112 */ 01113 int 01114 vacm_is_configured(void) 01115 { 01116 if (accessList == NULL && groupList == NULL) { 01117 return 0; 01118 } 01119 return 1; 01120 } 01121 01122 /* 01123 * backwards compatability 01124 */ 01125 struct vacm_viewEntry * 01126 vacm_getViewEntry(const char *viewName, 01127 oid * viewSubtree, size_t viewSubtreeLen, int mode) 01128 { 01129 return netsnmp_view_get( viewList, viewName, viewSubtree, viewSubtreeLen, 01130 mode); 01131 } 01132 01133 int 01134 vacm_checkSubtree(const char *viewName, 01135 oid * viewSubtree, size_t viewSubtreeLen) 01136 { 01137 return netsnmp_view_subtree_check( viewList, viewName, viewSubtree, 01138 viewSubtreeLen); 01139 } 01140 01141 struct vacm_viewEntry * 01142 vacm_createViewEntry(const char *viewName, 01143 oid * viewSubtree, size_t viewSubtreeLen) 01144 { 01145 return netsnmp_view_create( &viewList, viewName, viewSubtree, 01146 viewSubtreeLen); 01147 } 01148 01149 #ifndef NETSNMP_NO_WRITE_SUPPORT 01150 void 01151 vacm_destroyViewEntry(const char *viewName, 01152 oid * viewSubtree, size_t viewSubtreeLen) 01153 { 01154 netsnmp_view_destroy( &viewList, viewName, viewSubtree, viewSubtreeLen); 01155 } 01156 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 01157 01158 void 01159 vacm_destroyAllViewEntries(void) 01160 { 01161 netsnmp_view_clear( &viewList ); 01162 } 01163