/src/net-snmp/snmplib/snmp_secmod.c
Line | Count | Source (jump to first uncovered line) |
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 | | #ifdef HAVE_STDLIB_H |
18 | | #include <stdlib.h> |
19 | | #endif |
20 | | #ifdef HAVE_STRING_H |
21 | | #include <string.h> |
22 | | #else |
23 | | #include <strings.h> |
24 | | #endif |
25 | | #ifdef 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 |
47 | | init_secmod(void) |
48 | 2.81k | { |
49 | 2.81k | snmp_register_callback(SNMP_CALLBACK_LIBRARY, |
50 | 2.81k | SNMP_CALLBACK_SESSION_INIT, set_default_secmod, |
51 | 2.81k | NULL); |
52 | | |
53 | 2.81k | netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityModel", |
54 | 2.81k | 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 | 2.81k | #include "snmpsm_init.h" |
59 | 2.81k | } |
60 | | |
61 | | void |
62 | | shutdown_secmod(void) |
63 | 5.62k | { |
64 | 5.62k | #include "snmpsm_shutdown.h" |
65 | 5.62k | } |
66 | | |
67 | | int |
68 | | register_sec_mod(int secmod, const char *modname, |
69 | | struct snmp_secmod_def *newdef) |
70 | 8.44k | { |
71 | 8.44k | int result = 0; |
72 | 8.44k | struct snmp_secmod_list *sptr; |
73 | 8.44k | char *othername, *modname2 = NULL; |
74 | | |
75 | 16.8k | for (sptr = registered_services; sptr; sptr = sptr->next) { |
76 | 8.43k | if (sptr->securityModel == secmod) { |
77 | 0 | return SNMPERR_GENERR; |
78 | 0 | } |
79 | 8.43k | } |
80 | 8.44k | sptr = SNMP_MALLOC_STRUCT(snmp_secmod_list); |
81 | 8.44k | if (sptr == NULL) |
82 | 0 | return SNMPERR_MALLOC; |
83 | 8.44k | sptr->secDef = newdef; |
84 | 8.44k | sptr->securityModel = secmod; |
85 | 8.44k | sptr->next = registered_services; |
86 | 8.44k | registered_services = sptr; |
87 | 8.44k | modname2 = strdup(modname); |
88 | 8.44k | if (!modname2) |
89 | 0 | result = SE_NOMEM; |
90 | 8.44k | else |
91 | 8.44k | result = se_add_pair_to_slist("snmp_secmods", modname2, secmod); |
92 | 8.44k | if (result != SE_OK) { |
93 | 0 | switch (result) { |
94 | 0 | case SE_NOMEM: |
95 | 0 | snmp_log(LOG_CRIT, "snmp_secmod: no memory\n"); |
96 | 0 | break; |
97 | | |
98 | 0 | case SE_ALREADY_THERE: |
99 | 0 | othername = se_find_label_in_slist("snmp_secmods", secmod); |
100 | 0 | if (strcmp(othername, modname) != 0) { |
101 | 0 | snmp_log(LOG_ERR, |
102 | 0 | "snmp_secmod: two security modules %s and %s registered with the same security number\n", |
103 | 0 | modname, othername); |
104 | 0 | } |
105 | 0 | break; |
106 | | |
107 | 0 | default: |
108 | 0 | snmp_log(LOG_ERR, |
109 | 0 | "snmp_secmod: unknown error trying to register a new security module\n"); |
110 | 0 | break; |
111 | 0 | } |
112 | 0 | return SNMPERR_GENERR; |
113 | 0 | } |
114 | 8.44k | return SNMPERR_SUCCESS; |
115 | 8.44k | } |
116 | | |
117 | | netsnmp_feature_child_of(unregister_sec_mod, netsnmp_unused); |
118 | | #ifndef NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD |
119 | | int |
120 | | unregister_sec_mod(int secmod) |
121 | 0 | { |
122 | 0 | struct snmp_secmod_list *sptr, *lptr; |
123 | |
|
124 | 0 | for (sptr = registered_services, lptr = NULL; sptr; |
125 | 0 | lptr = sptr, sptr = sptr->next) { |
126 | 0 | if (sptr->securityModel == secmod) { |
127 | 0 | if ( lptr ) |
128 | 0 | lptr->next = sptr->next; |
129 | 0 | else |
130 | 0 | registered_services = sptr->next; |
131 | 0 | SNMP_FREE(sptr->secDef); |
132 | 0 | SNMP_FREE(sptr); |
133 | 0 | return SNMPERR_SUCCESS; |
134 | 0 | } |
135 | 0 | } |
136 | | /* |
137 | | * not registered |
138 | | */ |
139 | 0 | return SNMPERR_GENERR; |
140 | 0 | } |
141 | | #endif /* NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD */ |
142 | | |
143 | | void |
144 | | clear_sec_mod(void) |
145 | 5.62k | { |
146 | 5.62k | struct snmp_secmod_list *tmp = registered_services, *next = NULL; |
147 | | |
148 | 14.0k | while (tmp != NULL) { |
149 | 8.43k | next = tmp->next; |
150 | 8.43k | SNMP_FREE(tmp->secDef); |
151 | 8.43k | SNMP_FREE(tmp); |
152 | 8.43k | tmp = next; |
153 | 8.43k | } |
154 | 5.62k | registered_services = NULL; |
155 | 5.62k | } |
156 | | |
157 | | |
158 | | struct snmp_secmod_def * |
159 | | find_sec_mod(int secmod) |
160 | 88.2k | { |
161 | 88.2k | struct snmp_secmod_list *sptr; |
162 | | |
163 | 295k | for (sptr = registered_services; sptr; sptr = sptr->next) { |
164 | 214k | if (sptr->securityModel == secmod) { |
165 | 7.43k | return sptr->secDef; |
166 | 7.43k | } |
167 | 214k | } |
168 | | /* |
169 | | * not registered |
170 | | */ |
171 | 80.8k | return NULL; |
172 | 88.2k | } |
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 | 2.81k | #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 |
188 | | set_default_secmod(int major, int minor, void *serverarg, void *clientarg) |
189 | 4.62k | { |
190 | 4.62k | netsnmp_session *sess = (netsnmp_session *) serverarg; |
191 | 4.62k | char *cptr; |
192 | 4.62k | int model; |
193 | | |
194 | 4.62k | if (!sess) |
195 | 0 | return SNMPERR_GENERR; |
196 | 4.62k | if (sess->securityModel == SNMP_DEFAULT_SECMODEL) { |
197 | 2.81k | if ((cptr = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, |
198 | 2.81k | NETSNMP_DS_LIB_SECMODEL)) != NULL) { |
199 | 0 | if ((model = se_find_value_in_slist("snmp_secmods", cptr)) |
200 | 0 | != SE_DNE) { |
201 | 0 | sess->securityModel = model; |
202 | 0 | } else { |
203 | 0 | snmp_log(LOG_ERR, |
204 | 0 | "unknown security model name: %s. Forcing USM instead.\n", |
205 | 0 | cptr); |
206 | 0 | sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL; |
207 | 0 | return SNMPERR_GENERR; |
208 | 0 | } |
209 | 2.81k | } else { |
210 | 2.81k | sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL; |
211 | 2.81k | } |
212 | 2.81k | } |
213 | 4.62k | return SNMPERR_SUCCESS; |
214 | 4.62k | } |