1 /*
2 * security service wrapper to support pluggable security models
3 *
4 * Portions of this file are subject to the following copyright(s). See
5 * the Net-SNMP's COPYING file for more details and other copyrights
6 * that may apply:
7 *
8 * Portions of this file are copyrighted by:
9 * Copyright (c) 2016 VMware, Inc. All rights reserved.
10 * Use is subject to license terms specified in the COPYING file
11 * distributed with the Net-SNMP package.
12 */
13
14 #include <net-snmp/net-snmp-config.h>
15 #include <stdio.h>
16 #include <ctype.h>
17 #if HAVE_STDLIB_H
18 #include <stdlib.h>
19 #endif
20 #if HAVE_STRING_H
21 #include <string.h>
22 #else
23 #include <strings.h>
24 #endif
25 #if HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28
29 #include <net-snmp/types.h>
30 #include <net-snmp/output_api.h>
31 #include <net-snmp/config_api.h>
32 #include <net-snmp/utilities.h>
33
34 #include <net-snmp/library/snmp_api.h>
35 #include <net-snmp/library/snmp_enum.h>
36 #include <net-snmp/library/callback.h>
37 #include <net-snmp/library/snmp_secmod.h>
38 #include <net-snmp/library/snmpv3-security-includes.h>
39
40 #include <net-snmp/net-snmp-features.h>
41
42 static struct snmp_secmod_list *registered_services = NULL;
43
44 static SNMPCallback set_default_secmod;
45
46 void
init_secmod(void)47 init_secmod(void)
48 {
49 snmp_register_callback(SNMP_CALLBACK_LIBRARY,
50 SNMP_CALLBACK_SESSION_INIT, set_default_secmod,
51 NULL);
52
53 netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityModel",
54 NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECMODEL);
55 /*
56 * this file is generated by configure for all the stuff we're using
57 */
58 #include "snmpsm_init.h"
59 }
60
61 void
shutdown_secmod(void)62 shutdown_secmod(void)
63 {
64 #include "snmpsm_shutdown.h"
65 }
66
67 int
register_sec_mod(int secmod,const char * modname,struct snmp_secmod_def * newdef)68 register_sec_mod(int secmod, const char *modname,
69 struct snmp_secmod_def *newdef)
70 {
71 int result = 0;
72 struct snmp_secmod_list *sptr;
73 char *othername, *modname2 = NULL;
74
75 for (sptr = registered_services; sptr; sptr = sptr->next) {
76 if (sptr->securityModel == secmod) {
77 return SNMPERR_GENERR;
78 }
79 }
80 sptr = SNMP_MALLOC_STRUCT(snmp_secmod_list);
81 if (sptr == NULL)
82 return SNMPERR_MALLOC;
83 sptr->secDef = newdef;
84 sptr->securityModel = secmod;
85 sptr->next = registered_services;
86 registered_services = sptr;
87 modname2 = strdup(modname);
88 if (!modname2)
89 result = SE_NOMEM;
90 else
91 result = se_add_pair_to_slist("snmp_secmods", modname2, secmod);
92 if (result != SE_OK) {
93 switch (result) {
94 case SE_NOMEM:
95 snmp_log(LOG_CRIT, "snmp_secmod: no memory\n");
96 break;
97
98 case SE_ALREADY_THERE:
99 othername = se_find_label_in_slist("snmp_secmods", secmod);
100 if (strcmp(othername, modname) != 0) {
101 snmp_log(LOG_ERR,
102 "snmp_secmod: two security modules %s and %s registered with the same security number\n",
103 modname, othername);
104 }
105 break;
106
107 default:
108 snmp_log(LOG_ERR,
109 "snmp_secmod: unknown error trying to register a new security module\n");
110 break;
111 }
112 return SNMPERR_GENERR;
113 }
114 return SNMPERR_SUCCESS;
115 }
116
117 netsnmp_feature_child_of(unregister_sec_mod, netsnmp_unused);
118 #ifndef NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD
119 int
unregister_sec_mod(int secmod)120 unregister_sec_mod(int secmod)
121 {
122 struct snmp_secmod_list *sptr, *lptr;
123
124 for (sptr = registered_services, lptr = NULL; sptr;
125 lptr = sptr, sptr = sptr->next) {
126 if (sptr->securityModel == secmod) {
127 if ( lptr )
128 lptr->next = sptr->next;
129 else
130 registered_services = sptr->next;
131 SNMP_FREE(sptr->secDef);
132 SNMP_FREE(sptr);
133 return SNMPERR_SUCCESS;
134 }
135 }
136 /*
137 * not registered
138 */
139 return SNMPERR_GENERR;
140 }
141 #endif /* NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD */
142
143 void
clear_sec_mod(void)144 clear_sec_mod(void)
145 {
146 struct snmp_secmod_list *tmp = registered_services, *next = NULL;
147
148 while (tmp != NULL) {
149 next = tmp->next;
150 SNMP_FREE(tmp->secDef);
151 SNMP_FREE(tmp);
152 tmp = next;
153 }
154 registered_services = NULL;
155 }
156
157
158 struct snmp_secmod_def *
find_sec_mod(int secmod)159 find_sec_mod(int secmod)
160 {
161 struct snmp_secmod_list *sptr;
162
163 for (sptr = registered_services; sptr; sptr = sptr->next) {
164 if (sptr->securityModel == secmod) {
165 return sptr->secDef;
166 }
167 }
168 /*
169 * not registered
170 */
171 return NULL;
172 }
173
174 /* try to pick a reasonable security module default based on what was
175 compiled into the net-snmp package */
176 #ifdef USM_SEC_MODEL_NUMBER
177 #define NETSNMP_SECMOD_DEFAULT_MODEL USM_SEC_MODEL_NUMBER
178 #elif defined(TSM_SEC_MODEL_NUMBER)
179 #define NETSNMP_SECMOD_DEFAULT_MODEL TSM_SEC_MODEL_NUMBER
180 #elif defined(KSM_SEC_MODEL_NUMBER)
181 #define NETSNMP_SECMOD_DEFAULT_MODEL KSM_SEC_MODEL_NUMBER
182 #else
183 /* else we give up and leave it blank */
184 #define NETSNMP_SECMOD_DEFAULT_MODEL -1
185 #endif
186
187 static int
set_default_secmod(int major,int minor,void * serverarg,void * clientarg)188 set_default_secmod(int major, int minor, void *serverarg, void *clientarg)
189 {
190 netsnmp_session *sess = (netsnmp_session *) serverarg;
191 char *cptr;
192 int model;
193
194 if (!sess)
195 return SNMPERR_GENERR;
196 if (sess->securityModel == SNMP_DEFAULT_SECMODEL) {
197 if ((cptr = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
198 NETSNMP_DS_LIB_SECMODEL)) != NULL) {
199 if ((model = se_find_value_in_slist("snmp_secmods", cptr))
200 != SE_DNE) {
201 sess->securityModel = model;
202 } else {
203 snmp_log(LOG_ERR,
204 "unknown security model name: %s. Forcing USM instead.\n",
205 cptr);
206 sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL;
207 return SNMPERR_GENERR;
208 }
209 } else {
210 sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL;
211 }
212 }
213 return SNMPERR_SUCCESS;
214 }
215