Coverage Report

Created: 2026-09-04 09:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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