-/*
+/*
* Copyright (C) 2002-2004 Novell, Inc.
*
* edir_ldapext.c LDAP extension for reading eDirectory universal password
- *
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
* find current contact information at www.novell.com.
*
* Copyright 2006 The FreeRADIUS Server Project.
- */
+ */
#include <freeradius-devel/ident.h>
RCSID("$Id$")
#define NMAS_LDAP_EXT_VERSION 1
+/* OID of LDAP extension call to perform NMAS authentication */
+#define RADAUTH_OID_NMAS_AUTH_REQUEST "2.16.840.1.113719.1.510.100.1"
+#define RADAUTH_OID_NMAS_AUTH_REPLY "2.16.840.1.113719.1.510.100.2"
+
+#define RADAUTH_LDAP_EXT_VERSION 1
+
+#define REQUEST_CHALLENGED 1
/* ------------------------------------------------------------------------
err = 0;
}
- /*
- * Convert the BER we just built to a berval that we'll send with the extended request.
+ /*
+ * Convert the BER we just built to a berval that we'll send with the extended request.
*/
if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
{
memcpy(retData, retOctStr, retOctStrLen);
}
else if (!err)
- {
+ {
err = NMAS_E_BUFFER_OVERFLOW;
}
/* Do we have a good returned berval? */
if(!replyBV)
{
- /*
+ /*
* No; returned berval means we experienced a rather drastic error.
* Return operations error.
*/
/* Return the appropriate error/success code. */
return err;
} /* end of nmasldap_get_password */
+
+/* ------------------------------------------------------------------------
+ * berEncodeAuthData
+ * ==============================
+ * RequestBer contents:
+ * targetObjectDN OCTET STRING
+ * pwd OCTET STRING
+ * NasIP OCTET STRING
+ * stete OCTET STRING
+ *
+ * Description:
+ * This function takes the request BER value and input data items
+ * and BER encodes the data into the BER value
+ *
+ * ------------------------------------------------------------------------ */
+int berEncodeAuthData(
+ struct berval **requestBV,
+ char *objectDN,
+ char *pwd,
+ char *sequence,
+ char *NasIP,
+ char *state,
+ int *auth_state)
+{
+ int err = 0, rc=0;
+ BerElement *requestBer = NULL;
+
+ char * utf8ObjPtr = NULL;
+ int utf8ObjSize = 0;
+ char * utf8PwdPtr = NULL;
+ int utf8PwdSize = 0;
+ char * utf8NasIPPtr = NULL;
+ int utf8NasIPSize = 0;
+ char * utf8StatePtr = NULL;
+ int utf8StateSize = 0;
+ char * utf8SeqPtr = NULL;
+ int utf8SeqSize = 0;
+ int state_present = 0;
+
+ utf8ObjSize = strlen(objectDN)+1;
+ utf8ObjPtr = objectDN;
+
+ utf8PwdSize = strlen(pwd);
+ utf8PwdPtr = pwd;
+
+ utf8SeqSize = strlen(sequence)+1;
+ utf8SeqPtr = sequence;
+
+ utf8NasIPSize = strlen(NasIP)+1;
+ utf8NasIPPtr = NasIP;
+
+ /* Allocate a BerElement for the request parameters.*/
+ if((requestBer = ber_alloc()) == NULL)
+ {
+ err = NMAS_E_FRAG_FAILURE;
+ goto Cleanup;
+ }
+
+ /* BER encode the NMAS Version, the objectDN, and the password */
+ rc = ber_printf(requestBer, "{i", RADAUTH_LDAP_EXT_VERSION);
+ rc = ber_printf(requestBer, "o", utf8ObjPtr, utf8ObjSize);
+ rc = ber_printf(requestBer, "o", utf8PwdPtr, utf8PwdSize);
+ rc = ber_printf(requestBer, "o", utf8SeqPtr, utf8SeqSize);
+ rc = ber_printf(requestBer, "o", utf8NasIPPtr, utf8NasIPSize);
+
+ if( *auth_state == -2)
+ {
+ utf8StateSize = strlen(state)+1;
+ utf8StatePtr = state;
+ state_present = 1;
+ rc = ber_printf(requestBer, "io}", state_present, utf8StatePtr, utf8StateSize);
+ }
+ else
+ {
+ rc = ber_printf(requestBer, "i}", state_present);
+ }
+
+ if (rc < 0)
+ {
+ err = NMAS_E_FRAG_FAILURE;
+ goto Cleanup;
+ }
+ else
+ {
+ err = 0;
+ }
+ /*
+ * Convert the BER we just built to a berval that we'll send with the extended request.
+ */
+ if(ber_flatten(requestBer, requestBV) == -1)
+ {
+ err = NMAS_E_FRAG_FAILURE;
+ goto Cleanup;
+ }
+
+Cleanup:
+
+ if(requestBer)
+ {
+ ber_free(requestBer, 1);
+ }
+
+ return err;
+} /* End of berEncodeAuthData */
+
+/* ------------------------------------------------------------------------
+ * berDecodeAuthData()
+ * ==============================
+ * ResponseBer contents:
+ * serverVersion INTEGER
+ * auth_state INTEGER
+ * challenge_data OCTET STRING
+ *
+ * Description:
+ * This function takes the reply BER Value and decodes the
+ * server version and return code and if a non null retData
+ * buffer was supplied, tries to decode the the return data and length
+ *
+ * ------------------------------------------------------------------------ */
+int berDecodeAuthData(
+ struct berval *replyBV,
+ int *errCode,
+ size_t *retDataLen,
+ char *retData,
+ int *auth_state )
+{
+ int rc=0, err = 0;
+ BerElement *replyBer = NULL;
+ struct berval challenge = {0};
+
+ if((replyBer = ber_init(replyBV)) == NULL)
+ {
+ err = NMAS_E_SYSTEM_RESOURCES; // fix err code
+ goto Cleanup;
+ }
+ if( (rc = ber_scanf(replyBer, "{ii", errCode, auth_state)) != -1)
+ {
+ if ( *auth_state != REQUEST_CHALLENGED )
+ {
+ if( (rc = ber_scanf(replyBer, "}")) != -1)
+ return err;
+ }
+ else
+ {
+ if( (rc = ber_scanf(replyBer, "o}", &challenge)) != -1)
+ {
+ if (*retDataLen >= challenge.bv_len)
+ {
+ memcpy(retData, challenge.bv_val, challenge.bv_len);
+ }
+ *retDataLen = challenge.bv_len;
+ }
+ }
+ }
+
+Cleanup:
+ if(replyBer)
+ {
+ ber_free(replyBer, 1);
+ }
+
+ return err;
+}/* End of berDecodeLoginData */
+
+/* -----------------------------------------------------------------------
+ * radLdapXtnNMASAuth()
+ * ==============================
+ *
+ * Description:
+ * This API attempts to perform NMAS authentication.
+ *
+ * ------------------------------------------------------------------------ */
+int radLdapXtnNMASAuth(
+ LDAP *ld,
+ char *objectDN,
+ char *pwd,
+ char *sequence,
+ char *NasIPaddr,
+ size_t *statesize,
+ char *state,
+ int *auth_state
+)
+{
+ int err = 0;
+
+ struct berval *requestBV = NULL;
+ char *replyOID = NULL;
+ struct berval *replyBV = NULL;
+ int errCode;
+ char *challenge;
+ size_t challengesize;
+
+ challengesize = *statesize;
+ challenge = (char *)malloc(challengesize+2);
+ if(challenge == NULL)
+ {
+ return NMAS_E_INSUFFICIENT_MEMORY;
+ }
+
+ /* Validate char parameters. */
+ if(objectDN == NULL || (strlen(objectDN) == 0) || statesize == NULL || NasIPaddr == NULL || ld == NULL)
+ {
+ return NMAS_E_INVALID_PARAMETER;
+ }
+
+ err = berEncodeAuthData(&requestBV, objectDN, pwd, sequence, NasIPaddr, state, auth_state);
+
+ if(err)
+ {
+ goto Cleanup;
+ }
+
+ /* Call the ldap_extended_operation (synchronously) */
+ if((err = ldap_extended_operation_s(ld, RADAUTH_OID_NMAS_AUTH_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV))!=0)
+ {
+ goto Cleanup;
+ }
+ /* Make sure there is a return OID */
+ if(!replyOID)
+ {
+ err = NMAS_E_NOT_SUPPORTED; // change error values
+ goto Cleanup;
+ }
+
+ /* Is this what we were expecting to get back. */
+ if(strcmp(replyOID, RADAUTH_OID_NMAS_AUTH_REPLY))
+ {
+ err = NMAS_E_NOT_SUPPORTED; // change return value
+ goto Cleanup;
+ }
+
+ /* Do we have a good returned berval? */
+ if(!replyBV)
+ {
+ /*
+ * No; returned berval means we experienced a rather drastic error.
+ * Return operations error.
+ */
+ err = NMAS_E_SYSTEM_RESOURCES; //change return value
+ goto Cleanup;
+ }
+ err = berDecodeAuthData(replyBV, &errCode, &challengesize, challenge, auth_state);
+
+/* errCode return error in case of AUTH-REJECT */
+ if (!err && challengesize!= 0)
+ {
+ if (*statesize >= challengesize+1 && challenge != NULL)
+ {
+ memcpy(state, challenge, challengesize);
+ state[challengesize] = 0; /* add null termination */
+ }
+ *statesize = challengesize; /* does not include null termination */
+ }
+
+Cleanup:
+ /* Free memory allocated for challenge */
+ if(challenge)
+ {
+ free(challenge);
+ }
+
+ if(replyBV)
+ {
+ ber_bvfree(replyBV);
+ }
+
+ /* Free the return OID string if one was returned. */
+ if(replyOID)
+ {
+ ldap_memfree(replyOID);
+ }
+
+ /* Free memory allocated while building the request ber and berval. */
+ if(requestBV)
+ {
+ ber_bvfree(requestBV);
+ }
+
+#ifdef NOT_N_PLAT_NLM
+ SetThreadGroupID(currentThreadGroupID);
+#endif
+
+ /* Return the appropriate error/success code. */
+ return err;
+}/* End of radLdapXtnNMASAuth */
+