/*
 * security service wrapper to support pluggable security models 
 */

#include <net-snmp/net-snmp-config.h>
#include <stdio.h>
#include <ctype.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif

#if HAVE_DMALLOC_H
#include <dmalloc.h>
#endif

#include <net-snmp/types.h>
#include <net-snmp/output_api.h>
#include <net-snmp/config_api.h>
#include <net-snmp/utilities.h>

#include <net-snmp/library/snmp_api.h>
#include <net-snmp/library/snmp_enum.h>
#include <net-snmp/library/callback.h>
#include <net-snmp/library/snmp_secmod.h>
#include <net-snmp/library/snmpv3-security-includes.h>

static struct snmp_secmod_list *registered_services = NULL;

static SNMPCallback set_default_secmod;

void
init_secmod(void)
{
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
                           SNMP_CALLBACK_SESSION_INIT, set_default_secmod,
                           NULL);

    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defSecurityModel",
			       NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_SECMODEL);
    /*
     * this file is generated by configure for all the stuff we're using 
     */
#include "snmpsm_init.h"
}


int
register_sec_mod(int secmod, const char *modname,
                 struct snmp_secmod_def *newdef)
{
    int             result;
    struct snmp_secmod_list *sptr;
    char           *othername;

    for (sptr = registered_services; sptr; sptr = sptr->next) {
        if (sptr->securityModel == secmod) {
            return SNMPERR_GENERR;
        }
    }
    sptr = SNMP_MALLOC_STRUCT(snmp_secmod_list);
    if (sptr == NULL)
        return SNMPERR_MALLOC;
    sptr->secDef = newdef;
    sptr->securityModel = secmod;
    sptr->next = registered_services;
    registered_services = sptr;
    if ((result =
         se_add_pair_to_slist("snmp_secmods", strdup(modname), secmod))
        != SE_OK) {
        switch (result) {
        case SE_NOMEM:
            snmp_log(LOG_CRIT, "snmp_secmod: no memory\n");
            break;

        case SE_ALREADY_THERE:
            othername = se_find_label_in_slist("snmp_secmods", secmod);
            if (strcmp(othername, modname) != 0) {
                snmp_log(LOG_ERR,
                         "snmp_secmod: two security modules %s and %s registered with the same security number\n",
                         modname, othername);
            }
            break;

        default:
            snmp_log(LOG_ERR,
                     "snmp_secmod: unknown error trying to register a new security module\n");
            break;
        }
        return SNMPERR_GENERR;
    }
    return SNMPERR_SUCCESS;
}

int
unregister_sec_mod(int secmod)
{
    struct snmp_secmod_list *sptr, *lptr;

    for (sptr = registered_services, lptr = NULL; sptr;
         lptr = sptr, sptr = sptr->next) {
        if (sptr->securityModel == secmod) {
            if ( lptr )
                lptr->next = sptr->next;
            else
                registered_services = sptr->next;
	    SNMP_FREE(sptr->secDef);
            SNMP_FREE(sptr);
            return SNMPERR_SUCCESS;
        }
    }
    /*
     * not registered 
     */
    return SNMPERR_GENERR;
}

void            
clear_sec_mod(void)
{
    struct snmp_secmod_list *tmp = registered_services, *next = NULL;

    while (tmp != NULL) {
	next = tmp->next;
	SNMP_FREE(tmp->secDef);
	SNMP_FREE(tmp);
	tmp = next;
    }
    registered_services = NULL;
}


struct snmp_secmod_def *
find_sec_mod(int secmod)
{
    struct snmp_secmod_list *sptr;

    for (sptr = registered_services; sptr; sptr = sptr->next) {
        if (sptr->securityModel == secmod) {
            return sptr->secDef;
        }
    }
    /*
     * not registered 
     */
    return NULL;
}

static int
set_default_secmod(int major, int minor, void *serverarg, void *clientarg)
{
    netsnmp_session *sess = (netsnmp_session *) serverarg;
    char           *cptr;
    int             model;

    if (!sess)
        return SNMPERR_GENERR;
    if (sess->securityModel == SNMP_DEFAULT_SECMODEL) {
        if ((cptr = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
					  NETSNMP_DS_LIB_SECMODEL)) != NULL) {
            if ((model = se_find_value_in_slist("snmp_secmods", cptr))
		!= SE_DNE) {
                sess->securityModel = model;
            } else {
                snmp_log(LOG_ERR,
                         "unknown security model name: %s.  Forcing USM instead.\n",
                         cptr);
                sess->securityModel = USM_SEC_MODEL_NUMBER;
                return SNMPERR_GENERR;
            }
        } else {
            sess->securityModel = USM_SEC_MODEL_NUMBER;
        }
    }
    return SNMPERR_SUCCESS;
}
