/src/net-snmp/agent/mibgroup/utilities/iquery.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Portions of this file are copyrighted by: |
3 | | * Copyright (c) 2016 VMware, Inc. All rights reserved. |
4 | | * Use is subject to license terms specified in the COPYING file |
5 | | * distributed with the Net-SNMP package. |
6 | | */ |
7 | | #include <net-snmp/net-snmp-config.h> |
8 | | #include <net-snmp/net-snmp-features.h> |
9 | | #include <net-snmp/net-snmp-includes.h> |
10 | | #include <net-snmp/agent/net-snmp-agent-includes.h> |
11 | | |
12 | | #include "agent_global_vars.h" |
13 | | #include "agentx/subagent.h" |
14 | | #include "utilities/iquery.h" |
15 | | |
16 | | netsnmp_feature_child_of(iquery_all, libnetsnmpmibs); |
17 | | netsnmp_feature_child_of(iquery, iquery_all); |
18 | | netsnmp_feature_child_of(iquery_community_session, iquery_all); |
19 | | netsnmp_feature_child_of(iquery_pdu_session, iquery_all); |
20 | | |
21 | | netsnmp_feature_require(query_set_default_session); |
22 | | |
23 | | #ifndef NETSNMP_FEATURE_REMOVE_IQUERY |
24 | | |
25 | | void |
26 | | netsnmp_parse_iquerySecLevel(const char *token, char *line) |
27 | 0 | { |
28 | 0 | int secLevel; |
29 | |
|
30 | 0 | #ifndef NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION |
31 | 0 | if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
32 | 0 | NETSNMP_DS_LIB_DISABLE_V3)) { |
33 | 0 | netsnmp_config_error("SNMPv3 disabled"); |
34 | 0 | } else |
35 | 0 | #endif |
36 | 0 | if ((secLevel = parse_secLevel_conf( token, line )) >= 0 ) { |
37 | 0 | netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, |
38 | 0 | NETSNMP_DS_AGENT_INTERNAL_SECLEVEL, secLevel); |
39 | 0 | } else { |
40 | 0 | netsnmp_config_error("Unknown security level: %s", line); |
41 | 0 | } |
42 | 0 | } |
43 | | |
44 | | void |
45 | | netsnmp_parse_iqueryVersion(const char *token, char *line) |
46 | 0 | { |
47 | 0 | #ifndef NETSNMP_DISABLE_SNMPV1 |
48 | 0 | if (!strcmp( line, "1" ) |
49 | 0 | #ifndef NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION |
50 | 0 | && !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
51 | 0 | NETSNMP_DS_LIB_DISABLE_V1) |
52 | 0 | #endif |
53 | 0 | ) |
54 | 0 | netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, |
55 | 0 | NETSNMP_DS_AGENT_INTERNAL_VERSION, SNMP_VERSION_1); |
56 | 0 | else |
57 | 0 | #endif |
58 | 0 | #ifndef NETSNMP_DISABLE_SNMPV2C |
59 | 0 | if ((!strcmp( line, "2" ) || !strcasecmp( line, "2c" )) |
60 | 0 | #ifndef NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION |
61 | 0 | && !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
62 | 0 | NETSNMP_DS_LIB_DISABLE_V2c) |
63 | 0 | #endif |
64 | 0 | ) |
65 | 0 | netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, |
66 | 0 | NETSNMP_DS_AGENT_INTERNAL_VERSION, SNMP_VERSION_2c); |
67 | 0 | else |
68 | 0 | #endif |
69 | 0 | if (!strcmp( line, "3" ) |
70 | 0 | #ifndef NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION |
71 | 0 | && !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, |
72 | 0 | NETSNMP_DS_LIB_DISABLE_V3) |
73 | 0 | #endif |
74 | 0 | ) |
75 | 0 | netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, |
76 | 0 | NETSNMP_DS_AGENT_INTERNAL_VERSION, SNMP_VERSION_3); |
77 | 0 | else { |
78 | 0 | netsnmp_config_error("Unknown/disabled version: %s", line); |
79 | 0 | } |
80 | 0 | } |
81 | | |
82 | | /* |
83 | | * Set up a default session for running internal queries. |
84 | | * This needs to be done before the config files are read, |
85 | | * so that it is available for "monitor" directives... |
86 | | */ |
87 | | int |
88 | | _init_default_iquery_session( int majorID, int minorID, |
89 | | void *serverargs, void *clientarg) |
90 | 2.62k | { |
91 | 2.62k | char *secName = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, |
92 | 2.62k | NETSNMP_DS_AGENT_INTERNAL_SECNAME); |
93 | 2.62k | if (secName) |
94 | 0 | netsnmp_query_set_default_session( |
95 | 0 | netsnmp_iquery_user_session(secName)); |
96 | 2.62k | return SNMPERR_SUCCESS; |
97 | 2.62k | } |
98 | | |
99 | | /* |
100 | | * ... Unfortunately, the internal engine ID is not set up |
101 | | * until later, so this default session is incomplete. |
102 | | * The resulting engineID probe runs into problems, |
103 | | * causing the very first internal query to time out. |
104 | | * Updating the default session with the internal engineID |
105 | | * once it has been set, fixes this problem. |
106 | | */ |
107 | | int |
108 | | _tweak_default_iquery_session( int majorID, int minorID, |
109 | | void *serverargs, void *clientarg) |
110 | 2.62k | { |
111 | 2.62k | u_char eID[SNMP_MAXBUF_SMALL]; |
112 | 2.62k | size_t elen; |
113 | 2.62k | netsnmp_session *s = netsnmp_query_get_default_session_unchecked(); |
114 | | |
115 | 2.62k | if ( s && s->securityEngineIDLen == 0 ) { |
116 | 0 | elen = snmpv3_get_engineID(eID, sizeof(eID)); |
117 | 0 | s->securityEngineID = netsnmp_memdup(eID, elen); |
118 | 0 | s->securityEngineIDLen = elen; |
119 | 0 | } |
120 | 2.62k | return SNMPERR_SUCCESS; |
121 | 2.62k | } |
122 | | |
123 | 2.62k | void init_iquery(void){ |
124 | 2.62k | char *type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, |
125 | 2.62k | NETSNMP_DS_LIB_APPTYPE); |
126 | 2.62k | netsnmp_ds_register_premib(ASN_OCTET_STR, type, "agentSecName", |
127 | 2.62k | NETSNMP_DS_APPLICATION_ID, |
128 | 2.62k | NETSNMP_DS_AGENT_INTERNAL_SECNAME); |
129 | 2.62k | netsnmp_ds_register_premib(ASN_OCTET_STR, type, "iquerySecName", |
130 | 2.62k | NETSNMP_DS_APPLICATION_ID, |
131 | 2.62k | NETSNMP_DS_AGENT_INTERNAL_SECNAME); |
132 | | |
133 | 2.62k | snmpd_register_config_handler("iqueryVersion", |
134 | 2.62k | netsnmp_parse_iqueryVersion, NULL, |
135 | 2.62k | "1 | 2c | 3"); |
136 | 2.62k | snmpd_register_config_handler("iquerySecLevel", |
137 | 2.62k | netsnmp_parse_iquerySecLevel, NULL, |
138 | 2.62k | "noAuthNoPriv | authNoPriv | authPriv"); |
139 | | |
140 | | /* |
141 | | * Set defaults |
142 | | */ |
143 | 2.62k | netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, |
144 | 2.62k | NETSNMP_DS_AGENT_INTERNAL_VERSION, SNMP_VERSION_3); |
145 | 2.62k | netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, |
146 | 2.62k | NETSNMP_DS_AGENT_INTERNAL_SECLEVEL, SNMP_SEC_LEVEL_AUTHNOPRIV); |
147 | | |
148 | 2.62k | snmp_register_callback(SNMP_CALLBACK_LIBRARY, |
149 | 2.62k | SNMP_CALLBACK_POST_PREMIB_READ_CONFIG, |
150 | 2.62k | _init_default_iquery_session, NULL); |
151 | 2.62k | snmp_register_callback(SNMP_CALLBACK_LIBRARY, |
152 | 2.62k | SNMP_CALLBACK_POST_READ_CONFIG, |
153 | 2.62k | _tweak_default_iquery_session, NULL); |
154 | 2.62k | } |
155 | | |
156 | | /************************** |
157 | | * |
158 | | * APIs to construct an "internal query" session |
159 | | * |
160 | | **************************/ |
161 | | |
162 | | #ifndef NETSNMP_FEATURE_REMOVE_IQUERY_PDU_SESSION |
163 | 0 | netsnmp_session *netsnmp_iquery_pdu_session(netsnmp_pdu* pdu) { |
164 | 0 | if (!pdu || NETSNMP_RUNTIME_PROTOCOL_SKIP(pdu->version)) |
165 | 0 | return NULL; |
166 | 0 | if (pdu->version == SNMP_VERSION_3) |
167 | 0 | return netsnmp_iquery_session( pdu->securityName, |
168 | 0 | pdu->version, |
169 | 0 | pdu->securityModel, |
170 | 0 | pdu->securityLevel, |
171 | 0 | pdu->securityEngineID, |
172 | 0 | pdu->securityEngineIDLen); |
173 | 0 | else |
174 | 0 | return netsnmp_iquery_session((char *) pdu->community, |
175 | |
|
176 | 0 | pdu->version, |
177 | 0 | pdu->version+1, |
178 | 0 | SNMP_SEC_LEVEL_NOAUTH, |
179 | 0 | pdu->securityEngineID, |
180 | 0 | pdu->securityEngineIDLen); |
181 | 0 | } |
182 | | #endif /* NETSNMP_FEATURE_REMOVE_IQUERY_PDU_SESSION */ |
183 | | |
184 | 0 | netsnmp_session *netsnmp_iquery_user_session(char* secName){ |
185 | 0 | u_char eID[SNMP_MAXBUF_SMALL]; |
186 | 0 | size_t elen = snmpv3_get_engineID(eID, sizeof(eID)); |
187 | |
|
188 | 0 | return netsnmp_iquery_session( secName, |
189 | 0 | SNMP_VERSION_3, |
190 | 0 | SNMP_SEC_MODEL_USM, |
191 | 0 | SNMP_SEC_LEVEL_AUTHNOPRIV, eID, elen); |
192 | 0 | } |
193 | | |
194 | | #ifndef NETSNMP_FEATURE_REMOVE_IQUERY_COMMUNITY_SESSION |
195 | 0 | netsnmp_session *netsnmp_iquery_community_session( char* community, int version ) { |
196 | 0 | u_char eID[SNMP_MAXBUF_SMALL]; |
197 | 0 | size_t elen = snmpv3_get_engineID(eID, sizeof(eID)); |
198 | |
|
199 | 0 | return netsnmp_iquery_session( community, version, version+1, |
200 | 0 | SNMP_SEC_LEVEL_NOAUTH, eID, elen); |
201 | 0 | } |
202 | | #endif /* NETSNMP_FEATURE_REMOVE_IQUERY_COMMUNITY_SESSION */ |
203 | | |
204 | | netsnmp_session *netsnmp_iquery_session(char* secName, int version, |
205 | | int secModel, int secLevel, |
206 | 0 | u_char* engineID, size_t engIDLen) { |
207 | | |
208 | | /* |
209 | | * This routine creates a completely new session every time. |
210 | | * It might be worth keeping track of which 'secNames' already |
211 | | * have iquery sessions created, and re-using the appropriate one. |
212 | | */ |
213 | 0 | netsnmp_session *ss = NULL; |
214 | |
|
215 | 0 | NETSNMP_RUNTIME_PROTOCOL_CHECK(version, unsupported_version); |
216 | | |
217 | 0 | #ifdef NETSNMP_TRANSPORT_CALLBACK_DOMAIN |
218 | 0 | ss = netsnmp_callback_open( callback_master_num, NULL, NULL, NULL); |
219 | 0 | if (ss) { |
220 | 0 | ss->version = version; |
221 | 0 | ss->securityModel = secModel; |
222 | 0 | ss->securityLevel = secLevel; |
223 | 0 | ss->securityEngineID = netsnmp_memdup(engineID, engIDLen); |
224 | 0 | ss->securityEngineIDLen = engIDLen; |
225 | 0 | if ( version == SNMP_VERSION_3 ) { |
226 | 0 | ss->securityNameLen = strlen(secName); |
227 | 0 | ss->securityName = netsnmp_memdup(secName, ss->securityNameLen + 1); |
228 | 0 | } else { |
229 | 0 | ss->community = netsnmp_memdup(secName, strlen(secName)); |
230 | 0 | ss->community_len = strlen(secName); |
231 | 0 | } |
232 | 0 | ss->myvoid = (void *)netsnmp_check_outstanding_agent_requests; |
233 | 0 | ss->flags |= SNMP_FLAGS_RESP_CALLBACK | SNMP_FLAGS_DONT_PROBE; |
234 | 0 | } |
235 | 0 | #endif |
236 | |
|
237 | 0 | unsupported_version: |
238 | 0 | return ss; |
239 | 0 | } |
240 | | |
241 | | #else /* NETSNMP_FEATURE_REMOVE_IQUERY */ |
242 | | netsnmp_feature_unused(iquery); |
243 | | #endif /* NETSNMP_FEATURE_REMOVE_IQUERY */ |
244 | | |