Coverage Report

Created: 2024-09-11 06:05

/src/net-snmp/agent/snmp_vars.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * snmp_vars.c - return a pointer to the named variable.
3
 */
4
/**
5
 * @addtogroup library
6
 *
7
 * @{
8
 */
9
/* Portions of this file are subject to the following copyright(s).  See
10
 * the Net-SNMP's COPYING file for more details and other copyrights
11
 * that may apply:
12
 */
13
/* Portions of this file are subject to the following copyright(s).  See
14
 * the Net-SNMP's COPYING file for more details and other copyrights
15
 * that may apply:
16
 */
17
/***********************************************************
18
  Copyright 1988, 1989, 1990 by Carnegie Mellon University
19
  Copyright 1989  TGV, Incorporated
20
21
          All Rights Reserved
22
23
Permission to use, copy, modify, and distribute this software and its
24
documentation for any purpose and without fee is hereby granted,
25
provided that the above copyright notice appear in all copies and that
26
both that copyright notice and this permission notice appear in
27
supporting documentation, and that the name of CMU and TGV not be used
28
in advertising or publicity pertaining to distribution of the software
29
without specific, written prior permission.
30
31
CMU AND TGV DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
32
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
33
EVENT SHALL CMU OR TGV BE LIABLE FOR ANY SPECIAL, INDIRECT OR
34
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
35
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
36
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
37
PERFORMANCE OF THIS SOFTWARE.
38
******************************************************************/
39
/*
40
 * Portions of this file are copyrighted by:
41
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
42
 * Use is subject to license terms specified in the COPYING file
43
 * distributed with the Net-SNMP package.
44
 *
45
 * Portions of this file are copyrighted by:
46
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
47
 * Use is subject to license terms specified in the COPYING file
48
 * distributed with the Net-SNMP package.
49
 */
50
51
/*
52
 * additions, fixes and enhancements for Linux by Erik Schoenfelder
53
 * (schoenfr@ibr.cs.tu-bs.de) 1994/1995.
54
 * Linux additions taken from CMU to UCD stack by Jennifer Bray of Origin
55
 * (jbray@origin-at.co.uk) 1997
56
 */
57
58
/*
59
 * XXXWWW merge todo: incl/excl range changes in differences between
60
 * 1.194 and 1.199 
61
 */
62
63
#include <net-snmp/net-snmp-config.h>
64
#ifdef HAVE_SYS_PARAM_H
65
#include <sys/param.h>
66
#endif
67
#ifdef HAVE_STRING_H
68
#include <string.h>
69
#endif
70
#ifdef HAVE_STDLIB_H
71
#include <stdlib.h>
72
#endif
73
#include <sys/types.h>
74
#include <stdio.h>
75
#include <fcntl.h>
76
#include <errno.h>
77
78
#ifdef TIME_WITH_SYS_TIME
79
# include <sys/time.h>
80
# include <time.h>
81
#else
82
# ifdef HAVE_SYS_TIME_H
83
#  include <sys/time.h>
84
# else
85
#  include <time.h>
86
# endif
87
#endif
88
#ifdef HAVE_SYS_SOCKET_H
89
# include <sys/socket.h>
90
#endif
91
#ifdef HAVE_SYS_STREAM_H
92
#   ifdef sysv5UnixWare7
93
#      define _KMEMUSER 1 /* <sys/stream.h> needs this for queue_t */
94
#   endif
95
#include <sys/stream.h>
96
#endif
97
#ifdef HAVE_SYS_SOCKETVAR_H
98
# include <sys/socketvar.h>
99
#endif
100
#ifdef HAVE_NETINET_IN_H
101
#include <netinet/in.h>
102
#endif
103
#ifdef HAVE_NETINET_IN_SYSTM_H
104
#include <netinet/in_systm.h>
105
#endif
106
#ifdef HAVE_NETINET_IP_H
107
#include <netinet/ip.h>
108
#endif
109
#ifdef NETSNMP_ENABLE_IPV6
110
#ifdef HAVE_NETINET_IP6_H
111
#include <netinet/ip6.h>
112
#endif
113
#endif
114
#ifdef HAVE_SYS_QUEUE_H
115
#include <sys/queue.h>
116
#endif
117
#ifdef HAVE_NET_ROUTE_H
118
#include <net/route.h>
119
#endif
120
#ifdef HAVE_NETINET_IP_VAR_H
121
#include <netinet/ip_var.h>
122
#endif
123
#ifdef NETSNMP_ENABLE_IPV6
124
#ifdef HAVE_NETNETSNMP_ENABLE_IPV6_IP6_VAR_H
125
#include <netinet6/ip6_var.h>
126
#endif
127
#endif
128
#ifdef HAVE_NETINET_IN_PCB_H
129
#include <netinet/in_pcb.h>
130
#endif
131
#ifdef HAVE_INET_MIB2_H
132
#include <inet/mib2.h>
133
#endif
134
135
#include <net-snmp/net-snmp-includes.h>
136
#include <net-snmp/agent/net-snmp-agent-includes.h>
137
#include <net-snmp/agent/mib_modules.h>
138
#include <net-snmp/agent/agent_sysORTable.h>
139
#include "agent_global_vars.h"
140
#include "kernel.h"
141
142
#include "mibgroup/struct.h"
143
#include "snmpd.h"
144
#include "agentx/agentx_config.h"
145
#include "agentx/subagent.h"
146
#include "net-snmp/agent/all_helpers.h"
147
#include "agent_module_includes.h"
148
#include "net-snmp/library/container.h"
149
150
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL)
151
#include <openssl/ssl.h>
152
#include <openssl/x509v3.h>
153
#include <net-snmp/library/cert_util.h>
154
#endif
155
156
#include "snmp_perl.h"
157
158
#ifndef  MIN
159
#define  MIN(a,b)                     (((a) < (b)) ? (a) : (b))
160
#endif
161
162
static char     done_init_agent = 0;
163
164
struct module_init_list *initlist = NULL;
165
struct module_init_list *noinitlist = NULL;
166
167
/*
168
 *      Each variable name is placed in the variable table, without the
169
 * terminating substring that determines the instance of the variable.  When
170
 * a string is found that is lexicographicly preceded by the input string,
171
 * the function for that entry is called to find the method of access of the
172
 * instance of the named variable.  If that variable is not found, NULL is
173
 * returned, and the search through the table continues (it will probably
174
 * stop at the next entry).  If it is found, the function returns a character
175
 * pointer and a length or a function pointer.  The former is the address
176
 * of the operand, the latter is a write routine for the variable.
177
 *
178
 * u_char *
179
 * findVar(name, length, exact, var_len, write_method)
180
 * oid      *name;          IN/OUT - input name requested, output name found
181
 * int      length;         IN/OUT - number of sub-ids in the in and out oid's
182
 * int      exact;          IN - TRUE if an exact match was requested.
183
 * int      len;            OUT - length of variable or 0 if function returned.
184
 * int      write_method;   OUT - pointer to function to set variable,
185
 *                                otherwise 0
186
 *
187
 *     The writeVar function is returned to handle row addition or complex
188
 * writes that require boundary checking or executing an action.
189
 * This routine will be called three times for each varbind in the packet.
190
 * The first time for each varbind, action is set to RESERVE1.  The type
191
 * and value should be checked during this pass.  If any other variables
192
 * in the MIB depend on this variable, this variable will be stored away
193
 * (but *not* committed!) in a place where it can be found by a call to
194
 * writeVar for a dependent variable, even in the same PDU.  During
195
 * the second pass, action is set to RESERVE2.  If this variable is dependent
196
 * on any other variables, it will check them now.  It must check to see
197
 * if any non-committed values have been stored for variables in the same
198
 * PDU that it depends on.  Sometimes resources will need to be reserved
199
 * in the first two passes to guarantee that the operation can proceed
200
 * during the third pass.  During the third pass, if there were no errors
201
 * in the first two passes, writeVar is called for every varbind with action
202
 * set to COMMIT.  It is now that the values should be written.  If there
203
 * were errors during the first two passes, writeVar is called in the third
204
 * pass once for each varbind, with the action set to FREE.  An opportunity
205
 * is thus provided to free those resources reserved in the first two passes.
206
 * 
207
 * writeVar(action, var_val, var_val_type, var_val_len, statP, name, name_len)
208
 * int      action;         IN - RESERVE1, RESERVE2, COMMIT, or FREE
209
 * u_char   *var_val;       IN - input or output buffer space
210
 * u_char   var_val_type;   IN - type of input buffer
211
 * int      var_val_len;    IN - input and output buffer len
212
 * u_char   *statP;         IN - pointer to local statistic
213
 * oid      *name           IN - pointer to name requested
214
 * int      name_len        IN - number of sub-ids in the name
215
 */
216
217
long            long_return;
218
#ifndef ibm032
219
u_char          return_buf[258];
220
#else
221
u_char          return_buf[256];        /* nee 64 */
222
#endif
223
224
static int
225
_warn_if_all_disabled(int maj, int min, void *serverarg, void *clientarg);
226
227
int             callback_master_num = -1;
228
229
#ifdef NETSNMP_TRANSPORT_CALLBACK_DOMAIN
230
netsnmp_session *callback_master_sess = NULL;
231
232
static void
233
_init_agent_callback_transport(void)
234
2.62k
{
235
    /*
236
     * always register a callback transport for internal use 
237
     */
238
2.62k
    callback_master_sess = netsnmp_callback_open(0, handle_snmp_packet,
239
2.62k
                                                 netsnmp_agent_check_packet,
240
2.62k
                                                 netsnmp_agent_check_parse);
241
2.62k
    if (callback_master_sess)
242
2.62k
        callback_master_num = callback_master_sess->local_port;
243
2.62k
}
244
#else
245
#define _init_agent_callback_transport()
246
#endif
247
248
/**
249
 * Initialize the agent.  Calls into init_agent_read_config to set that app's
250
 * configuration file in the appropriate default storage space,
251
 *  NETSNMP_DS_LIB_APPTYPE.  Need to call init_agent before calling init_snmp.
252
 *
253
 * @param app the configuration file to be read in, gets stored in default
254
 *        storage
255
 *
256
 * @return Returns non-zero on failure and zero on success.
257
 *
258
 * @see init_snmp
259
 */
260
int
261
init_agent(const char *app)
262
2.62k
{
263
2.62k
    int             r = 0;
264
265
2.62k
    if(++done_init_agent > 1) {
266
0
        snmp_log(LOG_WARNING, "ignoring extra call to init_agent (%d)\n", 
267
0
                 done_init_agent);
268
0
        return r;
269
0
    }
270
271
    /*
272
     * get current time (ie, the time the agent started) 
273
     */
274
2.62k
    netsnmp_set_agent_starttime(NULL);
275
276
    /*
277
     * we handle alarm signals ourselves in the select loop 
278
     */
279
2.62k
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
280
2.62k
         NETSNMP_DS_LIB_ALARM_DONT_USE_SIG, 1);
281
282
2.62k
    r = init_kmem("/dev/kmem") ? 0 : -EACCES;
283
284
2.62k
    setup_tree();
285
286
2.62k
    init_agent_read_config(app);
287
288
#ifdef TESTING
289
    auto_nlist_print_tree(-2, 0);
290
#endif
291
292
2.62k
    _init_agent_callback_transport();
293
294
2.62k
#ifndef NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION
295
2.62k
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
296
2.62k
                           SNMP_CALLBACK_POST_READ_CONFIG,
297
2.62k
                           _warn_if_all_disabled, NULL);
298
2.62k
#endif /* NETSNMP_FEATURE_REMOVE_RUNTIME_DISABLE_VERSION */
299
300
2.62k
    netsnmp_init_helpers();
301
2.62k
    init_traps();
302
2.62k
    netsnmp_container_init_list();
303
2.62k
    init_agent_sysORTable();
304
305
2.62k
#if defined(USING_AGENTX_SUBAGENT_MODULE) || defined(USING_AGENTX_MASTER_MODULE)
306
    /*
307
     * initialize agentx configs
308
     */
309
2.62k
    agentx_config_init();
310
2.62k
#if defined(USING_AGENTX_SUBAGENT_MODULE)
311
2.62k
    if(netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
312
2.62k
                              NETSNMP_DS_AGENT_ROLE) == SUB_AGENT)
313
0
        subagent_init();
314
2.62k
#endif
315
2.62k
#endif
316
317
    /*
318
     * Register configuration tokens from transport modules.  
319
     */
320
2.62k
#ifdef NETSNMP_TRANSPORT_UDP_DOMAIN
321
2.62k
    netsnmp_udp_agent_config_tokens_register();
322
2.62k
#endif
323
2.62k
#ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
324
2.62k
    netsnmp_udp6_agent_config_tokens_register();
325
2.62k
#endif
326
2.62k
#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
327
2.62k
    netsnmp_unix_agent_config_tokens_register();
328
2.62k
#endif
329
330
#ifdef NETSNMP_EMBEDDED_PERL
331
    init_perl();
332
#endif
333
334
2.62k
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && NETSNMP_TRANSPORT_TLSBASE_DOMAIN
335
    /** init secname mapping */
336
2.62k
    netsnmp_certs_agent_init();
337
2.62k
#endif
338
339
2.62k
#ifdef USING_AGENTX_SUBAGENT_MODULE
340
    /*
341
     * don't init agent modules for a sub-agent
342
     */
343
2.62k
    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
344
2.62k
             NETSNMP_DS_AGENT_ROLE) == SUB_AGENT)
345
0
        return r;
346
2.62k
#endif
347
348
2.62k
#  include "agent_module_inits.h"
349
350
2.62k
    return r;
351
2.62k
}                               /* end init_agent() */
352
353
const oid       nullOid[] = { 0, 0 };
354
const int       nullOidLen = sizeof(nullOid);
355
356
void
357
shutdown_agent(void)
358
2.62k
{
359
2.62k
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && NETSNMP_TRANSPORT_TLSBASE_DOMAIN
360
2.62k
    netsnmp_certs_shutdown();
361
2.62k
#endif
362
    /* probably some of this can be called as shutdown callback */
363
2.62k
    shutdown_tree();
364
2.62k
    clear_context();
365
2.62k
    netsnmp_clear_callback_list();
366
2.62k
    netsnmp_clear_tdomain_list();
367
2.62k
    netsnmp_clear_handler_list();
368
2.62k
    shutdown_agent_sysORTable();
369
2.62k
    netsnmp_container_free_list();
370
2.62k
    clear_sec_mod();
371
2.62k
    clear_snmp_enum();
372
2.62k
    clear_callback();
373
2.62k
    shutdown_secmod();
374
2.62k
    netsnmp_addrcache_destroy();
375
2.62k
    free_kmem();
376
377
2.62k
    done_init_agent = 0;
378
2.62k
}
379
380
381
void
382
add_to_init_list(char *module_list)
383
2.62k
{
384
2.62k
    struct module_init_list *newitem, **list;
385
2.62k
    char           *cp;
386
2.62k
    char           *st;
387
388
2.62k
    if (module_list == NULL) {
389
0
        return;
390
2.62k
    } else {
391
2.62k
        cp = (char *) module_list;
392
2.62k
    }
393
394
2.62k
    if (*cp == '-' || *cp == '!') {
395
2.62k
        cp++;
396
2.62k
        list = &noinitlist;
397
2.62k
    } else {
398
0
        list = &initlist;
399
0
    }
400
401
2.62k
    cp = strtok_r(cp, ", :", &st);
402
5.25k
    while (cp) {
403
2.62k
        newitem = calloc(1, sizeof(*initlist));
404
2.62k
        newitem->module_name = strdup(cp);
405
2.62k
        newitem->next = *list;
406
2.62k
        *list = newitem;
407
2.62k
        cp = strtok_r(NULL, ", :", &st);
408
2.62k
    }
409
2.62k
}
410
411
int
412
should_init(const char *module_name)
413
13.1k
{
414
13.1k
    struct module_init_list *listp;
415
416
    /*
417
     * a definitive list takes priority 
418
     */
419
13.1k
    if (initlist) {
420
0
        listp = initlist;
421
0
        while (listp) {
422
0
            if (strcmp(listp->module_name, module_name) == 0) {
423
0
                DEBUGMSGTL(("mib_init", "initializing: %s\n",
424
0
                            module_name));
425
0
                return DO_INITIALIZE;
426
0
            }
427
0
            listp = listp->next;
428
0
        }
429
0
        DEBUGMSGTL(("mib_init", "skipping:     %s\n", module_name));
430
0
        return DONT_INITIALIZE;
431
0
    }
432
433
    /*
434
     * initialize it only if not on the bad list (bad module, no bone) 
435
     */
436
13.1k
    if (noinitlist) {
437
13.1k
        listp = noinitlist;
438
10.3M
        while (listp) {
439
10.3M
            if (strcmp(listp->module_name, module_name) == 0) {
440
5.25k
                DEBUGMSGTL(("mib_init", "skipping:     %s\n",
441
5.25k
                            module_name));
442
5.25k
                return DONT_INITIALIZE;
443
5.25k
            }
444
10.3M
            listp = listp->next;
445
10.3M
        }
446
13.1k
    }
447
7.87k
    DEBUGMSGTL(("mib_init", "initializing: %s\n", module_name));
448
449
    /*
450
     * initialize it 
451
     */
452
7.87k
    return DO_INITIALIZE;
453
13.1k
}
454
455
static int
456
_warn_if_all_disabled(int maj, int min, void *serverarg, void *clientarg)
457
2.62k
{
458
2.62k
    const char * name = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
459
2.62k
                                              NETSNMP_DS_LIB_APPTYPE);
460
2.62k
    const int agent_mode =  netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
461
2.62k
                                                   NETSNMP_DS_AGENT_ROLE);
462
2.62k
    int enabled = 0;
463
2.62k
    if (NULL==name)
464
0
        name = "snmpd";
465
466
2.62k
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
467
2.62k
                                NETSNMP_DS_LIB_DISABLE_V3))
468
2.62k
        ++enabled;
469
2.62k
#ifndef NETSNMP_DISABLE_SNMPV2C
470
2.62k
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
471
2.62k
                                NETSNMP_DS_LIB_DISABLE_V2c))
472
2.62k
        ++enabled;
473
2.62k
#endif /* NETSNMP_DISABLE_SNMPV2C */
474
2.62k
#ifndef NETSNMP_DISABLE_SNMPV1
475
2.62k
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
476
2.62k
                                NETSNMP_DS_LIB_DISABLE_V1))
477
2.62k
        ++enabled;
478
2.62k
#endif /* NETSNMP_DISABLE_SNMPV1 */
479
480
2.62k
    if (0 == enabled) {
481
0
        if ((MASTER_AGENT == agent_mode) && (strcmp(name, "snmptrapd") != 0)) {
482
0
            snmp_log(LOG_WARNING,
483
0
                     "Warning: all protocol versions are runtime disabled.\n"
484
0
                 "  It's unlikely this agent can serve any useful purpose in this state.\n"
485
0
                     "  Check %s.conf file(s) for this agent.\n", name);
486
0
        } else if (!strcmp(name, "snmptrapd") &&
487
0
            !netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
488
0
                                    NETSNMP_DS_APP_NO_AUTHORIZATION)) {
489
0
            snmp_log(LOG_WARNING,
490
0
                     "Warning: all protocol versions are runtime disabled.\n"
491
0
                     "This receiver will *NOT* accept any incoming notifications.\n");
492
0
        }
493
0
    }
494
2.62k
    return SNMP_ERR_NOERROR;
495
2.62k
}
496
497
/**  @} */
498