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