|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* snmpksm.c
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* This code implements the Kerberos Security Model (KSM) for SNMP.
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Security number - 2066432
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/net-snmp-config.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <sys/types.h>
|
|
Packit |
fcad23 |
#include <stdio.h>
|
|
Packit |
fcad23 |
#ifdef HAVE_STDLIB_H
|
|
Packit |
fcad23 |
#include <stdlib.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#if TIME_WITH_SYS_TIME
|
|
Packit |
fcad23 |
# include <sys/time.h>
|
|
Packit |
fcad23 |
# include <time.h>
|
|
Packit |
fcad23 |
#else
|
|
Packit |
fcad23 |
# if HAVE_SYS_TIME_H
|
|
Packit |
fcad23 |
# include <sys/time.h>
|
|
Packit |
fcad23 |
# else
|
|
Packit |
fcad23 |
# include <time.h>
|
|
Packit |
fcad23 |
# endif
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#if HAVE_STRING_H
|
|
Packit |
fcad23 |
#include <string.h>
|
|
Packit |
fcad23 |
#else
|
|
Packit |
fcad23 |
#include <strings.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef HAVE_NETINET_IN_H
|
|
Packit |
fcad23 |
#include <netinet/in.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#include <errno.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if HAVE_DMALLOC_H
|
|
Packit |
fcad23 |
#include <dmalloc.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
|
|
Packit |
fcad23 |
#ifndef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
#define OLD_HEIMDAL
|
|
Packit |
fcad23 |
#endif /* ! NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
#else
|
|
Packit |
fcad23 |
#define KRB5_DEPRECATED 1
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
|
|
Packit |
fcad23 |
#define oid heimdal_oid_renamed
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
#include <krb5.h>
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
|
|
Packit |
fcad23 |
#undef oid
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_HEIMDAL
|
|
Packit |
fcad23 |
#define CHECKSUM_TYPE(x) (x)->cksumtype
|
|
Packit |
fcad23 |
#define CHECKSUM_CONTENTS(x) (x)->checksum.data
|
|
Packit |
fcad23 |
#define CHECKSUM_LENGTH(x) (x)->checksum.length
|
|
Packit |
fcad23 |
#define TICKET_CLIENT(x) (x)->client
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
#define CHECKSUM_TYPE(x) (x)->checksum_type
|
|
Packit |
fcad23 |
#define CHECKSUM_CONTENTS(x) (x)->contents
|
|
Packit |
fcad23 |
#define CHECKSUM_LENGTH(x) (x)->length
|
|
Packit |
fcad23 |
#define TICKET_CLIENT(x) (x)->enc_part2->client
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if HAVE_ET_COM_ERR_H
|
|
Packit |
fcad23 |
#include <et/com_err.h>
|
|
Packit |
fcad23 |
#elif HAVE_COM_ERR_H
|
|
Packit |
fcad23 |
#include <com_err.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/output_api.h>
|
|
Packit |
fcad23 |
#include <net-snmp/config_api.h>
|
|
Packit |
fcad23 |
#include <net-snmp/utilities.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/library/asn1.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_api.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/callback.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/keytools.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpv3.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/lcd_time.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/scapi.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/callback.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_secmod.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpksm.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static krb5_context kcontext = NULL;
|
|
Packit |
fcad23 |
static krb5_rcache rcache = NULL;
|
|
Packit |
fcad23 |
static krb5_keytab keytab = NULL;
|
|
Packit |
fcad23 |
static int keytab_setup = 0;
|
|
Packit |
fcad23 |
static char *service_name = NULL;
|
|
Packit |
fcad23 |
static char service_host[] = "host";
|
|
Packit |
fcad23 |
static u_char null_id[] = {0};
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int ksm_session_init(netsnmp_session *);
|
|
Packit |
fcad23 |
static void ksm_free_state_ref(void *);
|
|
Packit |
fcad23 |
static int ksm_free_pdu(netsnmp_pdu *);
|
|
Packit |
fcad23 |
static int ksm_clone_pdu(netsnmp_pdu *, netsnmp_pdu *);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int ksm_insert_cache(long, krb5_auth_context, u_char *,
|
|
Packit |
fcad23 |
size_t);
|
|
Packit |
fcad23 |
static void ksm_decrement_ref_count(long);
|
|
Packit |
fcad23 |
static void ksm_increment_ref_count(long);
|
|
Packit |
fcad23 |
static struct ksm_cache_entry *ksm_get_cache(long);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if !defined(HAVE_KRB5_AUTH_CON_GETSENDSUBKEY) /* Heimdal */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_error_code krb5_auth_con_getsendsubkey(krb5_context context,
|
|
Packit |
fcad23 |
krb5_auth_context auth_context,
|
|
Packit |
fcad23 |
krb5_keyblock **keyblock)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
return krb5_auth_con_getlocalsubkey(context, auth_context, keyblock);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if !defined(HAVE_KRB5_AUTH_CON_GETRECVSUBKEY) /* Heimdal */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_error_code krb5_auth_con_getrecvsubkey(krb5_context context,
|
|
Packit |
fcad23 |
krb5_auth_context auth_context,
|
|
Packit |
fcad23 |
krb5_keyblock **keyblock)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
return krb5_auth_con_getremotesubkey(context, auth_context, keyblock);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#define HASHSIZE 64
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Our information stored for the response PDU.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
struct ksm_secStateRef {
|
|
Packit |
fcad23 |
krb5_auth_context auth_context;
|
|
Packit |
fcad23 |
krb5_cksumtype cksumtype;
|
|
Packit |
fcad23 |
};
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* A KSM outgoing pdu cache entry
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
struct ksm_cache_entry {
|
|
Packit |
fcad23 |
long msgid;
|
|
Packit |
fcad23 |
int refcount;
|
|
Packit |
fcad23 |
krb5_auth_context auth_context;
|
|
Packit |
fcad23 |
u_char *secName;
|
|
Packit |
fcad23 |
size_t secNameLen;
|
|
Packit |
fcad23 |
struct ksm_cache_entry *next;
|
|
Packit |
fcad23 |
};
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Poor man's hash table
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static struct ksm_cache_entry *ksm_hash_table[HASHSIZE];
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Stuff to deal with config values
|
|
Packit |
fcad23 |
* Note the conditionals that wrap these--i don't know if these are
|
|
Packit |
fcad23 |
* needed, since i don't know how library initialization and callbacks
|
|
Packit |
fcad23 |
* and stuff work
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
init_snmpksm_post_config(int majorid, int minorid, void *serverarg,
|
|
Packit |
fcad23 |
void *clientarg)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (kcontext == NULL) {
|
|
Packit |
fcad23 |
/* not reached, i'd imagine */
|
|
Packit |
fcad23 |
return SNMPERR_KRB5;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (service_name == NULL) {
|
|
Packit |
fcad23 |
/* always reached, i'd imagine */
|
|
Packit |
fcad23 |
char *c = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_KSM_SERVICE_NAME);
|
|
Packit |
fcad23 |
if (c != NULL) {
|
|
Packit |
fcad23 |
service_name = c;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
else {
|
|
Packit |
fcad23 |
service_name = service_host;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (keytab_setup == 0) {
|
|
Packit |
fcad23 |
/* always reached, i'd imagine */
|
|
Packit |
fcad23 |
char *c = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_KSM_KEYTAB);
|
|
Packit |
fcad23 |
if (c) {
|
|
Packit |
fcad23 |
krb5_error_code retval;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Using keytab %s\n", c));
|
|
Packit |
fcad23 |
retval = krb5_kt_resolve(kcontext, c, &keytab);
|
|
Packit |
fcad23 |
if (retval) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_kt_resolve(\"%s\") failed. KSM "
|
|
Packit |
fcad23 |
"config callback failing\n", error_message(retval)));
|
|
Packit |
fcad23 |
return SNMPERR_KRB5;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
else {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Using default keytab\n"));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
keytab_setup = 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return SNMPERR_SUCCESS;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Initialize all of the state required for Kerberos (right now, just call
|
|
Packit |
fcad23 |
* krb5_init_context).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
init_ksm(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
krb5_error_code retval;
|
|
Packit |
fcad23 |
struct snmp_secmod_def *def;
|
|
Packit |
fcad23 |
int i;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defKSMKeytab",
|
|
Packit |
fcad23 |
NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_KSM_KEYTAB);
|
|
Packit |
fcad23 |
netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "defKSMServiceName",
|
|
Packit |
fcad23 |
NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_KSM_SERVICE_NAME);
|
|
Packit |
fcad23 |
snmp_register_callback(SNMP_CALLBACK_LIBRARY,
|
|
Packit |
fcad23 |
SNMP_CALLBACK_POST_READ_CONFIG,
|
|
Packit |
fcad23 |
init_snmpksm_post_config, NULL);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (kcontext == NULL) {
|
|
Packit |
fcad23 |
retval = krb5_init_context(&kcontext);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retval) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_init_context failed (%s), not "
|
|
Packit |
fcad23 |
"registering KSM\n", error_message(retval)));
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (i = 0; i < HASHSIZE; i++)
|
|
Packit |
fcad23 |
ksm_hash_table[i] = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
def = SNMP_MALLOC_STRUCT(snmp_secmod_def);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!def) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to malloc snmp_secmod struct, not "
|
|
Packit |
fcad23 |
"registering KSM\n"));
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
def->encode_reverse = ksm_rgenerate_out_msg;
|
|
Packit |
fcad23 |
def->decode = ksm_process_in_msg;
|
|
Packit |
fcad23 |
def->session_open = ksm_session_init;
|
|
Packit |
fcad23 |
def->pdu_free_state_ref = ksm_free_state_ref;
|
|
Packit |
fcad23 |
def->pdu_free = ksm_free_pdu;
|
|
Packit |
fcad23 |
def->pdu_clone = ksm_clone_pdu;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
register_sec_mod(NETSNMP_SEC_MODEL_KSM, "ksm", def);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void shutdown_ksm(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* These routines implement a simple cache for information we need to
|
|
Packit |
fcad23 |
* process responses. When we send out a request, it contains an AP_REQ;
|
|
Packit |
fcad23 |
* we get back an AP_REP, and we need the authorization context from the
|
|
Packit |
fcad23 |
* AP_REQ to decrypt the AP_REP. But because right now there's nothing
|
|
Packit |
fcad23 |
* that gets preserved across calls to rgenerate_out_msg to process_in_msg,
|
|
Packit |
fcad23 |
* we cache these internally based on the message ID (we also cache the
|
|
Packit |
fcad23 |
* passed-in security name, for reasons that are mostly stupid).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
ksm_insert_cache(long msgid, krb5_auth_context auth_context,
|
|
Packit |
fcad23 |
u_char * secName, size_t secNameLen)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
struct ksm_cache_entry *entry;
|
|
Packit |
fcad23 |
int bucket;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
entry = SNMP_MALLOC_STRUCT(ksm_cache_entry);
|
|
Packit |
fcad23 |
if (!entry)
|
|
Packit |
fcad23 |
return SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
entry->msgid = msgid;
|
|
Packit |
fcad23 |
entry->auth_context = auth_context;
|
|
Packit |
fcad23 |
entry->refcount = 1;
|
|
Packit |
fcad23 |
entry->secName = netsnmp_memdup(secName, secNameLen);
|
|
Packit |
fcad23 |
if (secName && !entry->secName) {
|
|
Packit |
fcad23 |
free(entry);
|
|
Packit |
fcad23 |
return SNMPERR_GENERR;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
entry->secNameLen = secNameLen;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
bucket = msgid % HASHSIZE;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
entry->next = ksm_hash_table[bucket];
|
|
Packit |
fcad23 |
ksm_hash_table[bucket] = entry;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return SNMPERR_SUCCESS;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static struct ksm_cache_entry *
|
|
Packit |
fcad23 |
ksm_get_cache(long msgid)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
struct ksm_cache_entry *entry;
|
|
Packit |
fcad23 |
int bucket;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
bucket = msgid % HASHSIZE;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (entry = ksm_hash_table[bucket]; entry != NULL;
|
|
Packit |
fcad23 |
entry = entry->next)
|
|
Packit |
fcad23 |
if (entry->msgid == msgid)
|
|
Packit |
fcad23 |
return entry;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
ksm_decrement_ref_count(long msgid)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
struct ksm_cache_entry *entry, *entry1;
|
|
Packit |
fcad23 |
int bucket;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
bucket = msgid % HASHSIZE;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (ksm_hash_table[bucket] && ksm_hash_table[bucket]->msgid == msgid) {
|
|
Packit |
fcad23 |
entry = ksm_hash_table[bucket];
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* If the reference count is zero, then free it
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (--entry->refcount <= 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n", msgid));
|
|
Packit |
fcad23 |
krb5_auth_con_free(kcontext, entry->auth_context);
|
|
Packit |
fcad23 |
free(entry->secName);
|
|
Packit |
fcad23 |
ksm_hash_table[bucket] = entry->next;
|
|
Packit |
fcad23 |
free(entry);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
} else if (ksm_hash_table[bucket])
|
|
Packit |
fcad23 |
for (entry1 = ksm_hash_table[bucket], entry = entry1->next;
|
|
Packit |
fcad23 |
entry != NULL; entry1 = entry, entry = entry->next)
|
|
Packit |
fcad23 |
if (entry->msgid == msgid) {
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (--entry->refcount <= 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Freeing entry for msgid %ld\n",
|
|
Packit |
fcad23 |
msgid));
|
|
Packit |
fcad23 |
krb5_auth_con_free(kcontext, entry->auth_context);
|
|
Packit |
fcad23 |
free(entry->secName);
|
|
Packit |
fcad23 |
entry1->next = entry->next;
|
|
Packit |
fcad23 |
free(entry);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM: Unable to decrement cache entry for msgid %ld.\n",
|
|
Packit |
fcad23 |
msgid));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
ksm_increment_ref_count(long msgid)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
struct ksm_cache_entry *entry = ksm_get_cache(msgid);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!entry) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to find cache entry for msgid %ld "
|
|
Packit |
fcad23 |
"for increment\n", msgid));
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
entry->refcount++;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Initialize specific session information (right now, just set up things to
|
|
Packit |
fcad23 |
* not do an engineID probe)
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
ksm_session_init(netsnmp_session * sess)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM: Reached our session initialization callback\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
sess->flags |= SNMP_FLAGS_DONT_PROBE;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return SNMPERR_SUCCESS;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Free our state information (this is only done on the agent side)
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
ksm_free_state_ref(void *ptr)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
struct ksm_secStateRef *ref = (struct ksm_secStateRef *) ptr;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Freeing state reference\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_auth_con_free(kcontext, ref->auth_context);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
free(ref);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* This is called when the PDU is freed; this will decrement reference counts
|
|
Packit |
fcad23 |
* for entries in our state cache.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
ksm_free_pdu(netsnmp_pdu *pdu)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
ksm_decrement_ref_count(pdu->msgid);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Decrementing cache entry for PDU msgid %ld\n",
|
|
Packit |
fcad23 |
pdu->msgid));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return SNMPERR_SUCCESS;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* This is called when a PDU is cloned (to increase reference counts)
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
ksm_clone_pdu(netsnmp_pdu *pdu, netsnmp_pdu *pdu2)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
ksm_increment_ref_count(pdu->msgid);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Incrementing cache entry for PDU msgid %ld\n",
|
|
Packit |
fcad23 |
pdu->msgid));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return SNMPERR_SUCCESS;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/****************************************************************************
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* ksm_generate_out_msg
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Parameters:
|
|
Packit |
fcad23 |
* (See list below...)
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Returns:
|
|
Packit |
fcad23 |
* SNMPERR_GENERIC On success.
|
|
Packit |
fcad23 |
* SNMPERR_KRB5
|
|
Packit |
fcad23 |
* ... and others
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Generate an outgoing message.
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
****************************************************************************/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
ksm_rgenerate_out_msg(struct snmp_secmod_outgoing_params *parms)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
krb5_auth_context auth_context = NULL;
|
|
Packit |
fcad23 |
krb5_error_code retcode;
|
|
Packit |
fcad23 |
krb5_ccache cc = NULL;
|
|
Packit |
fcad23 |
int retval = SNMPERR_SUCCESS;
|
|
Packit |
fcad23 |
krb5_data outdata, ivector;
|
|
Packit |
fcad23 |
krb5_keyblock *subkey = NULL;
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
krb5_data input;
|
|
Packit |
fcad23 |
krb5_enc_data output;
|
|
Packit |
fcad23 |
unsigned int numcksumtypes;
|
|
Packit |
fcad23 |
krb5_cksumtype *cksumtype_array;
|
|
Packit |
fcad23 |
#elif defined OLD_HEIMDAL /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
krb5_crypto heim_crypto = NULL;
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
krb5_encrypt_block eblock;
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
size_t blocksize, encrypted_length;
|
|
Packit |
fcad23 |
unsigned char *encrypted_data = NULL;
|
|
Packit |
fcad23 |
long zero = 0, tmp;
|
|
Packit |
fcad23 |
int i;
|
|
Packit |
fcad23 |
u_char *cksum_pointer;
|
|
Packit |
fcad23 |
krb5_cksumtype cksumtype;
|
|
Packit |
fcad23 |
krb5_checksum pdu_checksum;
|
|
Packit |
fcad23 |
u_char **wholeMsg = parms->wholeMsg;
|
|
Packit |
fcad23 |
size_t *offset = parms->wholeMsgOffset, seq_offset;
|
|
Packit |
fcad23 |
struct ksm_secStateRef *ksm_state = (struct ksm_secStateRef *)
|
|
Packit |
fcad23 |
parms->secStateRef;
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
krb5_data encrypted_scoped_pdu;
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
int rc;
|
|
Packit |
fcad23 |
char *colon = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Starting KSM processing\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
outdata.length = 0;
|
|
Packit |
fcad23 |
outdata.data = NULL;
|
|
Packit |
fcad23 |
ivector.length = 0;
|
|
Packit |
fcad23 |
ivector.data = NULL;
|
|
Packit |
fcad23 |
CHECKSUM_CONTENTS(&pdu_checksum) = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!ksm_state) {
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* If we've got a port number as part of the "peername", then
|
|
Packit |
fcad23 |
* suppress this (temporarily) while we build the credential info.
|
|
Packit |
fcad23 |
* XXX - what about "udp:host" style addresses?
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
colon = strrchr(parms->session->peername, ':');
|
|
Packit |
fcad23 |
if (colon != NULL) {
|
|
Packit |
fcad23 |
*colon='\0';
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* If we don't have a ksm_state, then we're a request. Get a
|
|
Packit |
fcad23 |
* credential cache and build a ap_req.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
retcode = krb5_cc_default(kcontext, &cc);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: krb5_cc_default failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Set credential cache successfully\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* This seems odd, since we don't need this until later (or earlier,
|
|
Packit |
fcad23 |
* depending on how you look at it), but because the most likely
|
|
Packit |
fcad23 |
* errors are Kerberos at this point, I'll get this now to save
|
|
Packit |
fcad23 |
* time not encoding the rest of the packet.
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Also, we need the subkey to encrypt the PDU (if required).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode =
|
|
Packit |
fcad23 |
krb5_mk_req(kcontext, &auth_context,
|
|
Packit |
fcad23 |
AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
|
|
Packit |
fcad23 |
service_name, parms->session->peername, NULL,
|
|
Packit |
fcad23 |
cc, &outdata);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (colon != NULL)
|
|
Packit |
fcad23 |
*colon=':';
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: krb5_mk_req failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: ticket retrieved successfully for \"%s/%s\" "
|
|
Packit |
fcad23 |
"(may not be actual ticket sname)\n", service_name,
|
|
Packit |
fcad23 |
parms->session->peername));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Grab the auth_context from our security state reference
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
auth_context = ksm_state->auth_context;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Bundle up an AP_REP. Note that we do this only when we
|
|
Packit |
fcad23 |
* have a security state reference (which means we're in an agent
|
|
Packit |
fcad23 |
* and we're sending a response).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Starting reply processing.\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_mk_rep(kcontext, auth_context, &outdata);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: krb5_mk_rep failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Finished with krb5_mk_rep()\n"));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* If we have to encrypt the PDU, do that now
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (parms->secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Starting PDU encryption.\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* It's weird -
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* If we're on the manager, it's a local subkey (because that's in
|
|
Packit |
fcad23 |
* our AP_REQ)
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* If we're on the agent, it's a remote subkey (because that comes
|
|
Packit |
fcad23 |
* FROM the received AP_REQ).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (ksm_state)
|
|
Packit |
fcad23 |
retcode = krb5_auth_con_getrecvsubkey(kcontext, auth_context,
|
|
Packit |
fcad23 |
&subkey);
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
retcode = krb5_auth_con_getsendsubkey(kcontext, auth_context,
|
|
Packit |
fcad23 |
&subkey);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM: krb5_auth_con_getsendsubkey failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Note that here we need to handle different things between the
|
|
Packit |
fcad23 |
* old and new crypto APIs. First, we need to get the final encrypted
|
|
Packit |
fcad23 |
* length of the PDU.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
retcode = krb5_c_encrypt_length(kcontext, subkey->enctype,
|
|
Packit |
fcad23 |
parms->scopedPduLen,
|
|
Packit |
fcad23 |
&encrypted_length);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"Encryption length calculation failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#elif defined OLD_HEIMDAL
|
|
Packit |
fcad23 |
retcode = krb5_crypto_init(kcontext, subkey, 0, &heim_crypto);
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_crypto_init failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
encrypted_length = krb5_get_wrapped_length(kcontext, heim_crypto,
|
|
Packit |
fcad23 |
parms->scopedPduLen);
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_use_enctype(kcontext, &eblock, subkey->enctype);
|
|
Packit |
fcad23 |
retcode = krb5_process_key(kcontext, &eblock, subkey);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_process_key failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
encrypted_length = krb5_encrypt_size(parms->scopedPduLen,
|
|
Packit |
fcad23 |
eblock.crypto_entry);
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef OLD_HEIMDAL /* since heimdal allocs the space for us */
|
|
Packit |
fcad23 |
encrypted_data = malloc(encrypted_length);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!encrypted_data) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM: Unable to malloc %d bytes for encrypt "
|
|
Packit |
fcad23 |
"buffer: %s\n", (int)parms->scopedPduLen,
|
|
Packit |
fcad23 |
strerror(errno)));
|
|
Packit |
fcad23 |
retval = SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
#ifndef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
krb5_finish_key(kcontext, &eblock);
|
|
Packit |
fcad23 |
#endif /* ! NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* ! OLD_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* We need to set up a blank initialization vector for the encryption.
|
|
Packit |
fcad23 |
* Use a block of all zero's (which is dependent on the block size
|
|
Packit |
fcad23 |
* of the encryption method).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_c_block_size(kcontext, subkey->enctype, &blocksize);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"Unable to determine crypto block size: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#elif defined (OLD_HEIMDAL) /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
blocksize =
|
|
Packit |
fcad23 |
krb5_enctype_array[subkey->enctype]->system->block_length;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef OLD_HEIMDAL /* since allocs the space for us */
|
|
Packit |
fcad23 |
ivector.data = malloc(blocksize);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!ivector.data) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to allocate %d bytes for ivector\n",
|
|
Packit |
fcad23 |
(int)blocksize));
|
|
Packit |
fcad23 |
retval = SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
ivector.length = blocksize;
|
|
Packit |
fcad23 |
memset(ivector.data, 0, blocksize);
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Finally! Do the encryption!
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
input.data = (char *) parms->scopedPdu;
|
|
Packit |
fcad23 |
input.length = parms->scopedPduLen;
|
|
Packit |
fcad23 |
output.ciphertext.data = (char *) encrypted_data;
|
|
Packit |
fcad23 |
output.ciphertext.length = encrypted_length;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode =
|
|
Packit |
fcad23 |
krb5_c_encrypt(kcontext, subkey, KSM_KEY_USAGE_ENCRYPTION,
|
|
Packit |
fcad23 |
&ivector, &input, &output);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#elif defined OLD_HEIMDAL /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_data_zero(&encrypted_scoped_pdu);
|
|
Packit |
fcad23 |
retcode = krb5_encrypt(kcontext, heim_crypto, KSM_KEY_USAGE_ENCRYPTION,
|
|
Packit |
fcad23 |
parms->scopedPdu, parms->scopedPduLen,
|
|
Packit |
fcad23 |
&encrypted_scoped_pdu);
|
|
Packit |
fcad23 |
if (retcode == 0) {
|
|
Packit |
fcad23 |
encrypted_length = encrypted_scoped_pdu.length;
|
|
Packit |
fcad23 |
encrypted_data = encrypted_scoped_pdu.data;
|
|
Packit |
fcad23 |
krb5_data_zero(&encrypted_scoped_pdu);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_encrypt(kcontext, (krb5_pointer) parms->scopedPdu,
|
|
Packit |
fcad23 |
(krb5_pointer) encrypted_data,
|
|
Packit |
fcad23 |
parms->scopedPduLen, &eblock, ivector.data);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_finish_key(kcontext, &eblock);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: krb5_encrypt failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*offset = 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_string(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
offset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_UNIVERSAL |
|
|
Packit |
fcad23 |
ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR),
|
|
Packit |
fcad23 |
encrypted_data,
|
|
Packit |
fcad23 |
encrypted_length);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building encrypted payload failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Encryption complete.\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Plaintext PDU (not encrypted)
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (*parms->wholeMsgLen < parms->scopedPduLen) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Not enough room for plaintext PDU.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Start encoding the msgSecurityParameters
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* For now, use 0 for the response hint
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: scopedPdu added to payload\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
seq_offset = *offset;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_int(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
offset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_UNIVERSAL |
|
|
Packit |
fcad23 |
ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_INTEGER),
|
|
Packit |
fcad23 |
(long *) &zero, sizeof(zero));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_string(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
offset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_UNIVERSAL |
|
|
Packit |
fcad23 |
ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR),
|
|
Packit |
fcad23 |
(u_char *) outdata.data,
|
|
Packit |
fcad23 |
outdata.length);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building ksm AP_REQ failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* If we didn't encrypt the packet, we haven't yet got the subkey.
|
|
Packit |
fcad23 |
* Get that now.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!subkey) {
|
|
Packit |
fcad23 |
if (ksm_state)
|
|
Packit |
fcad23 |
retcode = krb5_auth_con_getrecvsubkey(kcontext, auth_context,
|
|
Packit |
fcad23 |
&subkey);
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
retcode = krb5_auth_con_getsendsubkey(kcontext, auth_context,
|
|
Packit |
fcad23 |
&subkey);
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_auth_con_getsendsubkey failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
retcode = krb5_crypto_init(kcontext, subkey, 0, &heim_crypto);
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_crypto_init failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Now, we need to pick the "right" checksum algorithm. For old
|
|
Packit |
fcad23 |
* crypto, just pick CKSUMTYPE_RSA_MD5_DES; for new crypto, pick
|
|
Packit |
fcad23 |
* one of the "approved" ones.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
retcode = krb5_c_keyed_checksum_types(kcontext, subkey->enctype,
|
|
Packit |
fcad23 |
&numcksumtypes, &cksumtype_array);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to find appropriate keyed checksum: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (numcksumtypes <= 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "We received a list of zero cksumtypes for this "
|
|
Packit |
fcad23 |
"enctype (%d)\n", subkey->enctype));
|
|
Packit |
fcad23 |
snmp_set_detail("No valid checksum type for this encryption type");
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* It's not clear to me from the API which checksum you're supposed
|
|
Packit |
fcad23 |
* to support, so I'm taking a guess at the first one
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
cksumtype = cksumtype_array[0];
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_free_cksumtypes(kcontext, cksumtype_array);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Choosing checksum type of %d (subkey type "
|
|
Packit |
fcad23 |
"of %d)\n", cksumtype, subkey->enctype));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_c_checksum_length(kcontext, cksumtype, &blocksize);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to determine checksum length: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
CHECKSUM_LENGTH(&pdu_checksum) = blocksize;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
if (ksm_state)
|
|
Packit |
fcad23 |
cksumtype = ksm_state->cksumtype;
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
/* no way to tell what kind of checksum to use without trying */
|
|
Packit |
fcad23 |
retval = krb5_create_checksum(kcontext, heim_crypto,
|
|
Packit |
fcad23 |
KSM_KEY_USAGE_CHECKSUM, 0,
|
|
Packit |
fcad23 |
parms->scopedPdu, parms->scopedPduLen,
|
|
Packit |
fcad23 |
&pdu_checksum);
|
|
Packit |
fcad23 |
if (retval) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to create a checksum: %s\n",
|
|
Packit |
fcad23 |
error_message(retval)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
cksumtype = CHECKSUM_TYPE(&pdu_checksum);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#else /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
cksumtype = CKSUMTYPE_RSA_MD5_DES;
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
if (!krb5_checksum_is_keyed(kcontext, cksumtype)) {
|
|
Packit |
fcad23 |
#else /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
if (!is_keyed_cksum(cksumtype)) {
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Checksum type %d is not a keyed checksum\n",
|
|
Packit |
fcad23 |
cksumtype));
|
|
Packit |
fcad23 |
snmp_set_detail("Checksum is not a keyed checksum");
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
if (!krb5_checksum_is_collision_proof(kcontext, cksumtype)) {
|
|
Packit |
fcad23 |
#else /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
if (!is_coll_proof_cksum(cksumtype)) {
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Checksum type %d is not a collision-proof "
|
|
Packit |
fcad23 |
"checksum\n", cksumtype));
|
|
Packit |
fcad23 |
snmp_set_detail("Checksum is not a collision-proof checksum");
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
if (CHECKSUM_CONTENTS(&pdu_checksum) != NULL ) {
|
|
Packit |
fcad23 |
/* we did the bogus checksum--don't need to ask for the size again
|
|
Packit |
fcad23 |
* or initialize cksumtype; just free the bits */
|
|
Packit |
fcad23 |
free(CHECKSUM_CONTENTS(&pdu_checksum));
|
|
Packit |
fcad23 |
CHECKSUM_CONTENTS(&pdu_checksum) = NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
else {
|
|
Packit |
fcad23 |
retval = krb5_checksumsize(kcontext, cksumtype,
|
|
Packit |
fcad23 |
&CHECKSUM_LENGTH(&pdu_checksum));
|
|
Packit |
fcad23 |
if (retval) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to determine checksum length: %s\n",
|
|
Packit |
fcad23 |
error_message(retval)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#else /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
CHECKSUM_LENGTH(&pdu_checksum) = krb5_checksum_size(kcontext, cksumtype);
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
CHECKSUM_TYPE(&pdu_checksum) = cksumtype;
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Note that here, we're just leaving blank space for the checksum;
|
|
Packit |
fcad23 |
* we remember where that is, and we'll fill it in later.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*offset += CHECKSUM_LENGTH(&pdu_checksum);
|
|
Packit |
fcad23 |
memset(*wholeMsg + *parms->wholeMsgLen - *offset, 0, CHECKSUM_LENGTH(&pdu_checksum));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
cksum_pointer = *wholeMsg + *parms->wholeMsgLen - *offset;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_header(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
parms->wholeMsgOffset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_UNIVERSAL |
|
|
Packit |
fcad23 |
ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR),
|
|
Packit |
fcad23 |
CHECKSUM_LENGTH(&pdu_checksum));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
tmp = cksumtype;
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_int(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
parms->wholeMsgOffset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_UNIVERSAL |
|
|
Packit |
fcad23 |
ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_INTEGER),
|
|
Packit |
fcad23 |
&tmp, sizeof(tmp));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_sequence(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
parms->wholeMsgOffset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_SEQUENCE |
|
|
Packit |
fcad23 |
ASN_CONSTRUCTOR),
|
|
Packit |
fcad23 |
*offset - seq_offset);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_header(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
parms->wholeMsgOffset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_UNIVERSAL |
|
|
Packit |
fcad23 |
ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR),
|
|
Packit |
fcad23 |
*offset - seq_offset);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building ksm security parameters failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Security parameter encoding completed\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* We're done with the KSM security parameters - now we do the global
|
|
Packit |
fcad23 |
* header and wrap up the whole PDU.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (*parms->wholeMsgLen < parms->globalDataLen) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building global data failed.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*offset += parms->globalDataLen;
|
|
Packit |
fcad23 |
memcpy(*wholeMsg + *parms->wholeMsgLen - *offset,
|
|
Packit |
fcad23 |
parms->globalData, parms->globalDataLen);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = asn_realloc_rbuild_sequence(wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
offset, 1,
|
|
Packit |
fcad23 |
(u_char) (ASN_SEQUENCE |
|
|
Packit |
fcad23 |
ASN_CONSTRUCTOR),
|
|
Packit |
fcad23 |
*offset);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Building master packet sequence.\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: PDU master packet encoding complete.\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Now we need to checksum the entire PDU (since it's built).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef OLD_HEIMDAL /* since heimdal allocs the mem for us */
|
|
Packit |
fcad23 |
CHECKSUM_CONTENTS(&pdu_checksum) = malloc(CHECKSUM_LENGTH(&pdu_checksum));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!CHECKSUM_CONTENTS(&pdu_checksum)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to malloc %d bytes for checksum\n",
|
|
Packit |
fcad23 |
CHECKSUM_LENGTH(&pdu_checksum)));
|
|
Packit |
fcad23 |
retval = SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* ! OLD_HEIMDAL */
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
input.data = (char *) (*wholeMsg + *parms->wholeMsgLen - *offset);
|
|
Packit |
fcad23 |
input.length = *offset;
|
|
Packit |
fcad23 |
retcode = krb5_c_make_checksum(kcontext, cksumtype, subkey,
|
|
Packit |
fcad23 |
KSM_KEY_USAGE_CHECKSUM, &input,
|
|
Packit |
fcad23 |
&pdu_checksum);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#elif defined(OLD_HEIMDAL) /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_create_checksum(kcontext, heim_crypto,
|
|
Packit |
fcad23 |
KSM_KEY_USAGE_CHECKSUM, cksumtype,
|
|
Packit |
fcad23 |
*wholeMsg + *parms->wholeMsgLen
|
|
Packit |
fcad23 |
- *offset, *offset, &pdu_checksum);
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_calculate_checksum(kcontext, cksumtype, *wholeMsg +
|
|
Packit |
fcad23 |
*parms->wholeMsgLen - *offset,
|
|
Packit |
fcad23 |
*offset,
|
|
Packit |
fcad23 |
(krb5_pointer) subkey->contents,
|
|
Packit |
fcad23 |
subkey->length, &pdu_checksum);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Calculate checksum failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Checksum calculation complete.\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
memcpy(cksum_pointer, CHECKSUM_CONTENTS(&pdu_checksum), CHECKSUM_LENGTH(&pdu_checksum));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Writing checksum of %d bytes at offset %d\n",
|
|
Packit |
fcad23 |
(int)CHECKSUM_LENGTH(&pdu_checksum),
|
|
Packit |
fcad23 |
(int)(cksum_pointer - (*wholeMsg + 1))));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: Checksum:"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (i = 0; i < CHECKSUM_LENGTH(&pdu_checksum); i++)
|
|
Packit |
fcad23 |
DEBUGMSG(("ksm", " %02x",
|
|
Packit |
fcad23 |
(unsigned int) ((unsigned char *)CHECKSUM_CONTENTS(&pdu_checksum))[i]));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSG(("ksm", "\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* If we're _not_ called as part of a response (null ksm_state),
|
|
Packit |
fcad23 |
* then save the auth_context for later using our cache routines.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!ksm_state) {
|
|
Packit |
fcad23 |
if ((retval = ksm_insert_cache(parms->pdu->msgid, auth_context,
|
|
Packit |
fcad23 |
(u_char *) parms->secName,
|
|
Packit |
fcad23 |
parms->secNameLen)) !=
|
|
Packit |
fcad23 |
SNMPERR_SUCCESS)
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
auth_context = NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM processing complete!\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
error:
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (CHECKSUM_CONTENTS(&pdu_checksum))
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
krb5_free_checksum_contents(kcontext, &pdu_checksum);
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
free(CHECKSUM_CONTENTS(&pdu_checksum));
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (ivector.data)
|
|
Packit |
fcad23 |
free(ivector.data);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (subkey)
|
|
Packit |
fcad23 |
krb5_free_keyblock(kcontext, subkey);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
if (heim_crypto)
|
|
Packit |
fcad23 |
krb5_crypto_destroy(kcontext, heim_crypto);
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (encrypted_data)
|
|
Packit |
fcad23 |
free(encrypted_data);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (cc)
|
|
Packit |
fcad23 |
krb5_cc_close(kcontext, cc);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (auth_context && !ksm_state)
|
|
Packit |
fcad23 |
krb5_auth_con_free(kcontext, auth_context);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return retval;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/****************************************************************************
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* ksm_process_in_msg
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Parameters:
|
|
Packit |
fcad23 |
* (See list below...)
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Returns:
|
|
Packit |
fcad23 |
* KSM_ERR_NO_ERROR On success.
|
|
Packit |
fcad23 |
* SNMPERR_KRB5
|
|
Packit |
fcad23 |
* KSM_ERR_GENERIC_ERROR
|
|
Packit |
fcad23 |
* KSM_ERR_UNSUPPORTED_SECURITY_LEVEL
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* Processes an incoming message.
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
****************************************************************************/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
ksm_process_in_msg(struct snmp_secmod_incoming_params *parms)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
long temp;
|
|
Packit |
fcad23 |
krb5_cksumtype cksumtype;
|
|
Packit |
fcad23 |
krb5_auth_context auth_context = NULL;
|
|
Packit |
fcad23 |
krb5_error_code retcode;
|
|
Packit |
fcad23 |
krb5_checksum checksum;
|
|
Packit |
fcad23 |
krb5_data ap_req, ivector;
|
|
Packit |
fcad23 |
krb5_flags flags;
|
|
Packit |
fcad23 |
krb5_keyblock *subkey = NULL;
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
krb5_data input, output;
|
|
Packit |
fcad23 |
krb5_boolean valid;
|
|
Packit |
fcad23 |
krb5_enc_data in_crypt;
|
|
Packit |
fcad23 |
#elif defined OLD_HEIMDAL /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
krb5_data output;
|
|
Packit |
fcad23 |
krb5_crypto heim_crypto = NULL;
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
krb5_encrypt_block eblock;
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
krb5_ticket *ticket = NULL;
|
|
Packit |
fcad23 |
int retval = SNMPERR_SUCCESS, response = 0;
|
|
Packit |
fcad23 |
size_t length =
|
|
Packit |
fcad23 |
parms->wholeMsgLen - (u_int) (parms->secParams - parms->wholeMsg);
|
|
Packit |
fcad23 |
u_char *current = parms->secParams, type;
|
|
Packit |
fcad23 |
size_t cksumlength, blocksize;
|
|
Packit |
fcad23 |
long hint;
|
|
Packit |
fcad23 |
char *cname;
|
|
Packit |
fcad23 |
struct ksm_secStateRef *ksm_state;
|
|
Packit |
fcad23 |
struct ksm_cache_entry *entry;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Processing has begun\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
CHECKSUM_CONTENTS(&checksum) = NULL;
|
|
Packit |
fcad23 |
ap_req.data = NULL;
|
|
Packit |
fcad23 |
ivector.length = 0;
|
|
Packit |
fcad23 |
ivector.data = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* First, parse the security parameters (because we need the subkey inside
|
|
Packit |
fcad23 |
* of the ticket to do anything
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((current = asn_parse_sequence(current, &length, &type,
|
|
Packit |
fcad23 |
(ASN_UNIVERSAL | ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR),
|
|
Packit |
fcad23 |
"ksm first octet")) == NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Initial security paramter parsing failed\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_ASN_PARSE_ERR;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((current = asn_parse_sequence(current, &length, &type,
|
|
Packit |
fcad23 |
(ASN_SEQUENCE | ASN_CONSTRUCTOR),
|
|
Packit |
fcad23 |
"ksm sequence")) == NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"Security parameter sequence parsing failed\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_ASN_PARSE_ERR;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((current = asn_parse_int(current, &length, &type, &temp,
|
|
Packit |
fcad23 |
sizeof(temp))) == NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Security parameter checksum type parsing"
|
|
Packit |
fcad23 |
"failed\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_ASN_PARSE_ERR;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
cksumtype = temp;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
if (!krb5_c_valid_cksumtype(cksumtype)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Invalid checksum type (%d)\n", cksumtype));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail("Invalid checksum type");
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!krb5_c_is_keyed_cksum(cksumtype)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Checksum type %d is not a keyed checksum\n",
|
|
Packit |
fcad23 |
cksumtype));
|
|
Packit |
fcad23 |
snmp_set_detail("Checksum is not a keyed checksum");
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!krb5_c_is_coll_proof_cksum(cksumtype)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Checksum type %d is not a collision-proof "
|
|
Packit |
fcad23 |
"checksum\n", cksumtype));
|
|
Packit |
fcad23 |
snmp_set_detail("Checksum is not a collision-proof checksum");
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#else /* ! NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
/* kludge */
|
|
Packit |
fcad23 |
if (krb5_checksumsize(kcontext, cksumtype, &cksumlength)) {
|
|
Packit |
fcad23 |
#else /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
if (!valid_cksumtype(cksumtype)) {
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Invalid checksum type (%d)\n", cksumtype));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail("Invalid checksum type");
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
if (!krb5_checksum_is_keyed(kcontext, cksumtype)) {
|
|
Packit |
fcad23 |
#else /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
if (!is_keyed_cksum(cksumtype)) {
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Checksum type %d is not a keyed checksum\n",
|
|
Packit |
fcad23 |
cksumtype));
|
|
Packit |
fcad23 |
snmp_set_detail("Checksum is not a keyed checksum");
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL
|
|
Packit |
fcad23 |
if (!krb5_checksum_is_collision_proof(kcontext, cksumtype)) {
|
|
Packit |
fcad23 |
#else /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
if (!is_coll_proof_cksum(cksumtype)) {
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Checksum type %d is not a collision-proof "
|
|
Packit |
fcad23 |
"checksum\n", cksumtype));
|
|
Packit |
fcad23 |
snmp_set_detail("Checksum is not a collision-proof checksum");
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
CHECKSUM_TYPE(&checksum) = cksumtype;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
cksumlength = length;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((current = asn_parse_sequence(current, &cksumlength, &type,
|
|
Packit |
fcad23 |
(ASN_UNIVERSAL | ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR), "ksm checksum")) ==
|
|
Packit |
fcad23 |
NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"Security parameter checksum parsing failed\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_ASN_PARSE_ERR;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
CHECKSUM_CONTENTS(&checksum) = malloc(cksumlength);
|
|
Packit |
fcad23 |
if (!CHECKSUM_CONTENTS(&checksum)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to malloc %d bytes for checksum.\n",
|
|
Packit |
fcad23 |
(int)cksumlength));
|
|
Packit |
fcad23 |
retval = SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
memcpy(CHECKSUM_CONTENTS(&checksum), current, cksumlength);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
CHECKSUM_LENGTH(&checksum) = cksumlength;
|
|
Packit |
fcad23 |
CHECKSUM_TYPE(&checksum) = cksumtype;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Zero out the checksum so the validation works correctly
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
memset(current, 0, cksumlength);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
current += cksumlength;
|
|
Packit |
fcad23 |
length = parms->wholeMsgLen - (u_int) (current - parms->wholeMsg);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((current = asn_parse_sequence(current, &length, &type,
|
|
Packit |
fcad23 |
(ASN_UNIVERSAL | ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR), "ksm ap_req")) ==
|
|
Packit |
fcad23 |
NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM security parameter AP_REQ/REP parsing "
|
|
Packit |
fcad23 |
"failed\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_ASN_PARSE_ERR;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
ap_req.length = length;
|
|
Packit |
fcad23 |
ap_req.data = malloc(length);
|
|
Packit |
fcad23 |
if (!ap_req.data) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM unable to malloc %d bytes for AP_REQ/REP.\n",
|
|
Packit |
fcad23 |
(int)length));
|
|
Packit |
fcad23 |
retval = SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
memcpy(ap_req.data, current, length);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
current += length;
|
|
Packit |
fcad23 |
length = parms->wholeMsgLen - (u_int) (current - parms->wholeMsg);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((current = asn_parse_int(current, &length, &type, &hint,
|
|
Packit |
fcad23 |
sizeof(hint))) == NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM security parameter hint parsing failed\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retval = SNMPERR_ASN_PARSE_ERR;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Okay! We've got it all! Now try decoding the damn ticket.
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* But of course there's a WRINKLE! We need to figure out if we're
|
|
Packit |
fcad23 |
* processing a AP_REQ or an AP_REP. How do we do that? We're going
|
|
Packit |
fcad23 |
* to cheat, and look at the first couple of bytes (which is what
|
|
Packit |
fcad23 |
* the Kerberos library routines do anyway).
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* If there are ever new Kerberos message formats, we'll need to fix
|
|
Packit |
fcad23 |
* this here.
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* If it's a _response_, then we need to get the auth_context
|
|
Packit |
fcad23 |
* from our cache.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (ap_req.length
|
|
Packit |
fcad23 |
#ifndef NETSNMP_USE_KERBEROS_HEIMDAL
|
|
Packit |
fcad23 |
&& (ap_req.data[0] == 0x6e || ap_req.data[0] == 0x4e)) {
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
&& (((char *)ap_req.data)[0] == 0x6e || ((char *)ap_req.data)[0] == 0x4e)) {
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* We need to initalize the authorization context, and set the
|
|
Packit |
fcad23 |
* replay cache in it (and initialize the replay cache if we
|
|
Packit |
fcad23 |
* haven't already
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_auth_con_init(kcontext, &auth_context);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_auth_con_init failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!rcache) {
|
|
Packit |
fcad23 |
krb5_data server;
|
|
Packit |
fcad23 |
server.data = service_host;
|
|
Packit |
fcad23 |
server.length = strlen(server.data);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_get_server_rcache(kcontext, &server, &rcache);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_get_server_rcache failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_auth_con_setrcache(kcontext, auth_context, rcache);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_auth_con_setrcache failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_rd_req(kcontext, &auth_context, &ap_req, NULL,
|
|
Packit |
fcad23 |
keytab, &flags, &ticket);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_auth_con_setrcache(kcontext, auth_context, NULL);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_rd_req() failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode =
|
|
Packit |
fcad23 |
krb5_unparse_name(kcontext, TICKET_CLIENT(ticket), &cname);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM authenticated principal name: %s\n",
|
|
Packit |
fcad23 |
cname));
|
|
Packit |
fcad23 |
free(cname);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Check to make sure AP_OPTS_MUTUAL_REQUIRED was set
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!(flags & AP_OPTS_MUTUAL_REQUIRED)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM MUTUAL_REQUIRED not set in request!\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail("MUTUAL_REQUIRED not set in message");
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode =
|
|
Packit |
fcad23 |
krb5_auth_con_getrecvsubkey(kcontext, auth_context, &subkey);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM remote subkey retrieval failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef NETSNMP_USE_KERBEROS_HEIMDAL
|
|
Packit |
fcad23 |
} else if (ap_req.length && (ap_req.data[0] == 0x6f ||
|
|
Packit |
fcad23 |
ap_req.data[0] == 0x4f)) {
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
} else if (ap_req.length && (((char *)ap_req.data)[0] == 0x6f ||
|
|
Packit |
fcad23 |
((char *)ap_req.data)[0] == 0x4f)) {
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Looks like a response; let's see if we've got that auth_context
|
|
Packit |
fcad23 |
* in our cache.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_ap_rep_enc_part *repl = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
response = 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
entry = ksm_get_cache(parms->pdu->msgid);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!entry) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM: Unable to find auth_context for PDU with "
|
|
Packit |
fcad23 |
"message ID of %ld\n", parms->pdu->msgid));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
auth_context = entry->auth_context;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* In that case, let's call the rd_rep function
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_rd_rep(kcontext, auth_context, &ap_req, &repl);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (repl)
|
|
Packit |
fcad23 |
krb5_free_ap_rep_enc_part(kcontext, repl);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: krb5_rd_rep() failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM: krb5_rd_rep() decoded successfully.\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode =
|
|
Packit |
fcad23 |
krb5_auth_con_getsendsubkey(kcontext, auth_context, &subkey);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to retrieve local subkey: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail("Unable to retrieve local subkey");
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
#ifndef NETSNMP_USE_KERBEROS_HEIMDAL
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unknown Kerberos message type (%02x)\n",
|
|
Packit |
fcad23 |
ap_req.data[0]));
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_HEIMDAL */
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unknown Kerberos message type (%02x)\n",
|
|
Packit |
fcad23 |
((char *)ap_req.data)[0]));
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail("Unknown Kerberos message type");
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
input.data = (char *) parms->wholeMsg;
|
|
Packit |
fcad23 |
input.length = parms->wholeMsgLen;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode =
|
|
Packit |
fcad23 |
krb5_c_verify_checksum(kcontext, subkey, KSM_KEY_USAGE_CHECKSUM,
|
|
Packit |
fcad23 |
&input, &checksum, &valid);
|
|
Packit |
fcad23 |
#elif defined(OLD_HEIMDAL) /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
retcode = krb5_crypto_init(kcontext, subkey, 0, &heim_crypto);
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "krb5_crypto_init failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
retcode = krb5_verify_checksum(kcontext, heim_crypto,
|
|
Packit |
fcad23 |
KSM_KEY_USAGE_CHECKSUM, parms->wholeMsg,
|
|
Packit |
fcad23 |
parms->wholeMsgLen, &checksum);
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
retcode = krb5_verify_checksum(kcontext, cksumtype, &checksum,
|
|
Packit |
fcad23 |
parms->wholeMsg, parms->wholeMsgLen,
|
|
Packit |
fcad23 |
(krb5_pointer) subkey->contents,
|
|
Packit |
fcad23 |
subkey->length);
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM checksum verification failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Don't ask me why they didn't simply return an error, but we have
|
|
Packit |
fcad23 |
* to check to see if "valid" is false.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
if (!valid) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Computed checksum did not match supplied "
|
|
Packit |
fcad23 |
"checksum!\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
snmp_set_detail
|
|
Packit |
fcad23 |
("Computed checksum did not match supplied checksum");
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Handle an encrypted PDU. Note that it's an OCTET_STRING of the
|
|
Packit |
fcad23 |
* output of whatever Kerberos cryptosystem you're using (defined by
|
|
Packit |
fcad23 |
* the encryption type). Note that this is NOT the EncryptedData
|
|
Packit |
fcad23 |
* sequence - it's what goes in the "cipher" field of EncryptedData.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (parms->secLevel == SNMP_SEC_LEVEL_AUTHPRIV) {
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((current = asn_parse_sequence(current, &length, &type,
|
|
Packit |
fcad23 |
(ASN_UNIVERSAL | ASN_PRIMITIVE |
|
|
Packit |
fcad23 |
ASN_OCTET_STR), "ksm pdu")) ==
|
|
Packit |
fcad23 |
NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM sPDU octet decoding failed\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_ASN_PARSE_ERR;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* The PDU is now pointed at by "current", and the length is in
|
|
Packit |
fcad23 |
* "length".
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM starting sPDU decode\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* We need to set up a blank initialization vector for the decryption.
|
|
Packit |
fcad23 |
* Use a block of all zero's (which is dependent on the block size
|
|
Packit |
fcad23 |
* of the encryption method).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_c_block_size(kcontext, subkey->enctype, &blocksize);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"Unable to determine crypto block size: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#elif defined(OLD_HEIMDAL) /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
blocksize =
|
|
Packit |
fcad23 |
krb5_enctype_array[subkey->enctype]->system->block_length;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef OLD_HEIMDAL
|
|
Packit |
fcad23 |
ivector.data = malloc(blocksize);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!ivector.data) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Unable to allocate %d bytes for ivector\n",
|
|
Packit |
fcad23 |
(int)blocksize));
|
|
Packit |
fcad23 |
retval = SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
ivector.length = blocksize;
|
|
Packit |
fcad23 |
memset(ivector.data, 0, blocksize);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_use_enctype(kcontext, &eblock, subkey->enctype);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_process_key(kcontext, &eblock, subkey);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM key post-processing failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* !NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* ! OLD_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (length > *parms->scopedPduLen) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM not enough room - have %d bytes to "
|
|
Packit |
fcad23 |
"decrypt but only %d bytes available\n", (int)length,
|
|
Packit |
fcad23 |
(int)*parms->scopedPduLen));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
#ifndef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
#ifndef OLD_HEIMDAL
|
|
Packit |
fcad23 |
krb5_finish_key(kcontext, &eblock);
|
|
Packit |
fcad23 |
#endif /* ! OLD_HEIMDAL */
|
|
Packit |
fcad23 |
#endif /* ! NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#ifdef NETSNMP_USE_KERBEROS_MIT
|
|
Packit |
fcad23 |
in_crypt.ciphertext.data = (char *) current;
|
|
Packit |
fcad23 |
in_crypt.ciphertext.length = length;
|
|
Packit |
fcad23 |
in_crypt.enctype = subkey->enctype;
|
|
Packit |
fcad23 |
output.data = (char *) *parms->scopedPdu;
|
|
Packit |
fcad23 |
output.length = *parms->scopedPduLen;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode =
|
|
Packit |
fcad23 |
krb5_c_decrypt(kcontext, subkey, KSM_KEY_USAGE_ENCRYPTION,
|
|
Packit |
fcad23 |
&ivector, &in_crypt, &output);
|
|
Packit |
fcad23 |
#elif defined (OLD_HEIMDAL) /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
retcode = krb5_decrypt(kcontext, heim_crypto, KSM_KEY_USAGE_ENCRYPTION,
|
|
Packit |
fcad23 |
current, length, &output);
|
|
Packit |
fcad23 |
if (retcode == 0) {
|
|
Packit |
fcad23 |
*parms->scopedPdu = (char *) output.data;
|
|
Packit |
fcad23 |
*parms->scopedPduLen = output.length;
|
|
Packit |
fcad23 |
krb5_data_zero(&output);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#else /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_decrypt(kcontext, (krb5_pointer) current,
|
|
Packit |
fcad23 |
*parms->scopedPdu, length, &eblock,
|
|
Packit |
fcad23 |
ivector.data);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
krb5_finish_key(kcontext, &eblock);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* NETSNMP_USE_KERBEROS_MIT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Decryption failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*parms->scopedPduLen = length;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Clear PDU
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*parms->scopedPdu = current;
|
|
Packit |
fcad23 |
*parms->scopedPduLen =
|
|
Packit |
fcad23 |
parms->wholeMsgLen - (current - parms->wholeMsg);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* A HUGE GROSS HACK
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*parms->maxSizeResponse = parms->maxMsgSize - 200;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM processing complete\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Set the secName to the right value (a hack for now). But that's
|
|
Packit |
fcad23 |
* only used for when we're processing a request, not a response.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!response) {
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
retcode = krb5_unparse_name(kcontext, TICKET_CLIENT(ticket),
|
|
Packit |
fcad23 |
&cname);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (retcode) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM krb5_unparse_name failed: %s\n",
|
|
Packit |
fcad23 |
error_message(retcode)));
|
|
Packit |
fcad23 |
snmp_set_detail(error_message(retcode));
|
|
Packit |
fcad23 |
retval = SNMPERR_KRB5;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (strlen(cname) > *parms->secNameLen + 1) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm",
|
|
Packit |
fcad23 |
"KSM: Principal length (%d) is too long (%d)\n",
|
|
Packit |
fcad23 |
(int)strlen(cname), (int)*parms->secNameLen));
|
|
Packit |
fcad23 |
retval = SNMPERR_TOO_LONG;
|
|
Packit |
fcad23 |
free(cname);
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
strcpy(parms->secName, cname);
|
|
Packit |
fcad23 |
*parms->secNameLen = strlen(cname);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
free(cname);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Also, if we're not a response, keep around our auth_context so we
|
|
Packit |
fcad23 |
* can encode the reply message correctly
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
ksm_state = SNMP_MALLOC_STRUCT(ksm_secStateRef);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!ksm_state) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "KSM unable to malloc memory for "
|
|
Packit |
fcad23 |
"ksm_secStateRef\n"));
|
|
Packit |
fcad23 |
retval = SNMPERR_MALLOC;
|
|
Packit |
fcad23 |
goto error;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
ksm_state->auth_context = auth_context;
|
|
Packit |
fcad23 |
auth_context = NULL;
|
|
Packit |
fcad23 |
ksm_state->cksumtype = cksumtype;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*parms->secStateRef = ksm_state;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* We _still_ have to set the secName in process_in_msg(). Do
|
|
Packit |
fcad23 |
* that now with what we were passed in before (we cached it,
|
|
Packit |
fcad23 |
* remember?)
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
memcpy(parms->secName, entry->secName, entry->secNameLen);
|
|
Packit |
fcad23 |
*parms->secNameLen = entry->secNameLen;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Just in case
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
parms->secEngineID = null_id;
|
|
Packit |
fcad23 |
*parms->secEngineIDLen = 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
auth_context = NULL; /* So we don't try to free it on success */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
error:
|
|
Packit |
fcad23 |
if (retval == SNMPERR_ASN_PARSE_ERR &&
|
|
Packit |
fcad23 |
snmp_increment_statistic(STAT_SNMPINASNPARSEERRS) == 0)
|
|
Packit |
fcad23 |
DEBUGMSGTL(("ksm", "Failed to increment statistics.\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (subkey)
|
|
Packit |
fcad23 |
krb5_free_keyblock(kcontext, subkey);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifdef OLD_HEIMDAL /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
if (heim_crypto)
|
|
Packit |
fcad23 |
krb5_crypto_destroy(kcontext, heim_crypto);
|
|
Packit |
fcad23 |
#endif /* OLD_HEIMDAL */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (CHECKSUM_CONTENTS(&checksum))
|
|
Packit |
fcad23 |
free(CHECKSUM_CONTENTS(&checksum));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (ivector.data)
|
|
Packit |
fcad23 |
free(ivector.data);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (ticket)
|
|
Packit |
fcad23 |
krb5_free_ticket(kcontext, ticket);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!response && auth_context)
|
|
Packit |
fcad23 |
krb5_auth_con_free(kcontext, auth_context);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (ap_req.data)
|
|
Packit |
fcad23 |
free(ap_req.data);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return retval;
|
|
Packit |
fcad23 |
}
|