net-snmp 5.7
snmp_secmod.c
00001 /*
00002  * security service wrapper to support pluggable security models 
00003  */
00004 
00005 #include <net-snmp/net-snmp-config.h>
00006 #include <stdio.h>
00007 #include <ctype.h>
00008 #if HAVE_STDLIB_H
00009 #include <stdlib.h>
00010 #endif
00011 #if HAVE_STRING_H
00012 #include <string.h>
00013 #else
00014 #include <strings.h>
00015 #endif
00016 #if HAVE_UNISTD_H
00017 #include <unistd.h>
00018 #endif
00019 
00020 #if HAVE_DMALLOC_H
00021 #include <dmalloc.h>
00022 #endif
00023 
00024 #include <net-snmp/types.h>
00025 #include <net-snmp/output_api.h>
00026 #include <net-snmp/config_api.h>
00027 #include <net-snmp/utilities.h>
00028 
00029 #include <net-snmp/library/snmp_api.h>
00030 #include <net-snmp/library/snmp_enum.h>
00031 #include <net-snmp/library/callback.h>
00032 #include <net-snmp/library/snmp_secmod.h>
00033 #include <net-snmp/library/snmpv3-security-includes.h>
00034 
00035 #include <net-snmp/net-snmp-features.h>
00036 
00037 static struct snmp_secmod_list *registered_services = NULL;
00038 
00039 static SNMPCallback set_default_secmod;
00040 
00041 void
00042 init_secmod(void)
00043 {
00044     snmp_register_callback(SNMP_CALLBACK_LIBRARY,
00045                            SNMP_CALLBACK_SESSION_INIT, set_default_secmod,
00046                            NULL);
00047 
00048     netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityModel",
00049                                NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECMODEL);
00050     /*
00051      * this file is generated by configure for all the stuff we're using 
00052      */
00053 #include "snmpsm_init.h"
00054 }
00055 
00056 void
00057 shutdown_secmod(void)
00058 {
00059     #include "snmpsm_shutdown.h"
00060 }
00061 
00062 int
00063 register_sec_mod(int secmod, const char *modname,
00064                  struct snmp_secmod_def *newdef)
00065 {
00066     int             result;
00067     struct snmp_secmod_list *sptr;
00068     char           *othername;
00069 
00070     for (sptr = registered_services; sptr; sptr = sptr->next) {
00071         if (sptr->securityModel == secmod) {
00072             return SNMPERR_GENERR;
00073         }
00074     }
00075     sptr = SNMP_MALLOC_STRUCT(snmp_secmod_list);
00076     if (sptr == NULL)
00077         return SNMPERR_MALLOC;
00078     sptr->secDef = newdef;
00079     sptr->securityModel = secmod;
00080     sptr->next = registered_services;
00081     registered_services = sptr;
00082     if ((result =
00083          se_add_pair_to_slist("snmp_secmods", strdup(modname), secmod))
00084         != SE_OK) {
00085         switch (result) {
00086         case SE_NOMEM:
00087             snmp_log(LOG_CRIT, "snmp_secmod: no memory\n");
00088             break;
00089 
00090         case SE_ALREADY_THERE:
00091             othername = se_find_label_in_slist("snmp_secmods", secmod);
00092             if (strcmp(othername, modname) != 0) {
00093                 snmp_log(LOG_ERR,
00094                          "snmp_secmod: two security modules %s and %s registered with the same security number\n",
00095                          modname, othername);
00096             }
00097             break;
00098 
00099         default:
00100             snmp_log(LOG_ERR,
00101                      "snmp_secmod: unknown error trying to register a new security module\n");
00102             break;
00103         }
00104         return SNMPERR_GENERR;
00105     }
00106     return SNMPERR_SUCCESS;
00107 }
00108 
00109 netsnmp_feature_child_of(unregister_sec_mod, netsnmp_unused)
00110 #ifndef NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD
00111 int
00112 unregister_sec_mod(int secmod)
00113 {
00114     struct snmp_secmod_list *sptr, *lptr;
00115 
00116     for (sptr = registered_services, lptr = NULL; sptr;
00117          lptr = sptr, sptr = sptr->next) {
00118         if (sptr->securityModel == secmod) {
00119             if ( lptr )
00120                 lptr->next = sptr->next;
00121             else
00122                 registered_services = sptr->next;
00123             SNMP_FREE(sptr->secDef);
00124             SNMP_FREE(sptr);
00125             return SNMPERR_SUCCESS;
00126         }
00127     }
00128     /*
00129      * not registered 
00130      */
00131     return SNMPERR_GENERR;
00132 }
00133 #endif /* NETSNMP_FEATURE_REMOVE_UNREGISTER_SEC_MOD */
00134 
00135 void            
00136 clear_sec_mod(void)
00137 {
00138     struct snmp_secmod_list *tmp = registered_services, *next = NULL;
00139 
00140     while (tmp != NULL) {
00141         next = tmp->next;
00142         SNMP_FREE(tmp->secDef);
00143         SNMP_FREE(tmp);
00144         tmp = next;
00145     }
00146     registered_services = NULL;
00147 }
00148 
00149 
00150 struct snmp_secmod_def *
00151 find_sec_mod(int secmod)
00152 {
00153     struct snmp_secmod_list *sptr;
00154 
00155     for (sptr = registered_services; sptr; sptr = sptr->next) {
00156         if (sptr->securityModel == secmod) {
00157             return sptr->secDef;
00158         }
00159     }
00160     /*
00161      * not registered 
00162      */
00163     return NULL;
00164 }
00165 
00166 /* try to pick a reasonable security module default based on what was
00167    compiled into the net-snmp package */
00168 #ifdef USM_SEC_MODEL_NUMBER
00169 #define NETSNMP_SECMOD_DEFAULT_MODEL  USM_SEC_MODEL_NUMBER
00170 #elif defined(TSM_SEC_MODEL_NUMBER)
00171 #define NETSNMP_SECMOD_DEFAULT_MODEL  TSM_SEC_MODEL_NUMBER
00172 #elif defined(KSM_SEC_MODEL_NUMBER)
00173 #define NETSNMP_SECMOD_DEFAULT_MODEL  KSM_SEC_MODEL_NUMBER
00174 #else
00175 /* else we give up and leave it blank */
00176 #define NETSNMP_SECMOD_DEFAULT_MODEL  -1
00177 #endif
00178 
00179 static int
00180 set_default_secmod(int major, int minor, void *serverarg, void *clientarg)
00181 {
00182     netsnmp_session *sess = (netsnmp_session *) serverarg;
00183     char           *cptr;
00184     int             model;
00185 
00186     if (!sess)
00187         return SNMPERR_GENERR;
00188     if (sess->securityModel == SNMP_DEFAULT_SECMODEL) {
00189         if ((cptr = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
00190                                           NETSNMP_DS_LIB_SECMODEL)) != NULL) {
00191             if ((model = se_find_value_in_slist("snmp_secmods", cptr))
00192                 != SE_DNE) {
00193                 sess->securityModel = model;
00194             } else {
00195                 snmp_log(LOG_ERR,
00196                          "unknown security model name: %s.  Forcing USM instead.\n",
00197                          cptr);
00198                 sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL;
00199                 return SNMPERR_GENERR;
00200             }
00201         } else {
00202             sess->securityModel = NETSNMP_SECMOD_DEFAULT_MODEL;
00203         }
00204     }
00205     return SNMPERR_SUCCESS;
00206 }