X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Frlm_ldap%2Fedir_ldapext.c;h=0c48ee8b810a8547e3f088d44b55da0b44bd14ab;hb=f67727e2d6e019246b445a8b6f5d5890aee2d568;hp=1e4a128396e192f4654b3d8c6fd89b7e7914887c;hpb=0ed19a6b20a1d0bacb91a9257ffde6fdcdbe6506;p=freeradius.git diff --git a/src/modules/rlm_ldap/edir_ldapext.c b/src/modules/rlm_ldap/edir_ldapext.c index 1e4a128..0c48ee8 100644 --- a/src/modules/rlm_ldap/edir_ldapext.c +++ b/src/modules/rlm_ldap/edir_ldapext.c @@ -1,8 +1,8 @@ -/* +/* * 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. @@ -17,12 +17,19 @@ * * To contact Novell about this file by physical or electronic mail, you may * find current contact information at www.novell.com. - */ + * + * Copyright 2006 The FreeRADIUS Server Project. + */ + +#include +RCSID("$Id$") #include #include #include +#include #include + /* NMAS error codes */ #define NMAS_E_BASE (-1600) @@ -44,6 +51,13 @@ #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 /* ------------------------------------------------------------------------ @@ -125,8 +139,8 @@ int berEncodePasswordData( 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) { @@ -192,7 +206,7 @@ int berDecodeLoginData( memcpy(retData, retOctStr, retOctStrLen); } else if (!err) - { + { err = NMAS_E_BUFFER_OVERFLOW; } @@ -303,7 +317,7 @@ int nmasldap_get_password( /* Do we have a good returned berval? */ if(!replyBV) { - /* + /* * No; returned berval means we experienced a rather drastic error. * Return operations error. */ @@ -361,3 +375,289 @@ Cleanup: /* 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 */ +