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