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