1 /*
2  * agent_read_config.c
3  *
4  * Portions of this file are copyrighted by:
5  * Copyright (c) 2016 VMware, Inc. All rights reserved.
6  * Use is subject to license terms specified in the COPYING file
7  * distributed with the Net-SNMP package.
8  */
9 
10 #include <net-snmp/net-snmp-config.h>
11 #include <net-snmp/net-snmp-features.h>
12 
13 #if HAVE_SYS_PARAM_H
14 #include <sys/param.h>
15 #else
16 #include <sys/types.h>
17 #endif
18 #if HAVE_STDLIB_H
19 #include <stdlib.h>
20 #endif
21 #if HAVE_STRING_H
22 #include <string.h>
23 #else
24 #include <strings.h>
25 #endif
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <errno.h>
29 
30 #if TIME_WITH_SYS_TIME
31 # include <sys/time.h>
32 # include <time.h>
33 #else
34 # if HAVE_SYS_TIME_H
35 #  include <sys/time.h>
36 # else
37 #  include <time.h>
38 # endif
39 #endif
40 #if HAVE_NETINET_IN_H
41 #include <netinet/in.h>
42 #endif
43 #if HAVE_NETINET_IN_SYSTM_H
44 #include <netinet/in_systm.h>
45 #endif
46 #if HAVE_NETINET_IP_H
47 #include <netinet/ip.h>
48 #endif
49 #ifdef NETSNMP_ENABLE_IPV6
50 #if HAVE_NETINET_IP6_H
51 #include <netinet/ip6.h>
52 #endif
53 #endif
54 #if HAVE_SYS_QUEUE_H
55 #include <sys/queue.h>
56 #endif
57 #if HAVE_SYS_SOCKET_H
58 #include <sys/socket.h>
59 #if HAVE_SYS_SOCKETVAR_H
60 #ifndef dynix
61 #include <sys/socketvar.h>
62 #else
63 #include <sys/param.h>
64 #endif
65 #endif
66 #endif
67 #if HAVE_SYS_STREAM_H
68 #   ifdef sysv5UnixWare7
69 #      define _KMEMUSER 1   /* <sys/stream.h> needs this for queue_t */
70 #   endif
71 #include <sys/stream.h>
72 #endif
73 #if HAVE_NET_ROUTE_H
74 #include <net/route.h>
75 #endif
76 #if HAVE_NETINET_IP_VAR_H
77 #include <netinet/ip_var.h>
78 #endif
79 #ifdef NETSNMP_ENABLE_IPV6
80 #if HAVE_NETNETSNMP_ENABLE_IPV6_IP6_VAR_H
81 #include <netinet6/ip6_var.h>
82 #endif
83 #endif
84 #if HAVE_NETINET_IN_PCB_H
85 #include <netinet/in_pcb.h>
86 #endif
87 #if HAVE_INET_MIB2_H
88 #include <inet/mib2.h>
89 #endif
90 
91 #if HAVE_UNISTD_H
92 #include <unistd.h>
93 #endif
94 #ifdef HAVE_PWD_H
95 #include <pwd.h>
96 #endif
97 #ifdef HAVE_GRP_H
98 #include <grp.h>
99 #endif
100 
101 #include <net-snmp/net-snmp-includes.h>
102 #include <net-snmp/agent/net-snmp-agent-includes.h>
103 
104 #include "mibgroup/struct.h"
105 #include <net-snmp/agent/agent_trap.h>
106 #include "snmpd.h"
107 #include <net-snmp/agent/agent_callbacks.h>
108 #include <net-snmp/agent/table.h>
109 #include <net-snmp/agent/table_iterator.h>
110 #include <net-snmp/agent/table_data.h>
111 #include <net-snmp/agent/table_dataset.h>
112 #include "agent_module_includes.h"
113 #include "mib_module_includes.h"
114 
115 netsnmp_feature_child_of(agent_read_config_all, libnetsnmpagent);
116 
117 netsnmp_feature_child_of(snmpd_unregister_config_handler, agent_read_config_all);
118 
netsnmp_set_agent_user_id(int uid)119 void netsnmp_set_agent_user_id(int uid)
120 {
121     static int agent_user_id = -1;
122 
123     if (agent_user_id != -1 && uid != agent_user_id) {
124         snmp_log(LOG_ERR, "User ID has already been set -- can not change\n");
125         return;
126     }
127     agent_user_id = uid;
128     netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_USERID, uid);
129 }
130 
netsnmp_set_agent_group_id(int gid)131 void netsnmp_set_agent_group_id(int gid)
132 {
133     static int agent_group_id = -1;
134 
135     if (agent_group_id != -1 && gid != agent_group_id) {
136         snmp_log(LOG_ERR, "Group ID has already been set -- can not change\n");
137         return;
138     }
139     agent_group_id = gid;
140     netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_GROUPID,
141                        gid);
142 }
143 
144 #ifdef HAVE_UNISTD_H
145 void
netsnmp_parse_agent_user(const char * token,char * cptr)146 netsnmp_parse_agent_user(const char *token, char *cptr)
147 {
148     if (cptr[0] == '#') {
149         char           *ecp;
150         int             uid;
151 
152         uid = strtoul(cptr + 1, &ecp, 10);
153         if (*ecp != 0) {
154             config_perror("Bad number");
155 	} else {
156             netsnmp_set_agent_user_id(uid);
157 	}
158 #if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
159     } else {
160         struct passwd  *info;
161 
162         info = getpwnam(cptr);
163         if (info)
164             netsnmp_set_agent_user_id(info->pw_uid);
165         else
166             config_perror("User not found in passwd database");
167         endpwent();
168 #endif
169     }
170 }
171 
172 void
netsnmp_parse_agent_group(const char * token,char * cptr)173 netsnmp_parse_agent_group(const char *token, char *cptr)
174 {
175     if (cptr[0] == '#') {
176         char           *ecp;
177         int             gid = strtoul(cptr + 1, &ecp, 10);
178 
179         if (*ecp != 0) {
180             config_perror("Bad number");
181 	} else {
182             netsnmp_set_agent_group_id(gid);
183 	}
184 #if defined(HAVE_GETGRNAM) && defined(HAVE_GRP_H)
185     } else {
186         struct group   *info;
187 
188         info = getgrnam(cptr);
189         if (info)
190             netsnmp_set_agent_group_id(info->gr_gid);
191         else
192             config_perror("Group not found in group database");
193         endgrent();
194 #endif
195     }
196 }
197 #endif
198 
199 #ifndef NETSNMP_NO_LISTEN_SUPPORT
200 void
snmpd_set_agent_address(const char * token,char * cptr)201 snmpd_set_agent_address(const char *token, char *cptr)
202 {
203     char            buf[SPRINT_MAX_LEN];
204     char           *ptr;
205 
206     /*
207      * has something been specified before?
208      */
209     ptr = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
210 				NETSNMP_DS_AGENT_PORTS);
211 
212     if (ptr) {
213         /*
214          * append to the older specification string
215          */
216         snprintf(buf, sizeof(buf), "%s,%s", ptr, cptr);
217 	buf[sizeof(buf) - 1] = '\0';
218     } else {
219         strlcpy(buf, cptr, sizeof(buf));
220     }
221 
222     DEBUGMSGTL(("snmpd_ports", "port spec: %s\n", buf));
223     netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
224 			  NETSNMP_DS_AGENT_PORTS, buf);
225 }
226 #endif /* NETSNMP_NO_LISTEN_SUPPORT */
227 
228 void
init_agent_read_config(const char * app)229 init_agent_read_config(const char *app)
230 {
231     if (app != NULL) {
232         netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
233 			      NETSNMP_DS_LIB_APPTYPE, app);
234     } else {
235         app = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
236 				    NETSNMP_DS_LIB_APPTYPE);
237     }
238 
239     register_app_config_handler("authtrapenable",
240                                 snmpd_parse_config_authtrap, NULL,
241                                 "1 | 2\t\t(1 = enable, 2 = disable)");
242     register_app_config_handler("pauthtrapenable",
243                                 snmpd_parse_config_authtrap, NULL, NULL);
244 
245 
246     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
247 			       NETSNMP_DS_AGENT_ROLE) == MASTER_AGENT) {
248 #ifndef NETSNMP_DISABLE_SNMPV1
249         register_app_config_handler("trapsink",
250                                     snmpd_parse_config_trapsink,
251                                     snmpd_free_trapsinks,
252                                     "[-profile p] [-name n] [-tag t] host [community] [port]");
253 #endif
254 #ifndef NETSNMP_DISABLE_SNMPV2C
255         register_app_config_handler("trap2sink",
256                                     snmpd_parse_config_trap2sink,
257                                     snmpd_free_trapsinks,
258                                     "[-profile p] [-name n] [-tag t] host [community] [port]");
259         register_app_config_handler("informsink",
260                                     snmpd_parse_config_informsink,
261                                     snmpd_free_trapsinks,
262                                     "[-profile p] [-name n] [-tag t] host [community] [port]");
263 #endif
264         register_app_config_handler("trapsess",
265                                     snmpd_parse_config_trapsess,
266                                     snmpd_free_trapsinks,
267                                     "[-profile p] [-name n] [-tag t] [snmpcmdargs] host");
268     }
269 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
270     register_app_config_handler("trapcommunity",
271                                 snmpd_parse_config_trapcommunity,
272                                 snmpd_free_trapcommunity,
273                                 "community-string");
274 #endif /* support for community based SNMP */
275     netsnmp_ds_register_config(ASN_OCTET_STR, app, "v1trapaddress",
276                                NETSNMP_DS_APPLICATION_ID,
277                                NETSNMP_DS_AGENT_TRAP_ADDR);
278 #ifdef HAVE_UNISTD_H
279     register_app_config_handler("agentuser",
280                                 netsnmp_parse_agent_user, NULL, "userid");
281     register_app_config_handler("agentgroup",
282                                 netsnmp_parse_agent_group, NULL, "groupid");
283 #endif
284 #ifndef NETSNMP_NO_LISTEN_SUPPORT
285     register_app_config_handler("agentaddress",
286                                 snmpd_set_agent_address, NULL,
287                                 "SNMP bind address");
288 #endif /* NETSNMP_NO_LISTEN_SUPPORT */
289     netsnmp_ds_register_config(ASN_BOOLEAN, app, "quit",
290 			       NETSNMP_DS_APPLICATION_ID,
291 			       NETSNMP_DS_AGENT_QUIT_IMMEDIATELY);
292     netsnmp_ds_register_config(ASN_BOOLEAN, app, "leave_pidfile",
293 			       NETSNMP_DS_APPLICATION_ID,
294 			       NETSNMP_DS_AGENT_LEAVE_PIDFILE);
295     netsnmp_ds_register_config(ASN_BOOLEAN, app, "dontLogTCPWrappersConnects",
296                                NETSNMP_DS_APPLICATION_ID,
297                                NETSNMP_DS_AGENT_DONT_LOG_TCPWRAPPERS_CONNECTS);
298     netsnmp_ds_register_config(ASN_INTEGER, app, "maxGetbulkRepeats",
299                                NETSNMP_DS_APPLICATION_ID,
300                                NETSNMP_DS_AGENT_MAX_GETBULKREPEATS);
301     netsnmp_ds_register_config(ASN_INTEGER, app, "maxGetbulkResponses",
302                                NETSNMP_DS_APPLICATION_ID,
303                                NETSNMP_DS_AGENT_MAX_GETBULKRESPONSES);
304     netsnmp_ds_register_config(ASN_INTEGER, app, "avgBulkVarbindSize",
305                                NETSNMP_DS_APPLICATION_ID,
306                                NETSNMP_DS_AGENT_AVG_BULKVARBINDSIZE);
307 #ifndef NETSNMP_NO_PDU_STATS
308     netsnmp_ds_register_config(ASN_INTEGER, app, "pduStatsMax",
309                                NETSNMP_DS_APPLICATION_ID,
310                                NETSNMP_DS_AGENT_PDU_STATS_MAX);
311     netsnmp_ds_register_config(ASN_INTEGER, app, "pduStatsThreshold",
312                                NETSNMP_DS_APPLICATION_ID,
313                                NETSNMP_DS_AGENT_PDU_STATS_THRESHOLD);
314 #endif /* NETSNMP_NO_PDU_STATS */
315 
316     netsnmp_init_handler_conf();
317 
318 #include "agent_module_dot_conf.h"
319 #include "mib_module_dot_conf.h"
320 #ifdef TESTING
321     print_config_handlers();
322 #endif
323 }
324 
325 void
update_config(void)326 update_config(void)
327 {
328     snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
329                         SNMPD_CALLBACK_PRE_UPDATE_CONFIG, NULL);
330     free_config();
331     read_configs();
332 }
333 
334 
335 void
snmpd_register_config_handler(const char * token,void (* parser)(const char *,char *),void (* releaser)(void),const char * help)336 snmpd_register_config_handler(const char *token,
337                               void (*parser) (const char *, char *),
338                               void (*releaser) (void), const char *help)
339 {
340     DEBUGMSGTL(("snmpd_register_app_config_handler",
341                 "registering .conf token for \"%s\"\n", token));
342     register_app_config_handler(token, parser, releaser, help);
343 }
344 
345 void
snmpd_register_const_config_handler(const char * token,void (* parser)(const char *,const char *),void (* releaser)(void),const char * help)346 snmpd_register_const_config_handler(const char *token,
347                                     void (*parser) (const char *, const char *),
348                                     void (*releaser) (void), const char *help)
349 {
350     DEBUGMSGTL(("snmpd_register_app_config_handler",
351                 "registering .conf token for \"%s\"\n", token));
352     register_app_config_handler(token, (void(*)(const char *, char *))parser,
353                                 releaser, help);
354 }
355 
356 #ifdef NETSNMP_FEATURE_REQUIRE_SNMPD_UNREGISTER_CONFIG_HANDLER
357 netsnmp_feature_require(unregister_app_config_handler);
358 #endif /* NETSNMP_FEATURE_REQUIRE_SNMPD_UNREGISTER_CONFIG_HANDLER */
359 
360 #ifndef NETSNMP_FEATURE_REMOVE_SNMPD_UNREGISTER_CONFIG_HANDLER
361 void
snmpd_unregister_config_handler(const char * token)362 snmpd_unregister_config_handler(const char *token)
363 {
364     unregister_app_config_handler(token);
365 }
366 #endif /* NETSNMP_FEATURE_REMOVE_SNMPD_UNREGISTER_CONFIG_HANDLER */
367 
368 /*
369  * this function is intended for use by mib-modules to store permenant
370  * configuration information generated by sets or persistent counters
371  */
372 void
snmpd_store_config(const char * line)373 snmpd_store_config(const char *line)
374 {
375     read_app_config_store(line);
376 }
377