/src/net-snmp/agent/mibgroup/mibII/vacm_conf.c
Line | Count | Source |
1 | | /* |
2 | | * SNMPv3 View-based Access Control Model |
3 | | */ |
4 | | /* Portions of this file are subject to the following copyright(s). See |
5 | | * the Net-SNMP's COPYING file for more details and other copyrights |
6 | | * that may apply: |
7 | | */ |
8 | | /* |
9 | | * Portions of this file are copyrighted by: |
10 | | * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. |
11 | | * Use is subject to license terms specified in the COPYING file |
12 | | * distributed with the Net-SNMP package. |
13 | | * |
14 | | * Portions of this file are copyrighted by: |
15 | | * Copyright (c) 2016 VMware, Inc. All rights reserved. |
16 | | * Use is subject to license terms specified in the COPYING file |
17 | | * distributed with the Net-SNMP package. |
18 | | */ |
19 | | |
20 | | #include <net-snmp/net-snmp-config.h> |
21 | | |
22 | | #ifdef HAVE_STDLIB_H |
23 | | #include <stdlib.h> |
24 | | #endif |
25 | | #ifdef HAVE_UNISTD_H |
26 | | #include <unistd.h> |
27 | | #endif |
28 | | #ifdef HAVE_STRING_H |
29 | | #include <string.h> |
30 | | #else |
31 | | #include <strings.h> |
32 | | #endif |
33 | | #ifdef HAVE_MALLOC_H |
34 | | #include <malloc.h> |
35 | | #endif |
36 | | #include <ctype.h> |
37 | | #include <sys/types.h> |
38 | | #ifdef HAVE_NETINET_IN_H |
39 | | #include <netinet/in.h> |
40 | | #endif |
41 | | #ifdef HAVE_ARPA_INET_H |
42 | | #include <arpa/inet.h> |
43 | | #endif |
44 | | |
45 | | #ifdef HAVE_NETDB_H |
46 | | #include <netdb.h> |
47 | | #endif |
48 | | |
49 | | #include <net-snmp/net-snmp-includes.h> |
50 | | #include <net-snmp/agent/net-snmp-agent-includes.h> |
51 | | |
52 | | #include <net-snmp/agent/agent_callbacks.h> |
53 | | #include <net-snmp/library/snmpTCPDomain.h> |
54 | | #include <net-snmp/library/snmpTCPIPv6Domain.h> |
55 | | #include <net-snmp/library/snmpUDPDomain.h> |
56 | | #include <net-snmp/library/snmpUDPIPv6Domain.h> |
57 | | #include <net-snmp/library/snmpUnixDomain.h> |
58 | | #include "vacm_conf.h" |
59 | | |
60 | | #include "snmpd.h" |
61 | | |
62 | | /** |
63 | | * Registers the VACM token handlers for inserting rows into the vacm tables. |
64 | | * These tokens will be recognised by both 'snmpd' and 'snmptrapd'. |
65 | | */ |
66 | | void |
67 | 3.34k | init_vacm_config_tokens(void) { |
68 | 3.34k | snmpd_register_config_handler("group", vacm_parse_group, |
69 | 3.34k | vacm_free_group, |
70 | 3.34k | "name v1|v2c|usm|... security"); |
71 | 3.34k | snmpd_register_config_handler("access", vacm_parse_access, |
72 | 3.34k | vacm_free_access, |
73 | 3.34k | "name context model level prefix read write notify"); |
74 | 3.34k | snmpd_register_config_handler("setaccess", vacm_parse_setaccess, |
75 | 3.34k | vacm_free_access, |
76 | 3.34k | "name context model level prefix viewname viewval"); |
77 | 3.34k | snmpd_register_config_handler("view", vacm_parse_view, vacm_free_view, |
78 | 3.34k | "name type subtree [mask]"); |
79 | 3.34k | snmpd_register_const_config_handler("vacmView", |
80 | 3.34k | vacm_parse_config_view, NULL, NULL); |
81 | 3.34k | snmpd_register_const_config_handler("vacmGroup", |
82 | 3.34k | vacm_parse_config_group, |
83 | 3.34k | NULL, NULL); |
84 | 3.34k | snmpd_register_const_config_handler("vacmAccess", |
85 | 3.34k | vacm_parse_config_access, |
86 | 3.34k | NULL, NULL); |
87 | 3.34k | snmpd_register_const_config_handler("vacmAuthAccess", |
88 | 3.34k | vacm_parse_config_auth_access, |
89 | 3.34k | NULL, NULL); |
90 | | |
91 | | /* easy community auth handler */ |
92 | 3.34k | snmpd_register_config_handler("authcommunity", |
93 | 3.34k | vacm_parse_authcommunity, |
94 | 3.34k | NULL, "authtype1,authtype2 community [default|hostname|network/bits [oid|-V view [context]]]"); |
95 | | |
96 | | /* easy user auth handler */ |
97 | 3.34k | snmpd_register_config_handler("authuser", |
98 | 3.34k | vacm_parse_authuser, |
99 | 3.34k | NULL, "authtype1,authtype2 [-s secmodel] user [noauth|auth|priv [oid|-V view [context]]]"); |
100 | | /* easy group auth handler */ |
101 | 3.34k | snmpd_register_config_handler("authgroup", |
102 | 3.34k | vacm_parse_authuser, |
103 | 3.34k | NULL, "authtype1,authtype2 [-s secmodel] group [noauth|auth|priv [oid|-V view [context]]]"); |
104 | | |
105 | 3.34k | snmpd_register_config_handler("authaccess", vacm_parse_authaccess, |
106 | 3.34k | vacm_free_access, |
107 | 3.34k | "name authtype1,authtype2 [-s secmodel] group view [noauth|auth|priv [context|context*]]"); |
108 | | |
109 | | /* |
110 | | * Define standard views "_all_" and "_none_" |
111 | | */ |
112 | 3.34k | snmp_register_callback(SNMP_CALLBACK_LIBRARY, |
113 | 3.34k | SNMP_CALLBACK_PRE_READ_CONFIG, |
114 | 3.34k | vacm_standard_views, NULL); |
115 | 3.34k | snmp_register_callback(SNMP_CALLBACK_LIBRARY, |
116 | 3.34k | SNMP_CALLBACK_POST_READ_CONFIG, |
117 | 3.34k | vacm_warn_if_not_configured, NULL); |
118 | 3.34k | } |
119 | | |
120 | | /** |
121 | | * Registers the easier-to-use VACM token handlers for quick access rules. |
122 | | * These tokens will only be recognised by 'snmpd'. |
123 | | */ |
124 | | void |
125 | 3.34k | init_vacm_snmpd_easy_tokens(void) { |
126 | 3.34k | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
127 | 3.34k | snmpd_register_config_handler("rwcommunity", vacm_parse_rwcommunity, NULL, |
128 | 3.34k | "community [default|hostname|network/bits [oid|-V view [context]]]"); |
129 | 3.34k | snmpd_register_config_handler("rocommunity", vacm_parse_rocommunity, NULL, |
130 | 3.34k | "community [default|hostname|network/bits [oid|-V view [context]]]"); |
131 | 3.34k | #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN |
132 | 3.34k | snmpd_register_config_handler("rwcommunity6", vacm_parse_rwcommunity6, NULL, |
133 | 3.34k | "community [default|hostname|network/bits [oid|-V view [context]]]"); |
134 | 3.34k | snmpd_register_config_handler("rocommunity6", vacm_parse_rocommunity6, NULL, |
135 | 3.34k | "community [default|hostname|network/bits [oid|-V view [context]]]"); |
136 | 3.34k | #endif |
137 | 3.34k | #endif /* support for community based SNMP */ |
138 | 3.34k | snmpd_register_config_handler("rwuser", vacm_parse_rwuser, NULL, |
139 | 3.34k | "user [noauth|auth|priv [oid|-V view [context]]]"); |
140 | 3.34k | snmpd_register_config_handler("rouser", vacm_parse_rouser, NULL, |
141 | 3.34k | "user [noauth|auth|priv [oid|-V view [context]]]"); |
142 | 3.34k | } |
143 | | |
144 | | void |
145 | | init_vacm_conf(void) |
146 | 3.34k | { |
147 | 3.34k | init_vacm_config_tokens(); |
148 | 3.34k | init_vacm_snmpd_easy_tokens(); |
149 | | /* |
150 | | * register ourselves to handle access control ('snmpd' only) |
151 | | */ |
152 | 3.34k | snmp_register_callback(SNMP_CALLBACK_APPLICATION, |
153 | 3.34k | SNMPD_CALLBACK_ACM_CHECK, vacm_in_view_callback, |
154 | 3.34k | NULL); |
155 | 3.34k | snmp_register_callback(SNMP_CALLBACK_APPLICATION, |
156 | 3.34k | SNMPD_CALLBACK_ACM_CHECK_INITIAL, |
157 | 3.34k | vacm_in_view_callback, NULL); |
158 | 3.34k | snmp_register_callback(SNMP_CALLBACK_APPLICATION, |
159 | 3.34k | SNMPD_CALLBACK_ACM_CHECK_SUBTREE, |
160 | 3.34k | vacm_in_view_callback, NULL); |
161 | 3.34k | } |
162 | | |
163 | | |
164 | | |
165 | | void |
166 | | vacm_parse_group(const char *token, char *param) |
167 | 0 | { |
168 | 0 | char group[VACMSTRINGLEN], model[VACMSTRINGLEN], security[VACMSTRINGLEN]; |
169 | 0 | int imodel; |
170 | 0 | struct vacm_groupEntry *gp = NULL; |
171 | 0 | char *st; |
172 | |
|
173 | 0 | st = copy_nword(param, group, sizeof(group)-1); |
174 | 0 | st = copy_nword(st, model, sizeof(model)-1); |
175 | 0 | st = copy_nword(st, security, sizeof(security)-1); |
176 | |
|
177 | 0 | if (group[0] == 0) { |
178 | 0 | config_perror("missing GROUP parameter"); |
179 | 0 | return; |
180 | 0 | } |
181 | 0 | if (model[0] == 0) { |
182 | 0 | config_perror("missing MODEL parameter"); |
183 | 0 | return; |
184 | 0 | } |
185 | 0 | if (security[0] == 0) { |
186 | 0 | config_perror("missing SECURITY parameter"); |
187 | 0 | return; |
188 | 0 | } |
189 | 0 | if (strcasecmp(model, "v1") == 0) |
190 | 0 | imodel = SNMP_SEC_MODEL_SNMPv1; |
191 | 0 | else if (strcasecmp(model, "v2c") == 0) |
192 | 0 | imodel = SNMP_SEC_MODEL_SNMPv2c; |
193 | 0 | else if (strcasecmp(model, "any") == 0) { |
194 | 0 | config_perror |
195 | 0 | ("bad security model \"any\" should be: v1, v2c, usm or a registered security plugin name - installing anyway"); |
196 | 0 | imodel = SNMP_SEC_MODEL_ANY; |
197 | 0 | } else { |
198 | 0 | if ((imodel = se_find_value_in_slist("snmp_secmods", model)) == |
199 | 0 | SE_DNE) { |
200 | 0 | config_perror |
201 | 0 | ("bad security model, should be: v1, v2c or usm or a registered security plugin name"); |
202 | 0 | return; |
203 | 0 | } |
204 | 0 | } |
205 | 0 | if (strlen(security) + 1 > sizeof(gp->groupName)) { |
206 | 0 | config_perror("security name too long"); |
207 | 0 | return; |
208 | 0 | } |
209 | 0 | gp = vacm_createGroupEntry(imodel, security); |
210 | 0 | if (!gp) { |
211 | 0 | config_perror("failed to create group entry"); |
212 | 0 | return; |
213 | 0 | } |
214 | 0 | strlcpy(gp->groupName, group, sizeof(gp->groupName)); |
215 | 0 | gp->storageType = SNMP_STORAGE_PERMANENT; |
216 | 0 | gp->status = SNMP_ROW_ACTIVE; |
217 | 0 | free(gp->reserved); |
218 | 0 | gp->reserved = NULL; |
219 | 0 | } |
220 | | |
221 | | void |
222 | | vacm_free_group(void) |
223 | 6.69k | { |
224 | 6.69k | vacm_destroyAllGroupEntries(); |
225 | 6.69k | } |
226 | | |
227 | 0 | #define PARSE_CONT 0 |
228 | 0 | #define PARSE_FAIL 1 |
229 | | |
230 | | int |
231 | | _vacm_parse_access_common(const char *token, char *param, char **st, |
232 | | char **name, char **context, int *imodel, |
233 | | int *ilevel, int *iprefix) |
234 | 0 | { |
235 | 0 | char *model, *level, *prefix; |
236 | |
|
237 | 0 | *name = strtok_r(param, " \t\n", st); |
238 | 0 | if (!*name) { |
239 | 0 | config_perror("missing NAME parameter"); |
240 | 0 | return PARSE_FAIL; |
241 | 0 | } |
242 | 0 | *context = strtok_r(NULL, " \t\n", st); |
243 | 0 | if (!*context) { |
244 | 0 | config_perror("missing CONTEXT parameter"); |
245 | 0 | return PARSE_FAIL; |
246 | 0 | } |
247 | | |
248 | 0 | model = strtok_r(NULL, " \t\n", st); |
249 | 0 | if (!model) { |
250 | 0 | config_perror("missing MODEL parameter"); |
251 | 0 | return PARSE_FAIL; |
252 | 0 | } |
253 | 0 | level = strtok_r(NULL, " \t\n", st); |
254 | 0 | if (!level) { |
255 | 0 | config_perror("missing LEVEL parameter"); |
256 | 0 | return PARSE_FAIL; |
257 | 0 | } |
258 | 0 | prefix = strtok_r(NULL, " \t\n", st); |
259 | 0 | if (!prefix) { |
260 | 0 | config_perror("missing PREFIX parameter"); |
261 | 0 | return PARSE_FAIL; |
262 | 0 | } |
263 | | |
264 | 0 | if (strcmp(*context, "\"\"") == 0 || strcmp(*context, "\'\'") == 0) |
265 | 0 | **context = 0; |
266 | 0 | if (strcasecmp(model, "any") == 0) |
267 | 0 | *imodel = SNMP_SEC_MODEL_ANY; |
268 | 0 | else if (strcasecmp(model, "v1") == 0) |
269 | 0 | *imodel = SNMP_SEC_MODEL_SNMPv1; |
270 | 0 | else if (strcasecmp(model, "v2c") == 0) |
271 | 0 | *imodel = SNMP_SEC_MODEL_SNMPv2c; |
272 | 0 | else { |
273 | 0 | if ((*imodel = se_find_value_in_slist("snmp_secmods", model)) |
274 | 0 | == SE_DNE) { |
275 | 0 | config_perror |
276 | 0 | ("bad security model, should be: v1, v2c or usm or a registered security plugin name"); |
277 | 0 | return PARSE_FAIL; |
278 | 0 | } |
279 | 0 | } |
280 | | |
281 | 0 | if (strcasecmp(level, "noauth") == 0) |
282 | 0 | *ilevel = SNMP_SEC_LEVEL_NOAUTH; |
283 | 0 | else if (strcasecmp(level, "noauthnopriv") == 0) |
284 | 0 | *ilevel = SNMP_SEC_LEVEL_NOAUTH; |
285 | 0 | else if (strcasecmp(level, "auth") == 0) |
286 | 0 | *ilevel = SNMP_SEC_LEVEL_AUTHNOPRIV; |
287 | 0 | else if (strcasecmp(level, "authnopriv") == 0) |
288 | 0 | *ilevel = SNMP_SEC_LEVEL_AUTHNOPRIV; |
289 | 0 | else if (strcasecmp(level, "priv") == 0) |
290 | 0 | *ilevel = SNMP_SEC_LEVEL_AUTHPRIV; |
291 | 0 | else if (strcasecmp(level, "authpriv") == 0) |
292 | 0 | *ilevel = SNMP_SEC_LEVEL_AUTHPRIV; |
293 | 0 | else { |
294 | 0 | config_perror |
295 | 0 | ("bad security level (noauthnopriv, authnopriv, authpriv)"); |
296 | 0 | return PARSE_FAIL; |
297 | 0 | } |
298 | | |
299 | 0 | if (strcmp(prefix, "exact") == 0) |
300 | 0 | *iprefix = 1; |
301 | 0 | else if (strcmp(prefix, "prefix") == 0) |
302 | 0 | *iprefix = 2; |
303 | 0 | else if (strcmp(prefix, "0") == 0) { |
304 | 0 | config_perror |
305 | 0 | ("bad prefix match parameter \"0\", should be: exact or prefix - installing anyway"); |
306 | 0 | *iprefix = 1; |
307 | 0 | } else { |
308 | 0 | config_perror |
309 | 0 | ("bad prefix match parameter, should be: exact or prefix"); |
310 | 0 | return PARSE_FAIL; |
311 | 0 | } |
312 | | |
313 | 0 | return PARSE_CONT; |
314 | 0 | } |
315 | | |
316 | | /* **************************************/ |
317 | | /* authorization parsing token handlers */ |
318 | | /* **************************************/ |
319 | | |
320 | | int |
321 | | vacm_parse_authtokens(const char *token, char **confline) |
322 | 0 | { |
323 | 0 | char authspec[SNMP_MAXBUF_MEDIUM]; |
324 | 0 | char *strtok_state; |
325 | 0 | char *type; |
326 | 0 | int viewtype, viewtypes = 0; |
327 | |
|
328 | 0 | *confline = copy_nword(*confline, authspec, sizeof(authspec)); |
329 | | |
330 | 0 | DEBUGMSGTL(("vacm_parse_authtokens","parsing %s",authspec)); |
331 | 0 | if (!*confline) { |
332 | 0 | config_perror("Illegal configuration line: missing fields"); |
333 | 0 | return -1; |
334 | 0 | } |
335 | | |
336 | 0 | type = strtok_r(authspec, ",|:", &strtok_state); |
337 | 0 | while(type && *type != '\0') { |
338 | 0 | viewtype = se_find_value_in_slist(VACM_VIEW_ENUM_NAME, type); |
339 | 0 | if (viewtype < 0 || viewtype >= VACM_MAX_VIEWS) { |
340 | 0 | config_perror("Illegal view name"); |
341 | 0 | } else { |
342 | 0 | viewtypes |= (1 << viewtype); |
343 | 0 | } |
344 | 0 | type = strtok_r(NULL, ",|:", &strtok_state); |
345 | 0 | } |
346 | 0 | DEBUGMSG(("vacm_parse_authtokens"," .. result = 0x%x\n",viewtypes)); |
347 | 0 | return viewtypes; |
348 | 0 | } |
349 | | |
350 | | void |
351 | | vacm_parse_authuser(const char *token, char *confline) |
352 | 0 | { |
353 | 0 | int viewtypes = vacm_parse_authtokens(token, &confline); |
354 | 0 | if (viewtypes != -1) |
355 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_V3, viewtypes); |
356 | 0 | } |
357 | | |
358 | | void |
359 | | vacm_parse_authcommunity(const char *token, char *confline) |
360 | 0 | { |
361 | 0 | int viewtypes = vacm_parse_authtokens(token, &confline); |
362 | 0 | if (viewtypes != -1) |
363 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COM, viewtypes); |
364 | 0 | } |
365 | | |
366 | | void |
367 | | vacm_parse_authaccess(const char *token, char *confline) |
368 | 0 | { |
369 | 0 | char *group, *view, *tmp; |
370 | 0 | const char *context; |
371 | 0 | int model = SNMP_SEC_MODEL_ANY; |
372 | 0 | int level, prefix; |
373 | 0 | int i; |
374 | 0 | char *st; |
375 | 0 | struct vacm_accessEntry *ap; |
376 | 0 | int viewtypes = vacm_parse_authtokens(token, &confline); |
377 | |
|
378 | 0 | if (viewtypes == -1) |
379 | 0 | return; |
380 | | |
381 | 0 | group = strtok_r(confline, " \t\n", &st); |
382 | 0 | if (!group) { |
383 | 0 | config_perror("missing GROUP parameter"); |
384 | 0 | return; |
385 | 0 | } |
386 | 0 | view = strtok_r(NULL, " \t\n", &st); |
387 | 0 | if (!view) { |
388 | 0 | config_perror("missing VIEW parameter"); |
389 | 0 | return; |
390 | 0 | } |
391 | | |
392 | | /* |
393 | | * Check for security model option |
394 | | */ |
395 | 0 | if ( strcasecmp(view, "-s") == 0 ) { |
396 | 0 | tmp = strtok_r(NULL, " \t\n", &st); |
397 | 0 | if (tmp) { |
398 | 0 | if (strcasecmp(tmp, "any") == 0) |
399 | 0 | model = SNMP_SEC_MODEL_ANY; |
400 | 0 | else if (strcasecmp(tmp, "v1") == 0) |
401 | 0 | model = SNMP_SEC_MODEL_SNMPv1; |
402 | 0 | else if (strcasecmp(tmp, "v2c") == 0) |
403 | 0 | model = SNMP_SEC_MODEL_SNMPv2c; |
404 | 0 | else { |
405 | 0 | model = se_find_value_in_slist("snmp_secmods", tmp); |
406 | 0 | if (model == SE_DNE) { |
407 | 0 | config_perror |
408 | 0 | ("bad security model, should be: v1, v2c or usm or a registered security plugin name"); |
409 | 0 | return; |
410 | 0 | } |
411 | 0 | } |
412 | 0 | } else { |
413 | 0 | config_perror("missing SECMODEL parameter"); |
414 | 0 | return; |
415 | 0 | } |
416 | 0 | view = strtok_r(NULL, " \t\n", &st); |
417 | 0 | if (!view) { |
418 | 0 | config_perror("missing VIEW parameter"); |
419 | 0 | return; |
420 | 0 | } |
421 | 0 | } |
422 | 0 | if (strlen(view) >= VACMSTRINGLEN ) { |
423 | 0 | config_perror("View value too long"); |
424 | 0 | return; |
425 | 0 | } |
426 | | |
427 | | /* |
428 | | * Now parse optional fields, or provide default values |
429 | | */ |
430 | | |
431 | 0 | tmp = strtok_r(NULL, " \t\n", &st); |
432 | 0 | if (tmp) { |
433 | 0 | if (strcasecmp(tmp, "noauth") == 0) |
434 | 0 | level = SNMP_SEC_LEVEL_NOAUTH; |
435 | 0 | else if (strcasecmp(tmp, "noauthnopriv") == 0) |
436 | 0 | level = SNMP_SEC_LEVEL_NOAUTH; |
437 | 0 | else if (strcasecmp(tmp, "auth") == 0) |
438 | 0 | level = SNMP_SEC_LEVEL_AUTHNOPRIV; |
439 | 0 | else if (strcasecmp(tmp, "authnopriv") == 0) |
440 | 0 | level = SNMP_SEC_LEVEL_AUTHNOPRIV; |
441 | 0 | else if (strcasecmp(tmp, "priv") == 0) |
442 | 0 | level = SNMP_SEC_LEVEL_AUTHPRIV; |
443 | 0 | else if (strcasecmp(tmp, "authpriv") == 0) |
444 | 0 | level = SNMP_SEC_LEVEL_AUTHPRIV; |
445 | 0 | else { |
446 | 0 | config_perror |
447 | 0 | ("bad security level (noauthnopriv, authnopriv, authpriv)"); |
448 | 0 | return; |
449 | 0 | } |
450 | 0 | } else { |
451 | | /* What about SNMP_SEC_MODEL_ANY ?? */ |
452 | 0 | if ( model == SNMP_SEC_MODEL_SNMPv1 || |
453 | 0 | model == SNMP_SEC_MODEL_SNMPv2c ) |
454 | 0 | level = SNMP_SEC_LEVEL_NOAUTH; |
455 | 0 | else |
456 | 0 | level = SNMP_SEC_LEVEL_AUTHNOPRIV; |
457 | 0 | } |
458 | | |
459 | | |
460 | 0 | context = tmp = strtok_r(NULL, " \t\n", &st); |
461 | 0 | if (tmp) { |
462 | 0 | tmp = (tmp + strlen(tmp)-1); |
463 | 0 | if (tmp && *tmp == '*') { |
464 | 0 | *tmp = '\0'; |
465 | 0 | prefix = 2; |
466 | 0 | } else { |
467 | 0 | prefix = 1; |
468 | 0 | } |
469 | 0 | } else { |
470 | 0 | context = ""; |
471 | 0 | prefix = 1; /* Or prefix(2) ?? */ |
472 | 0 | } |
473 | | |
474 | | /* |
475 | | * Now we can create the access entry |
476 | | */ |
477 | 0 | ap = vacm_getAccessEntry(group, context, model, level); |
478 | 0 | if (!ap) { |
479 | 0 | ap = vacm_createAccessEntry(group, context, model, level); |
480 | 0 | DEBUGMSGTL(("vacm:conf:authaccess", |
481 | 0 | "no existing access found; creating a new one\n")); |
482 | 0 | } else { |
483 | 0 | DEBUGMSGTL(("vacm:conf:authaccess", |
484 | 0 | "existing access found, using it\n")); |
485 | 0 | } |
486 | 0 | if (!ap) { |
487 | 0 | config_perror("failed to create access entry"); |
488 | 0 | return; |
489 | 0 | } |
490 | | |
491 | 0 | for (i = 0; i < VACM_MAX_VIEWS; i++) { |
492 | 0 | if (viewtypes & (1 << i)) { |
493 | 0 | strlcpy(ap->views[i], view, sizeof(ap->views[i])); |
494 | 0 | } |
495 | 0 | } |
496 | 0 | ap->contextMatch = prefix; |
497 | 0 | ap->storageType = SNMP_STORAGE_PERMANENT; |
498 | 0 | ap->status = SNMP_ROW_ACTIVE; |
499 | 0 | if (ap->reserved) |
500 | 0 | free(ap->reserved); |
501 | 0 | ap->reserved = NULL; |
502 | 0 | } |
503 | | |
504 | | void |
505 | | vacm_parse_setaccess(const char *token, char *param) |
506 | 0 | { |
507 | 0 | char *name, *context, *viewname, *viewval; |
508 | 0 | int imodel, ilevel, iprefix; |
509 | 0 | int viewnum; |
510 | 0 | char *st; |
511 | 0 | struct vacm_accessEntry *ap; |
512 | | |
513 | 0 | if (_vacm_parse_access_common(token, param, &st, &name, |
514 | 0 | &context, &imodel, &ilevel, &iprefix) |
515 | 0 | == PARSE_FAIL) { |
516 | 0 | return; |
517 | 0 | } |
518 | | |
519 | 0 | viewname = strtok_r(NULL, " \t\n", &st); |
520 | 0 | if (!viewname) { |
521 | 0 | config_perror("missing viewname parameter"); |
522 | 0 | return; |
523 | 0 | } |
524 | 0 | viewval = strtok_r(NULL, " \t\n", &st); |
525 | 0 | if (!viewval) { |
526 | 0 | config_perror("missing viewval parameter"); |
527 | 0 | return; |
528 | 0 | } |
529 | | |
530 | 0 | if (strlen(viewval) + 1 > sizeof(ap->views[VACM_VIEW_NOTIFY])) { |
531 | 0 | config_perror("View value too long"); |
532 | 0 | return; |
533 | 0 | } |
534 | | |
535 | 0 | viewnum = se_find_value_in_slist(VACM_VIEW_ENUM_NAME, viewname); |
536 | 0 | if (viewnum < 0 || viewnum >= VACM_MAX_VIEWS) { |
537 | 0 | config_perror("Illegal view name"); |
538 | 0 | return; |
539 | 0 | } |
540 | | |
541 | 0 | ap = vacm_getAccessEntry(name, context, imodel, ilevel); |
542 | 0 | if (!ap) { |
543 | 0 | ap = vacm_createAccessEntry(name, context, imodel, ilevel); |
544 | 0 | DEBUGMSGTL(("vacm:conf:setaccess", |
545 | 0 | "no existing access found; creating a new one\n")); |
546 | 0 | } else { |
547 | 0 | DEBUGMSGTL(("vacm:conf:setaccess", |
548 | 0 | "existing access found, using it\n")); |
549 | 0 | } |
550 | 0 | if (!ap) { |
551 | 0 | config_perror("failed to create access entry"); |
552 | 0 | return; |
553 | 0 | } |
554 | | |
555 | 0 | strlcpy(ap->views[viewnum], viewval, sizeof(ap->views[viewnum])); |
556 | 0 | ap->contextMatch = iprefix; |
557 | 0 | ap->storageType = SNMP_STORAGE_PERMANENT; |
558 | 0 | ap->status = SNMP_ROW_ACTIVE; |
559 | 0 | free(ap->reserved); |
560 | 0 | ap->reserved = NULL; |
561 | 0 | } |
562 | | |
563 | | void |
564 | | vacm_parse_access(const char *token, char *param) |
565 | 0 | { |
566 | 0 | char *name, *context, *readView, *writeView, *notify; |
567 | 0 | int imodel, ilevel, iprefix; |
568 | 0 | struct vacm_accessEntry *ap; |
569 | 0 | char *st; |
570 | | |
571 | | |
572 | 0 | if (_vacm_parse_access_common(token, param, &st, &name, |
573 | 0 | &context, &imodel, &ilevel, &iprefix) |
574 | 0 | == PARSE_FAIL) { |
575 | 0 | return; |
576 | 0 | } |
577 | | |
578 | 0 | readView = strtok_r(NULL, " \t\n", &st); |
579 | 0 | if (!readView) { |
580 | 0 | config_perror("missing readView parameter"); |
581 | 0 | return; |
582 | 0 | } |
583 | 0 | writeView = strtok_r(NULL, " \t\n", &st); |
584 | 0 | if (!writeView) { |
585 | 0 | config_perror("missing writeView parameter"); |
586 | 0 | return; |
587 | 0 | } |
588 | 0 | notify = strtok_r(NULL, " \t\n", &st); |
589 | 0 | if (!notify) { |
590 | 0 | config_perror("missing notifyView parameter"); |
591 | 0 | return; |
592 | 0 | } |
593 | | |
594 | 0 | if (strlen(readView) + 1 > sizeof(ap->views[VACM_VIEW_READ])) { |
595 | 0 | config_perror("readView too long"); |
596 | 0 | return; |
597 | 0 | } |
598 | 0 | if (strlen(writeView) + 1 > sizeof(ap->views[VACM_VIEW_WRITE])) { |
599 | 0 | config_perror("writeView too long"); |
600 | 0 | return; |
601 | 0 | } |
602 | 0 | if (strlen(notify) + 1 > sizeof(ap->views[VACM_VIEW_NOTIFY])) { |
603 | 0 | config_perror("notifyView too long"); |
604 | 0 | return; |
605 | 0 | } |
606 | 0 | ap = vacm_createAccessEntry(name, context, imodel, ilevel); |
607 | 0 | if (!ap) { |
608 | 0 | config_perror("failed to create access entry"); |
609 | 0 | return; |
610 | 0 | } |
611 | 0 | strlcpy(ap->views[VACM_VIEW_READ], readView, |
612 | 0 | sizeof(ap->views[VACM_VIEW_READ])); |
613 | 0 | strlcpy(ap->views[VACM_VIEW_WRITE], writeView, |
614 | 0 | sizeof(ap->views[VACM_VIEW_WRITE])); |
615 | 0 | strlcpy(ap->views[VACM_VIEW_NOTIFY], notify, |
616 | 0 | sizeof(ap->views[VACM_VIEW_NOTIFY])); |
617 | 0 | ap->contextMatch = iprefix; |
618 | 0 | ap->storageType = SNMP_STORAGE_PERMANENT; |
619 | 0 | ap->status = SNMP_ROW_ACTIVE; |
620 | 0 | free(ap->reserved); |
621 | 0 | ap->reserved = NULL; |
622 | 0 | } |
623 | | |
624 | | void |
625 | | vacm_free_access(void) |
626 | 20.0k | { |
627 | 20.0k | vacm_destroyAllAccessEntries(); |
628 | 20.0k | } |
629 | | |
630 | | void |
631 | | vacm_parse_view(const char *token, char *param) |
632 | 20.0k | { |
633 | 20.0k | char *name, *type, *subtree, *mask; |
634 | 20.0k | int inclexcl; |
635 | 20.0k | struct vacm_viewEntry *vp; |
636 | 20.0k | oid suboid[MAX_OID_LEN]; |
637 | 20.0k | size_t suboid_len = 0; |
638 | 20.0k | size_t mask_len = 0; |
639 | 20.0k | u_char viewMask[VACMSTRINGLEN]; |
640 | 20.0k | size_t i; |
641 | 20.0k | char *st; |
642 | | |
643 | 20.0k | name = strtok_r(param, " \t\n", &st); |
644 | 20.0k | if (!name) { |
645 | 0 | config_perror("missing NAME parameter"); |
646 | 0 | return; |
647 | 0 | } |
648 | 20.0k | type = strtok_r(NULL, " \n\t", &st); |
649 | 20.0k | if (!type) { |
650 | 0 | config_perror("missing TYPE parameter"); |
651 | 0 | return; |
652 | 0 | } |
653 | 20.0k | subtree = strtok_r(NULL, " \t\n", &st); |
654 | 20.0k | if (!subtree) { |
655 | 0 | config_perror("missing SUBTREE parameter"); |
656 | 0 | return; |
657 | 0 | } |
658 | 20.0k | mask = strtok_r(NULL, "\0", &st); |
659 | | |
660 | 20.0k | if (strcmp(type, "included") == 0) |
661 | 10.0k | inclexcl = SNMP_VIEW_INCLUDED; |
662 | 10.0k | else if (strcmp(type, "excluded") == 0) |
663 | 10.0k | inclexcl = SNMP_VIEW_EXCLUDED; |
664 | 0 | else { |
665 | 0 | config_perror("TYPE must be included/excluded?"); |
666 | 0 | return; |
667 | 0 | } |
668 | 20.0k | suboid_len = strlen(subtree)-1; |
669 | 20.0k | if (subtree[suboid_len] == '.') |
670 | 0 | subtree[suboid_len] = '\0'; /* stamp on a trailing . */ |
671 | 20.0k | suboid_len = MAX_OID_LEN; |
672 | 20.0k | if (!snmp_parse_oid(subtree, suboid, &suboid_len)) { |
673 | 0 | config_perror("bad SUBTREE object id"); |
674 | 0 | return; |
675 | 0 | } |
676 | 20.0k | if (mask) { |
677 | 0 | unsigned int val; |
678 | 0 | i = 0; |
679 | 0 | for (mask = strtok_r(mask, " .:", &st); mask; mask = strtok_r(NULL, " .:", &st)) { |
680 | 0 | if (i >= sizeof(viewMask)) { |
681 | 0 | config_perror("MASK too long"); |
682 | 0 | return; |
683 | 0 | } |
684 | 0 | if (sscanf(mask, "%x", &val) == 0) { |
685 | 0 | config_perror("invalid MASK"); |
686 | 0 | return; |
687 | 0 | } |
688 | 0 | viewMask[i] = val; |
689 | 0 | i++; |
690 | 0 | } |
691 | 0 | mask_len = i; |
692 | 20.0k | } else { |
693 | 702k | for (i = 0; i < sizeof(viewMask); i++) |
694 | 682k | viewMask[i] = 0xff; |
695 | 20.0k | } |
696 | 20.0k | vp = vacm_createViewEntry(name, suboid, suboid_len); |
697 | 20.0k | if (!vp) { |
698 | 0 | config_perror("failed to create view entry"); |
699 | 0 | return; |
700 | 0 | } |
701 | 20.0k | memcpy(vp->viewMask, viewMask, sizeof(viewMask)); |
702 | 20.0k | vp->viewMaskLen = mask_len; |
703 | 20.0k | vp->viewType = inclexcl; |
704 | 20.0k | vp->viewStorageType = SNMP_STORAGE_PERMANENT; |
705 | 20.0k | vp->viewStatus = SNMP_ROW_ACTIVE; |
706 | 20.0k | free(vp->reserved); |
707 | 20.0k | vp->reserved = NULL; |
708 | 20.0k | } |
709 | | |
710 | | void |
711 | | vacm_free_view(void) |
712 | 6.69k | { |
713 | 6.69k | vacm_destroyAllViewEntries(); |
714 | 6.69k | } |
715 | | |
716 | | void |
717 | | vacm_gen_com2sec(int commcount, const char *community, const char *addressname, |
718 | | const char *publishtoken, |
719 | | void (*parser)(const char *, char *), |
720 | | char *secname, size_t secname_len, |
721 | | char *viewname, size_t viewname_len, int version, |
722 | | const char *context) |
723 | 0 | { |
724 | 0 | char line[SPRINT_MAX_LEN]; |
725 | | |
726 | | /* |
727 | | * com2sec6|comsec [-Cn CONTEXT] anonymousSecNameNUM ADDRESS COMMUNITY |
728 | | */ |
729 | 0 | snprintf(secname, secname_len-1, "comm%d", commcount); |
730 | 0 | secname[secname_len-1] = '\0'; |
731 | 0 | if (viewname) { |
732 | 0 | snprintf(viewname, viewname_len-1, "viewComm%d", commcount); |
733 | 0 | viewname[viewname_len-1] = '\0'; |
734 | 0 | } |
735 | 0 | if ( context && *context ) |
736 | 0 | snprintf(line, sizeof(line), "-Cn %s %s %s '%s'", |
737 | 0 | context, secname, addressname, community); |
738 | 0 | else |
739 | 0 | snprintf(line, sizeof(line), "%s %s '%s'", |
740 | 0 | secname, addressname, community); |
741 | 0 | DEBUGMSGTL((publishtoken, "passing: %s %s\n", publishtoken, line)); |
742 | 0 | (*parser)(publishtoken, line); |
743 | | |
744 | | /* |
745 | | * sec->group mapping |
746 | | */ |
747 | | /* |
748 | | * group anonymousGroupNameNUM any anonymousSecNameNUM |
749 | | */ |
750 | 0 | if ( version & SNMP_SEC_MODEL_SNMPv1 ) { |
751 | 0 | snprintf(line, sizeof(line), |
752 | 0 | "grp%.28s v1 %s", secname, secname); |
753 | 0 | line[ sizeof(line)-1 ] = 0; |
754 | 0 | DEBUGMSGTL((publishtoken, "passing: %s %s\n", "group", line)); |
755 | 0 | vacm_parse_group("group", line); |
756 | 0 | } |
757 | |
|
758 | 0 | if ( version & SNMP_SEC_MODEL_SNMPv2c ) { |
759 | 0 | snprintf(line, sizeof(line), |
760 | 0 | "grp%.28s v2c %s", secname, secname); |
761 | 0 | line[ sizeof(line)-1 ] = 0; |
762 | 0 | DEBUGMSGTL((publishtoken, "passing: %s %s\n", "group", line)); |
763 | 0 | vacm_parse_group("group", line); |
764 | 0 | } |
765 | 0 | } |
766 | | |
767 | | void |
768 | | vacm_parse_rwuser(const char *token, char *confline) |
769 | 0 | { |
770 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_V3, |
771 | 0 | VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT); |
772 | 0 | } |
773 | | |
774 | | void |
775 | | vacm_parse_rouser(const char *token, char *confline) |
776 | 0 | { |
777 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_V3, |
778 | 0 | VACM_VIEW_READ_BIT); |
779 | 0 | } |
780 | | |
781 | | void |
782 | | vacm_parse_rocommunity(const char *token, char *confline) |
783 | 0 | { |
784 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV4, |
785 | 0 | VACM_VIEW_READ_BIT); |
786 | 0 | } |
787 | | |
788 | | void |
789 | | vacm_parse_rwcommunity(const char *token, char *confline) |
790 | 0 | { |
791 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV4, |
792 | 0 | VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT); |
793 | 0 | } |
794 | | |
795 | | void |
796 | | vacm_parse_rocommunity6(const char *token, char *confline) |
797 | 0 | { |
798 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV6, |
799 | 0 | VACM_VIEW_READ_BIT); |
800 | 0 | } |
801 | | |
802 | | void |
803 | | vacm_parse_rwcommunity6(const char *token, char *confline) |
804 | 0 | { |
805 | 0 | vacm_create_simple(token, confline, VACM_CREATE_SIMPLE_COMIPV6, |
806 | 0 | VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT); |
807 | 0 | } |
808 | | |
809 | | |
810 | | void |
811 | | vacm_create_simple(const char *token, char *confline, |
812 | | int parsetype, int viewtypes) |
813 | 0 | { |
814 | 0 | char line[SPRINT_MAX_LEN]; |
815 | 0 | char community[COMMUNITY_MAX_LEN]; |
816 | 0 | char theoid[SPRINT_MAX_LEN]; |
817 | 0 | char viewname[SPRINT_MAX_LEN]; |
818 | 0 | char *view_ptr = viewname; |
819 | 0 | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
820 | 0 | char addressname[SPRINT_MAX_LEN]; |
821 | | /* Conveniently, the community-based security |
822 | | model values can also be used as bit flags */ |
823 | 0 | int commversion = SNMP_SEC_MODEL_SNMPv1 | |
824 | 0 | SNMP_SEC_MODEL_SNMPv2c; |
825 | 0 | #endif |
826 | 0 | const char *rw = "none"; |
827 | 0 | char model[SPRINT_MAX_LEN]; |
828 | 0 | char *cp, *tmp; |
829 | 0 | char secname[SPRINT_MAX_LEN]; |
830 | 0 | char grpname[SPRINT_MAX_LEN]; |
831 | 0 | char authlevel[SPRINT_MAX_LEN]; |
832 | 0 | char context[SPRINT_MAX_LEN]; |
833 | 0 | int ctxprefix = 1; /* Default to matching all contexts */ |
834 | 0 | static int commcount = 0; |
835 | 0 | size_t ctxlen; |
836 | | |
837 | | /* |
838 | | * init |
839 | | */ |
840 | 0 | strcpy(model, "any"); |
841 | 0 | memset(context, 0, sizeof(context)); |
842 | 0 | memset(secname, 0, sizeof(secname)); |
843 | 0 | memset(grpname, 0, sizeof(grpname)); |
844 | | |
845 | | /* |
846 | | * community name or user name |
847 | | */ |
848 | 0 | cp = copy_nword(confline, community, sizeof(community)); |
849 | |
|
850 | 0 | if (parsetype == VACM_CREATE_SIMPLE_V3) { |
851 | | /* |
852 | | * maybe security model type |
853 | | */ |
854 | 0 | if (strcmp(community, "-s") == 0) { |
855 | | /* |
856 | | * -s model ... |
857 | | */ |
858 | 0 | if (cp) |
859 | 0 | cp = copy_nword(cp, model, sizeof(model)); |
860 | 0 | if (!cp) { |
861 | 0 | config_perror("illegal line"); |
862 | 0 | return; |
863 | 0 | } |
864 | 0 | if (cp) |
865 | 0 | cp = copy_nword(cp, community, sizeof(community)); |
866 | 0 | } else { |
867 | 0 | strcpy(model, "usm"); |
868 | 0 | } |
869 | | /* |
870 | | * authentication level |
871 | | */ |
872 | 0 | if (cp && *cp) |
873 | 0 | cp = copy_nword(cp, authlevel, sizeof(authlevel)); |
874 | 0 | else |
875 | 0 | strcpy(authlevel, "auth"); |
876 | 0 | DEBUGMSGTL((token, "setting auth level: \"%s\"\n", authlevel)); |
877 | 0 | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
878 | 0 | } else { |
879 | 0 | if (strcmp(community, "-v") == 0) { |
880 | | /* |
881 | | * -v version ... |
882 | | */ |
883 | 0 | if (cp) |
884 | 0 | cp = copy_nword(cp, model, sizeof(model)); |
885 | 0 | if (!cp) { |
886 | 0 | config_perror("illegal line"); |
887 | 0 | return; |
888 | 0 | } |
889 | 0 | if ( strcasecmp( model, "1" ) == 0 ) |
890 | 0 | strcpy(model, "v1"); |
891 | 0 | if ( strcasecmp( model, "v1" ) == 0 ) |
892 | 0 | commversion = SNMP_SEC_MODEL_SNMPv1; |
893 | 0 | if ( strcasecmp( model, "2c" ) == 0 ) |
894 | 0 | strcpy(model, "v2c"); |
895 | 0 | if ( strcasecmp( model, "v2c" ) == 0 ) |
896 | 0 | commversion = SNMP_SEC_MODEL_SNMPv2c; |
897 | 0 | if (cp) |
898 | 0 | cp = copy_nword(cp, community, sizeof(community)); |
899 | 0 | } |
900 | | /* |
901 | | * source address |
902 | | */ |
903 | 0 | if (cp && *cp) { |
904 | 0 | cp = copy_nword(cp, addressname, sizeof(addressname)); |
905 | 0 | } else { |
906 | 0 | strcpy(addressname, "default"); |
907 | 0 | } |
908 | | /* |
909 | | * authlevel has to be noauth |
910 | | */ |
911 | 0 | strcpy(authlevel, "noauth"); |
912 | 0 | #endif /* support for community based SNMP */ |
913 | 0 | } |
914 | | |
915 | | /* |
916 | | * oid they can touch |
917 | | */ |
918 | 0 | if (cp && *cp) { |
919 | 0 | if (strncmp(cp, "-V ", 3) == 0) { |
920 | 0 | cp = skip_token(cp); |
921 | 0 | cp = copy_nword(cp, viewname, sizeof(viewname)); |
922 | 0 | view_ptr = NULL; |
923 | 0 | } else { |
924 | 0 | cp = copy_nword(cp, theoid, sizeof(theoid)); |
925 | 0 | } |
926 | 0 | } else { |
927 | 0 | strcpy(theoid, ".1"); |
928 | 0 | strcpy(viewname, "_all_"); |
929 | 0 | view_ptr = NULL; |
930 | 0 | } |
931 | | /* |
932 | | * optional, non-default context |
933 | | */ |
934 | 0 | if (cp && *cp) { |
935 | 0 | cp = copy_nword(cp, context, sizeof(context)); |
936 | 0 | ctxlen = strlen(context); |
937 | 0 | if (ctxlen == 0) { |
938 | 0 | config_perror("Improper configuration line - if context is specified, it cannot be blank. For an empty context, simply do not specify one instead."); |
939 | 0 | return; |
940 | 0 | } |
941 | 0 | tmp = (context + ctxlen-1); |
942 | 0 | if (tmp && *tmp == '*') { |
943 | 0 | *tmp = '\0'; |
944 | 0 | ctxprefix = 1; |
945 | 0 | } else { |
946 | | /* |
947 | | * If no context field is given, then we default to matching |
948 | | * all contexts (for compatibility with previous releases). |
949 | | * But if a field context is specified (not ending with '*') |
950 | | * then this should be taken as an exact match. |
951 | | * Specifying a context field of "" will match the default |
952 | | * context (and *only* the default context). |
953 | | */ |
954 | 0 | ctxprefix = 0; |
955 | 0 | } |
956 | 0 | } |
957 | | |
958 | 0 | if (viewtypes & VACM_VIEW_WRITE_BIT) |
959 | 0 | rw = viewname; |
960 | |
|
961 | 0 | commcount++; |
962 | |
|
963 | 0 | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
964 | 0 | #ifdef NETSNMP_TRANSPORT_UDP_DOMAIN |
965 | 0 | if (parsetype == VACM_CREATE_SIMPLE_COMIPV4 || |
966 | 0 | parsetype == VACM_CREATE_SIMPLE_COM) { |
967 | 0 | vacm_gen_com2sec(commcount, community, addressname, |
968 | 0 | "com2sec", &netsnmp_udp_parse_security, |
969 | 0 | secname, sizeof(secname), |
970 | 0 | view_ptr, sizeof(viewname), commversion, context); |
971 | 0 | } |
972 | 0 | #endif |
973 | |
|
974 | 0 | #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN |
975 | 0 | if (parsetype == VACM_CREATE_SIMPLE_COMUNIX || |
976 | 0 | parsetype == VACM_CREATE_SIMPLE_COM) { |
977 | 0 | if ( *context ) |
978 | 0 | snprintf(line, sizeof(line), "-Cn %s %s %s '%s'", |
979 | 0 | context, secname, addressname, community); |
980 | 0 | else |
981 | 0 | snprintf(line, sizeof(line), "%s %s '%s'", |
982 | 0 | secname, addressname, community); |
983 | 0 | DEBUGMSGTL((token, "passing: %s %s\n", "com2secunix", line)); |
984 | 0 | netsnmp_unix_parse_security("com2secunix", line); |
985 | 0 | } |
986 | 0 | #endif |
987 | |
|
988 | 0 | #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN |
989 | 0 | if (parsetype == VACM_CREATE_SIMPLE_COMIPV6 || |
990 | 0 | parsetype == VACM_CREATE_SIMPLE_COM) { |
991 | 0 | vacm_gen_com2sec(commcount, community, addressname, |
992 | 0 | "com2sec6", &netsnmp_udp6_parse_security, |
993 | 0 | secname, sizeof(secname), |
994 | 0 | view_ptr, sizeof(viewname), commversion, context); |
995 | 0 | } |
996 | 0 | #endif |
997 | 0 | #endif /* support for community based SNMP */ |
998 | |
|
999 | 0 | if (parsetype == VACM_CREATE_SIMPLE_V3) { |
1000 | | /* support for SNMPv3 user names */ |
1001 | 0 | if (view_ptr) { |
1002 | 0 | sprintf(viewname,"viewUSM%d",commcount); |
1003 | 0 | } |
1004 | 0 | if ( strcmp( token, "authgroup" ) == 0 ) { |
1005 | 0 | strlcpy(grpname, community, sizeof(grpname)); |
1006 | 0 | } else { |
1007 | 0 | strlcpy(secname, community, sizeof(secname)); |
1008 | | |
1009 | | /* |
1010 | | * sec->group mapping |
1011 | | */ |
1012 | | /* |
1013 | | * group anonymousGroupNameNUM any anonymousSecNameNUM |
1014 | | */ |
1015 | 0 | snprintf(grpname, sizeof(grpname), "grp%.28s", secname); |
1016 | 0 | for (tmp=grpname; *tmp; tmp++) |
1017 | 0 | if (!isalnum((unsigned char)(*tmp))) |
1018 | 0 | *tmp = '_'; |
1019 | 0 | snprintf(line, sizeof(line), |
1020 | 0 | "%s %s \"%s\"", grpname, model, secname); |
1021 | 0 | DEBUGMSGTL((token, "passing: %s %s\n", "group", line)); |
1022 | 0 | vacm_parse_group("group", line); |
1023 | 0 | } |
1024 | 0 | } else { |
1025 | 0 | snprintf(grpname, sizeof(grpname), "grp%.28s", secname); |
1026 | 0 | for (tmp=grpname; *tmp; tmp++) |
1027 | 0 | if (!isalnum((unsigned char)(*tmp))) |
1028 | 0 | *tmp = '_'; |
1029 | 0 | } |
1030 | | |
1031 | | /* |
1032 | | * view definition |
1033 | | */ |
1034 | | /* |
1035 | | * view anonymousViewNUM included OID |
1036 | | */ |
1037 | 0 | if (view_ptr) { |
1038 | 0 | snprintf(line, sizeof(line), "%s included %s", viewname, theoid); |
1039 | 0 | DEBUGMSGTL((token, "passing: %s %s\n", "view", line)); |
1040 | 0 | vacm_parse_view("view", line); |
1041 | 0 | } |
1042 | | |
1043 | | /* |
1044 | | * map everything together |
1045 | | */ |
1046 | 0 | if ((viewtypes == VACM_VIEW_READ_BIT) || |
1047 | 0 | (viewtypes == (VACM_VIEW_READ_BIT | VACM_VIEW_WRITE_BIT))) { |
1048 | | /* Use the simple line access command */ |
1049 | | /* |
1050 | | * access anonymousGroupNameNUM "" MODEL AUTHTYPE prefix anonymousViewNUM [none/anonymousViewNUM] [none/anonymousViewNUM] |
1051 | | */ |
1052 | 0 | snprintf(line, sizeof(line), |
1053 | 0 | "%s %s %s %s %s %s %s %s", |
1054 | 0 | grpname, context[0] ? context : "\"\"", |
1055 | 0 | model, authlevel, |
1056 | 0 | (ctxprefix ? "prefix" : "exact"), |
1057 | 0 | viewname, rw, rw); |
1058 | 0 | DEBUGMSGTL((token, "passing: %s %s\n", "access", line)); |
1059 | 0 | vacm_parse_access("access", line); |
1060 | 0 | } else { |
1061 | | /* Use one setaccess line per access type */ |
1062 | | /* |
1063 | | * setaccess anonymousGroupNameNUM "" MODEL AUTHTYPE prefix viewname viewval |
1064 | | */ |
1065 | 0 | int i; |
1066 | 0 | DEBUGMSGTL((token, " checking view levels for %x\n", viewtypes)); |
1067 | 0 | for(i = 0; i <= VACM_MAX_VIEWS; i++) { |
1068 | 0 | if (viewtypes & (1 << i)) { |
1069 | 0 | snprintf(line, sizeof(line), |
1070 | 0 | "%s %s %s %s %s %s %s", |
1071 | 0 | grpname, context[0] ? context : "\"\"", |
1072 | 0 | model, authlevel, |
1073 | 0 | (ctxprefix ? "prefix" : "exact"), |
1074 | 0 | se_find_label_in_slist(VACM_VIEW_ENUM_NAME, i), |
1075 | 0 | viewname); |
1076 | 0 | DEBUGMSGTL((token, "passing: %s %s\n", "setaccess", line)); |
1077 | 0 | vacm_parse_setaccess("setaccess", line); |
1078 | 0 | } |
1079 | 0 | } |
1080 | 0 | } |
1081 | 0 | } |
1082 | | |
1083 | | int |
1084 | | vacm_standard_views(int majorID, int minorID, void *serverarg, |
1085 | | void *clientarg) |
1086 | 3.34k | { |
1087 | 3.34k | char line[SPRINT_MAX_LEN]; |
1088 | | |
1089 | 3.34k | memset(line, 0, sizeof(line)); |
1090 | | |
1091 | 3.34k | snprintf(line, sizeof(line), "_all_ included .0"); |
1092 | 3.34k | vacm_parse_view("view", line); |
1093 | 3.34k | snprintf(line, sizeof(line), "_all_ included .1"); |
1094 | 3.34k | vacm_parse_view("view", line); |
1095 | 3.34k | snprintf(line, sizeof(line), "_all_ included .2"); |
1096 | 3.34k | vacm_parse_view("view", line); |
1097 | | |
1098 | 3.34k | snprintf(line, sizeof(line), "_none_ excluded .0"); |
1099 | 3.34k | vacm_parse_view("view", line); |
1100 | 3.34k | snprintf(line, sizeof(line), "_none_ excluded .1"); |
1101 | 3.34k | vacm_parse_view("view", line); |
1102 | 3.34k | snprintf(line, sizeof(line), "_none_ excluded .2"); |
1103 | 3.34k | vacm_parse_view("view", line); |
1104 | | |
1105 | 3.34k | return SNMP_ERR_NOERROR; |
1106 | 3.34k | } |
1107 | | |
1108 | | int |
1109 | | vacm_warn_if_not_configured(int majorID, int minorID, void *serverarg, |
1110 | | void *clientarg) |
1111 | 3.34k | { |
1112 | 3.34k | const char * name = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, |
1113 | 3.34k | NETSNMP_DS_LIB_APPTYPE); |
1114 | 3.34k | const int agent_mode = netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, |
1115 | 3.34k | NETSNMP_DS_AGENT_ROLE); |
1116 | 3.34k | if (NULL==name) |
1117 | 0 | name = "snmpd"; |
1118 | | |
1119 | 3.34k | if (!vacm_is_configured()) { |
1120 | | /* |
1121 | | * An AgentX subagent relies on the master agent to apply suitable |
1122 | | * access control checks, so doesn't need local VACM configuration. |
1123 | | * The trap daemon has a separate check (see below). |
1124 | | * |
1125 | | * Otherwise, an AgentX master or SNMP standalone agent requires some |
1126 | | * form of VACM configuration. No config means that no incoming |
1127 | | * requests will be accepted, so warn the user accordingly. |
1128 | | */ |
1129 | 3.34k | if ((MASTER_AGENT == agent_mode) && (strcmp(name, "snmptrapd") != 0)) { |
1130 | 3.34k | snmp_log(LOG_WARNING, |
1131 | 3.34k | "Warning: no access control information configured.\n" |
1132 | 3.34k | " (Config search path: %s)\n" |
1133 | 3.34k | " It's unlikely this agent can serve any useful purpose in this state.\n" |
1134 | 3.34k | " Run \"snmpconf -g basic_setup\" to help you " |
1135 | 3.34k | "configure the %s.conf file for this agent.\n", |
1136 | 3.34k | get_configuration_directory(), name); |
1137 | 3.34k | } |
1138 | | |
1139 | | /* |
1140 | | * The trap daemon implements VACM-style access control for incoming |
1141 | | * notifications, but offers a way of turning this off (for backwards |
1142 | | * compatibility). Check for this explicitly, and warn if necessary. |
1143 | | * |
1144 | | * NB: The NETSNMP_DS_APP_NO_AUTHORIZATION definition is a duplicate |
1145 | | * of an identical setting in "apps/snmptrapd_ds.h". |
1146 | | * These two need to be kept in sync. |
1147 | | */ |
1148 | | #ifndef NETSNMP_DS_APP_NO_AUTHORIZATION |
1149 | | #define NETSNMP_DS_APP_NO_AUTHORIZATION 17 |
1150 | | #endif |
1151 | 3.34k | if (!strcmp(name, "snmptrapd") && |
1152 | 0 | !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, |
1153 | 0 | NETSNMP_DS_APP_NO_AUTHORIZATION)) { |
1154 | 0 | snmp_log(LOG_WARNING, |
1155 | 0 | "Warning: no access control information configured.\n" |
1156 | 0 | " (Config search path: %s)\n" |
1157 | 0 | "This receiver will *NOT* accept any incoming notifications.\n", |
1158 | 0 | get_configuration_directory()); |
1159 | 0 | } |
1160 | 3.34k | } |
1161 | 3.34k | return SNMP_ERR_NOERROR; |
1162 | 3.34k | } |
1163 | | |
1164 | | int |
1165 | | vacm_in_view_callback(int majorID, int minorID, void *serverarg, |
1166 | | void *clientarg) |
1167 | 0 | { |
1168 | 0 | struct view_parameters *view_parms = |
1169 | 0 | (struct view_parameters *) serverarg; |
1170 | 0 | int retval; |
1171 | |
|
1172 | 0 | if (view_parms == NULL) |
1173 | 0 | return 1; |
1174 | 0 | retval = vacm_in_view(view_parms->pdu, view_parms->name, |
1175 | 0 | view_parms->namelen, view_parms->check_subtree); |
1176 | 0 | if (retval != 0) |
1177 | 0 | view_parms->errorcode = retval; |
1178 | 0 | return retval; |
1179 | 0 | } |
1180 | | |
1181 | | |
1182 | | /** |
1183 | | * vacm_in_view: decides if a given PDU can be acted upon |
1184 | | * |
1185 | | * Parameters: |
1186 | | * *pdu |
1187 | | * *name |
1188 | | * namelen |
1189 | | * check_subtree |
1190 | | * |
1191 | | * Returns: |
1192 | | * VACM_SUCCESS(0) On success. |
1193 | | * VACM_NOSECNAME(1) Missing security name. |
1194 | | * VACM_NOGROUP(2) Missing group |
1195 | | * VACM_NOACCESS(3) Missing access |
1196 | | * VACM_NOVIEW(4) Missing view |
1197 | | * VACM_NOTINVIEW(5) Not in view |
1198 | | * VACM_NOSUCHCONTEXT(6) No Such Context |
1199 | | * VACM_SUBTREE_UNKNOWN(7) When testing an entire subtree, UNKNOWN (i.e., the entire |
1200 | | * subtree has both allowed and disallowed portions) |
1201 | | * |
1202 | | * Debug output listed as follows: |
1203 | | * \<securityName\> \<groupName\> \<viewName\> \<viewType\> |
1204 | | */ |
1205 | | int |
1206 | | vacm_in_view(netsnmp_pdu *pdu, oid * name, size_t namelen, |
1207 | | int check_subtree) |
1208 | 0 | { |
1209 | 0 | int viewtype; |
1210 | |
|
1211 | 0 | switch (pdu->command) { |
1212 | 0 | case SNMP_MSG_GET: |
1213 | 0 | case SNMP_MSG_GETNEXT: |
1214 | 0 | case SNMP_MSG_GETBULK: |
1215 | 0 | viewtype = VACM_VIEW_READ; |
1216 | 0 | break; |
1217 | 0 | #ifndef NETSNMP_NO_WRITE_SUPPORT |
1218 | 0 | case SNMP_MSG_SET: |
1219 | 0 | viewtype = VACM_VIEW_WRITE; |
1220 | 0 | break; |
1221 | 0 | #endif /* !NETSNMP_NO_WRITE_SUPPORT */ |
1222 | 0 | case SNMP_MSG_TRAP: |
1223 | 0 | case SNMP_MSG_TRAP2: |
1224 | 0 | case SNMP_MSG_INFORM: |
1225 | 0 | viewtype = VACM_VIEW_NOTIFY; |
1226 | 0 | break; |
1227 | 0 | default: |
1228 | 0 | snmp_log(LOG_ERR, "bad msg type in vacm_in_view: %d\n", |
1229 | 0 | pdu->command); |
1230 | 0 | viewtype = VACM_VIEW_READ; |
1231 | 0 | } |
1232 | 0 | return vacm_check_view(pdu, name, namelen, check_subtree, viewtype); |
1233 | 0 | } |
1234 | | |
1235 | | /** |
1236 | | * vacm_check_view: decides if a given PDU can be taken based on a view type |
1237 | | * |
1238 | | * Parameters: |
1239 | | * *pdu |
1240 | | * *name |
1241 | | * namelen |
1242 | | * check_subtree |
1243 | | * viewtype |
1244 | | * |
1245 | | * Returns: |
1246 | | * VACM_SUCCESS(0) On success. |
1247 | | * VACM_NOSECNAME(1) Missing security name. |
1248 | | * VACM_NOGROUP(2) Missing group |
1249 | | * VACM_NOACCESS(3) Missing access |
1250 | | * VACM_NOVIEW(4) Missing view |
1251 | | * VACM_NOTINVIEW(5) Not in view |
1252 | | * VACM_NOSUCHCONTEXT(6) No Such Context |
1253 | | * VACM_SUBTREE_UNKNOWN(7) When testing an entire subtree, UNKNOWN (i.e., the entire |
1254 | | * subtree has both allowed and disallowed portions) |
1255 | | * |
1256 | | * Debug output listed as follows: |
1257 | | * \<securityName\> \<groupName\> \<viewName\> \<viewType\> |
1258 | | */ |
1259 | | int |
1260 | | vacm_check_view(netsnmp_pdu *pdu, oid * name, size_t namelen, |
1261 | | int check_subtree, int viewtype) |
1262 | 0 | { |
1263 | 0 | return vacm_check_view_contents(pdu, name, namelen, check_subtree, viewtype, |
1264 | 0 | VACM_CHECK_VIEW_CONTENTS_NO_FLAGS); |
1265 | 0 | } |
1266 | | |
1267 | | int |
1268 | | vacm_check_view_contents(netsnmp_pdu *pdu, oid * name, size_t namelen, |
1269 | | int check_subtree, int viewtype, int flags) |
1270 | 0 | { |
1271 | 0 | struct vacm_accessEntry *ap; |
1272 | 0 | struct vacm_groupEntry *gp; |
1273 | 0 | struct vacm_viewEntry *vp; |
1274 | 0 | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
1275 | 0 | char vacm_default_context[1] = ""; |
1276 | 0 | const char *contextName = vacm_default_context; |
1277 | 0 | const char *pdu_community; |
1278 | 0 | #endif |
1279 | 0 | const char *sn = NULL; |
1280 | 0 | char *vn; |
1281 | | |
1282 | | /* |
1283 | | * len defined by the vacmContextName object |
1284 | | */ |
1285 | 0 | #define CONTEXTNAMEINDEXLEN 32 |
1286 | 0 | char contextNameIndex[CONTEXTNAMEINDEXLEN + 1]; |
1287 | |
|
1288 | 0 | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
1289 | | #if defined(NETSNMP_DISABLE_SNMPV1) |
1290 | | if (pdu->version == SNMP_VERSION_2c) |
1291 | | #else |
1292 | | #if defined(NETSNMP_DISABLE_SNMPV2C) |
1293 | | if (pdu->version == SNMP_VERSION_1) |
1294 | | #else |
1295 | 0 | if (pdu->version == SNMP_VERSION_1 || pdu->version == SNMP_VERSION_2c) |
1296 | 0 | #endif |
1297 | 0 | #endif |
1298 | 0 | { |
1299 | 0 | pdu_community = (const char *) pdu->community; |
1300 | 0 | if (!pdu_community) |
1301 | 0 | pdu_community = ""; |
1302 | 0 | if (snmp_get_do_debugging()) { |
1303 | 0 | char *buf; |
1304 | 0 | if (pdu->community) { |
1305 | 0 | buf = (char *) malloc(1 + pdu->community_len); |
1306 | 0 | memcpy(buf, pdu->community, pdu->community_len); |
1307 | 0 | buf[pdu->community_len] = '\0'; |
1308 | 0 | } else { |
1309 | 0 | DEBUGMSGTL(("mibII/vacm_vars", "NULL community")); |
1310 | 0 | buf = strdup("NULL"); |
1311 | 0 | } |
1312 | |
|
1313 | 0 | DEBUGMSGTL(("mibII/vacm_vars", |
1314 | 0 | "vacm_in_view: ver=%ld, community=%s\n", |
1315 | 0 | pdu->version, buf ? buf : "NULL")); |
1316 | 0 | SNMP_FREE(buf); |
1317 | 0 | } |
1318 | | |
1319 | | /* |
1320 | | * Okay, if this PDU was received from a UDP or a TCP transport then |
1321 | | * ask the transport abstraction layer to map its source address and |
1322 | | * community string to a security name for us. |
1323 | | */ |
1324 | |
|
1325 | 0 | if (0) { |
1326 | 0 | #ifdef NETSNMP_TRANSPORT_UDP_DOMAIN |
1327 | 0 | } else if (pdu->tDomain == netsnmpUDPDomain |
1328 | 0 | #ifdef NETSNMP_TRANSPORT_TCP_DOMAIN |
1329 | 0 | || pdu->tDomain == netsnmp_snmpTCPDomain |
1330 | 0 | #endif |
1331 | 0 | ) { |
1332 | 0 | if (!netsnmp_udp_getSecName(pdu->transport_data, |
1333 | 0 | pdu->transport_data_length, |
1334 | 0 | pdu_community, |
1335 | 0 | pdu->community_len, &sn, |
1336 | 0 | &contextName)) { |
1337 | | /* |
1338 | | * There are no com2sec entries. |
1339 | | */ |
1340 | 0 | sn = NULL; |
1341 | 0 | } |
1342 | | /* force the community -> context name mapping here */ |
1343 | 0 | SNMP_FREE(pdu->contextName); |
1344 | 0 | pdu->contextName = strdup(contextName); |
1345 | 0 | pdu->contextNameLen = strlen(contextName); |
1346 | 0 | #endif |
1347 | 0 | #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN |
1348 | 0 | } else if (pdu->tDomain == netsnmp_UDPIPv6Domain |
1349 | 0 | #ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN |
1350 | 0 | || pdu->tDomain == netsnmp_TCPIPv6Domain |
1351 | 0 | #endif |
1352 | 0 | ) { |
1353 | 0 | if (!netsnmp_udp6_getSecName(pdu->transport_data, |
1354 | 0 | pdu->transport_data_length, |
1355 | 0 | pdu_community, |
1356 | 0 | pdu->community_len, &sn, |
1357 | 0 | &contextName)) { |
1358 | | /* |
1359 | | * There are no com2sec entries. |
1360 | | */ |
1361 | 0 | sn = NULL; |
1362 | 0 | } |
1363 | | /* force the community -> context name mapping here */ |
1364 | 0 | SNMP_FREE(pdu->contextName); |
1365 | 0 | pdu->contextName = strdup(contextName); |
1366 | 0 | pdu->contextNameLen = strlen(contextName); |
1367 | 0 | #endif |
1368 | 0 | #ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN |
1369 | 0 | } else if (pdu->tDomain == netsnmp_UnixDomain){ |
1370 | 0 | if (!netsnmp_unix_getSecName(pdu->transport_data, |
1371 | 0 | pdu->transport_data_length, |
1372 | 0 | pdu_community, |
1373 | 0 | pdu->community_len, &sn, |
1374 | 0 | &contextName)) { |
1375 | 0 | sn = NULL; |
1376 | 0 | } |
1377 | | /* force the community -> context name mapping here */ |
1378 | 0 | SNMP_FREE(pdu->contextName); |
1379 | 0 | pdu->contextName = strdup(contextName); |
1380 | 0 | pdu->contextNameLen = strlen(contextName); |
1381 | 0 | #endif |
1382 | 0 | } else { |
1383 | | /* |
1384 | | * Map other <community, transport-address> pairs to security names |
1385 | | * here. For now just let non-IPv4 transport always succeed. |
1386 | | * |
1387 | | * WHAAAATTTT. No, we don't let non-IPv4 transports |
1388 | | * succeed! You must fix this to make it usable, sorry. |
1389 | | * From a security standpoint this is insane. -- Wes |
1390 | | */ |
1391 | | /** @todo alternate com2sec mappings for non v4 transports. |
1392 | | Should be implemented via registration */ |
1393 | 0 | sn = NULL; |
1394 | 0 | } |
1395 | |
|
1396 | 0 | } else |
1397 | 0 | #endif /* !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) */ |
1398 | 0 | if (find_sec_mod(pdu->securityModel)) { |
1399 | | /* |
1400 | | * any legal defined v3 security model |
1401 | | */ |
1402 | 0 | DEBUGMSG(("mibII/vacm_vars", |
1403 | 0 | "vacm_in_view: ver=%ld, model=%d, secName=%s\n", |
1404 | 0 | pdu->version, pdu->securityModel, pdu->securityName)); |
1405 | 0 | sn = pdu->securityName; |
1406 | 0 | } else { |
1407 | 0 | sn = NULL; |
1408 | 0 | } |
1409 | |
|
1410 | 0 | if (sn == NULL) { |
1411 | 0 | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
1412 | 0 | snmp_increment_statistic(STAT_SNMPINBADCOMMUNITYNAMES); |
1413 | 0 | #endif |
1414 | 0 | DEBUGMSGTL(("mibII/vacm_vars", |
1415 | 0 | "vacm_in_view: No security name found\n")); |
1416 | 0 | return VACM_NOSECNAME; |
1417 | 0 | } |
1418 | | |
1419 | 0 | if (pdu->contextNameLen > CONTEXTNAMEINDEXLEN) { |
1420 | 0 | DEBUGMSGTL(("mibII/vacm_vars", |
1421 | 0 | "vacm_in_view: bad ctxt length %d\n", |
1422 | 0 | (int)pdu->contextNameLen)); |
1423 | 0 | return VACM_NOSUCHCONTEXT; |
1424 | 0 | } |
1425 | | /* |
1426 | | * NULL termination of the pdu field is ugly here. Do in PDU parsing? |
1427 | | */ |
1428 | 0 | if (pdu->contextName) |
1429 | 0 | memcpy(contextNameIndex, pdu->contextName, pdu->contextNameLen); |
1430 | 0 | else |
1431 | 0 | contextNameIndex[0] = '\0'; |
1432 | |
|
1433 | 0 | contextNameIndex[pdu->contextNameLen] = '\0'; |
1434 | 0 | if (!(flags & VACM_CHECK_VIEW_CONTENTS_DNE_CONTEXT_OK) && |
1435 | 0 | !netsnmp_subtree_find_first(contextNameIndex)) { |
1436 | | /* |
1437 | | * rfc 3415 section 3.2, step 1 |
1438 | | * no such context here; return no such context error |
1439 | | */ |
1440 | 0 | DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: no such ctxt \"%s\"\n", |
1441 | 0 | contextNameIndex)); |
1442 | 0 | return VACM_NOSUCHCONTEXT; |
1443 | 0 | } |
1444 | | |
1445 | 0 | DEBUGMSGTL(("mibII/vacm_vars", "vacm_in_view: sn=%s", sn)); |
1446 | |
|
1447 | 0 | gp = vacm_getGroupEntry(pdu->securityModel, sn); |
1448 | 0 | if (gp == NULL) { |
1449 | 0 | DEBUGMSG(("mibII/vacm_vars", "\n")); |
1450 | 0 | return VACM_NOGROUP; |
1451 | 0 | } |
1452 | 0 | DEBUGMSG(("mibII/vacm_vars", ", gn=%s", gp->groupName)); |
1453 | |
|
1454 | 0 | ap = vacm_getAccessEntry(gp->groupName, contextNameIndex, |
1455 | 0 | pdu->securityModel, pdu->securityLevel); |
1456 | 0 | if (ap == NULL) { |
1457 | 0 | DEBUGMSG(("mibII/vacm_vars", "\n")); |
1458 | 0 | return VACM_NOACCESS; |
1459 | 0 | } |
1460 | | |
1461 | 0 | if (name == NULL) { /* only check the setup of the vacm for the request */ |
1462 | 0 | DEBUGMSG(("mibII/vacm_vars", ", Done checking setup\n")); |
1463 | 0 | return VACM_SUCCESS; |
1464 | 0 | } |
1465 | | |
1466 | 0 | if (viewtype < 0 || viewtype >= VACM_MAX_VIEWS) { |
1467 | 0 | DEBUGMSG(("mibII/vacm_vars", " illegal view type\n")); |
1468 | 0 | return VACM_NOACCESS; |
1469 | 0 | } |
1470 | 0 | vn = ap->views[viewtype]; |
1471 | 0 | DEBUGMSG(("mibII/vacm_vars", ", vn=%s", vn)); |
1472 | |
|
1473 | 0 | if (check_subtree) { |
1474 | 0 | DEBUGMSG(("mibII/vacm_vars", "\n")); |
1475 | 0 | return vacm_checkSubtree(vn, name, namelen); |
1476 | 0 | } |
1477 | | |
1478 | 0 | vp = vacm_getViewEntry(vn, name, namelen, VACM_MODE_FIND); |
1479 | |
|
1480 | 0 | if (vp == NULL) { |
1481 | 0 | DEBUGMSG(("mibII/vacm_vars", "\n")); |
1482 | 0 | return VACM_NOVIEW; |
1483 | 0 | } |
1484 | 0 | DEBUGMSG(("mibII/vacm_vars", ", vt=%d\n", vp->viewType)); |
1485 | |
|
1486 | 0 | if (vp->viewType == SNMP_VIEW_EXCLUDED) { |
1487 | 0 | #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) |
1488 | | #if defined(NETSNMP_DISABLE_SNMPV1) |
1489 | | if (pdu->version == SNMP_VERSION_2c) |
1490 | | #else |
1491 | | #if defined(NETSNMP_DISABLE_SNMPV2C) |
1492 | | if (pdu->version == SNMP_VERSION_1) |
1493 | | #else |
1494 | 0 | if (pdu->version == SNMP_VERSION_1 || pdu->version == SNMP_VERSION_2c) |
1495 | 0 | #endif |
1496 | 0 | #endif |
1497 | 0 | { |
1498 | 0 | snmp_increment_statistic(STAT_SNMPINBADCOMMUNITYUSES); |
1499 | 0 | } |
1500 | 0 | #endif |
1501 | 0 | return VACM_NOTINVIEW; |
1502 | 0 | } |
1503 | | |
1504 | 0 | return VACM_SUCCESS; |
1505 | |
|
1506 | 0 | } /* end vacm_in_view() */ |
1507 | | |
1508 | | |