21RCSID(
"$Id: c8dd1e58954f66c2542772e77b9e46fb04aa93c7 $")
24#include <freeradius-devel/server/base.h>
25#include <freeradius-devel/server/module_rlm.h>
26#include <freeradius-devel/util/debug.h>
27#include <freeradius-devel/util/md5.h>
35#include <DirectoryService/DirectoryService.h>
37#define kActiveDirLoc "/Active Directory/"
47 tDirNodeReference* userNodeRef, tDirReference dsRef)
49 tDataBuffer *tDataBuff = NULL;
50 tDirNodeReference nodeRef = 0;
51 long status = eDSNoErr;
52 char const *what = NULL;
53 char *status_name = NULL;
55 tDataList *nodeName = NULL;
56 tAttributeEntryPtr pAttrEntry = NULL;
57 tDataList *pRecName = NULL;
58 tDataList *pRecType = NULL;
59 tDataList *pAttrType = NULL;
60 tRecordEntry *pRecEntry = NULL;
61 tAttributeListRef attrListRef = 0;
62 char *pUserLocation = NULL;
63 tAttributeValueListRef valueRef = 0;
64 tDataList *pUserNode = NULL;
79 REDEBUG(
"getUserNodeRef(): No username");
83 tDataBuff = dsDataBufferAllocate(dsRef, 4096);
85 REDEBUG(
"Failed allocating buffer");
91 status = dsFindDirNodes(dsRef, tDataBuff, NULL,
92 eDSAuthenticationSearchNodeName,
94#define OPEN_DIR_ERROR(_x) do if (status != eDSNoErr) { \
99 OPEN_DIR_ERROR(
"Failed to find directory");
102 what =
"No directories found.";
106 status = dsGetDirNodeName(dsRef, tDataBuff, 1, &nodeName);
107 OPEN_DIR_ERROR(
"Failed getting directory name");
109 status = dsOpenDirNode(dsRef, nodeName, &nodeRef);
110 dsDataListDeallocate(dsRef, nodeName);
114 OPEN_DIR_ERROR(
"Failed opening directory");
116 pRecName = dsBuildListFromStrings(dsRef, inUserName, NULL);
117 pRecType = dsBuildListFromStrings(dsRef, kDSStdRecordTypeUsers,
119 pAttrType = dsBuildListFromStrings(dsRef,
120 kDSNAttrMetaNodeLocation,
121 kDSNAttrRecordName, NULL);
124 status = dsGetRecordList(nodeRef, tDataBuff, pRecName,
125 eDSExact, pRecType, pAttrType, 0,
127 OPEN_DIR_ERROR(
"Failed getting record list");
130 what =
"No user records returned";
134 status = dsGetRecordEntry(nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry);
135 OPEN_DIR_ERROR(
"Failed getting record entry");
137 for (attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++) {
138 status = dsGetAttributeEntry(nodeRef, tDataBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry);
139 if (status == eDSNoErr && pAttrEntry != NULL) {
140 tAttributeValueEntry *pValueEntry = NULL;
142 if (strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation) == 0) {
143 status = dsGetAttributeValue(nodeRef, tDataBuff, 1, valueRef, &pValueEntry);
144 if (status == eDSNoErr && pValueEntry != NULL) {
146 pValueEntry->fAttributeValueData.fBufferData,
147 pValueEntry->fAttributeValueData.fBufferLength);
149 }
else if (strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName) == 0) {
150 status = dsGetAttributeValue(nodeRef, tDataBuff, 1, valueRef, &pValueEntry);
151 if (status == eDSNoErr && pValueEntry != NULL) {
153 pValueEntry->fAttributeValueData.fBufferData,
154 pValueEntry->fAttributeValueData.fBufferLength);
159 dsDeallocAttributeValueEntry(dsRef, pValueEntry);
163 dsDeallocAttributeEntry(dsRef, pAttrEntry);
165 dsCloseAttributeValueList(valueRef);
170 if (!pUserLocation) {
171 DEBUG2(
"[mschap] OpenDirectory has no user location");
180 if (strncmp(pUserLocation, kActiveDirLoc, strlen(kActiveDirLoc)) == 0) {
181 DEBUG2(
"[mschap] OpenDirectory authentication returning noop. OD doesn't support MSCHAPv2 for ActiveDirectory users");
186 pUserNode = dsBuildFromPath(dsRef, pUserLocation,
"/");
188 RERROR(
"Failed building user from path");
193 status = dsOpenDirNode(dsRef, pUserNode, userNodeRef);
194 dsDataListDeallocate(dsRef, pUserNode);
197 if (status != eDSNoErr) {
199 status_name = dsCopyDirStatusName(status);
200 RERROR(
"%s: status = %s", what, status_name);
209 if (pRecEntry != NULL) dsDeallocRecordEntry(dsRef, pRecEntry);
211 if (tDataBuff != NULL) dsDataBufferDeAllocate(dsRef, tDataBuff);
213 if (pUserLocation != NULL)
216 if (pRecName != NULL) {
217 dsDataListDeallocate(dsRef, pRecName);
220 if (pRecType != NULL) {
221 dsDataListDeallocate(dsRef, pRecType);
224 if (pAttrType != NULL) {
225 dsDataListDeallocate(dsRef, pAttrType);
228 if (nodeRef != 0) dsCloseDirNode(nodeRef);
237 tDirStatus status = eDSNoErr;
238 tDirReference dsRef = 0;
239 tDirNodeReference userNodeRef = 0;
240 tDataBuffer *tDataBuff = NULL;
241 tDataBuffer *pStepBuff = NULL;
242 tDataNode *pAuthType = NULL;
245 char *username_string = NULL;
246 char *short_user_name = NULL;
254 username_string = talloc_array(request,
char, usernamepair->vp_length + 1);
257 strlcpy(username_string, usernamepair->vp_strvalue, usernamepair->vp_length + 1);
259 status = dsOpenDirService(&dsRef);
260 if (status != eDSNoErr) {
262 RERROR(
"Failed opening directory service");
266 getUserNodeRef(p_result, request, username_string, &short_user_name, &userNodeRef, dsRef);
269 RDEBUG2(
"od_mschap_auth: getUserNodeRef() failed");
271 if (username_string != NULL)
274 dsCloseDirService(dsRef);
299 pStepBuff = dsDataBufferAllocate(dsRef, 4096);
300 tDataBuff = dsDataBufferAllocate(dsRef, 4096);
301 pAuthType = dsDataNodeAllocateString(dsRef, kDSStdAuthMSCHAP2);
304 user_id_len = (
uint32_t)(short_user_name ? strlen(short_user_name) : 0);
306 RDEBUG2(
"OD username_string = %s, OD short_user_name=%s (length = %u)",
307 username_string, short_user_name, user_id_len);
310 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
311 uiCurr +=
sizeof(user_id_len);
312 memcpy(&(tDataBuff->fBufferData[uiCurr]), short_user_name, user_id_len);
313 uiCurr += user_id_len;
316 RDEBUG2(
"Stepbuf server challenge : ");
317 for (t = 0; t < challenge->vp_length; t++) {
318 fprintf(stderr,
"%02x", (
unsigned int) challenge->vp_strvalue[t]);
320 fprintf(stderr,
"\n");
325 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
326 uiCurr +=
sizeof(user_id_len);
327 memcpy(&(tDataBuff->fBufferData[uiCurr]), &(challenge->vp_strvalue[0]),
329 uiCurr += user_id_len;
332 RDEBUG2(
"Stepbuf peer challenge : ");
333 for (t = 2; t < 18; t++) {
334 fprintf(stderr,
"%02x", (
unsigned int) response->vp_strvalue[t]);
336 fprintf(stderr,
"\n");
341 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
342 uiCurr +=
sizeof(user_id_len);
343 memcpy(&(tDataBuff->fBufferData[uiCurr]), &(response->vp_strvalue[2]),
345 uiCurr += user_id_len;
350 for (t = 26; t < 50; t++) {
351 fprintf(stderr,
"%02x", (
unsigned int) response->vp_strvalue[t]);
353 fprintf(stderr,
"\n");
358 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
359 uiCurr +=
sizeof(user_id_len);
361 memcpy(&(tDataBuff->fBufferData[uiCurr]), &(response->vp_strvalue[26]), user_id_len);
362 uiCurr += user_id_len;
365 user_id_len = (
uint32_t)strlen(username_string);
366 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
367 uiCurr +=
sizeof(user_id_len);
368 memcpy(&(tDataBuff->fBufferData[uiCurr]), username_string, user_id_len);
369 uiCurr += user_id_len;
371 tDataBuff->fBufferLength = uiCurr;
373 status = dsDoDirNodeAuth(userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL);
374 if (status == eDSNoErr) {
375 if (pStepBuff->fBufferLength > 4) {
378 memcpy(&len, pStepBuff->fBufferData,
sizeof(len));
380 char mschap_reply[42] =
"";
381 mschap_reply[0] =
'S';
382 mschap_reply[1] =
'=';
383 memcpy(&(mschap_reply[2]), &(pStepBuff->fBufferData[4]), len);
386 mschap_reply, len + 2);
387 RDEBUG2(
"dsDoDirNodeAuth returns stepbuff: %s (len=%u)\n", mschap_reply, (
unsigned int) len);
393 if (username_string != NULL)
395 if (short_user_name != NULL)
398 if (tDataBuff != NULL)
399 dsDataBufferDeAllocate(dsRef, tDataBuff);
400 if (pStepBuff != NULL)
401 dsDataBufferDeAllocate(dsRef, pStepBuff);
402 if (pAuthType != NULL)
403 dsDataNodeDeAllocate(dsRef, pAuthType);
404 if (userNodeRef != 0)
405 dsCloseDirNode(userNodeRef);
407 dsCloseDirService(dsRef);
409 if (status != eDSNoErr) {
410 char *status_name = dsCopyDirStatusName(status);
411 RERROR(
"Authentication failed - status = %s", status_name);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define USES_APPLE_DEPRECATED_API
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RINDENT()
Indent R* messages by one level.
void mschap_add_reply(request_t *request, uint8_t ident, fr_dict_attr_t const *da, char const *value, size_t len)
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_REJECT
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
tmpl_t const * chap2_response
tmpl_t const * chap2_success
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
size_t strlcpy(char *dst, char const *src, size_t siz)
Stores an attribute, a value and various bits of other data.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.