21 RCSID(
"$Id: e6491b74db3944bd150af2d926c132e204b93d04 $")
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;
57 tDataList *nodeName = NULL;
58 tAttributeEntryPtr pAttrEntry = NULL;
59 tDataList *pRecName = NULL;
60 tDataList *pRecType = NULL;
61 tDataList *pAttrType = NULL;
63 tRecordEntry *pRecEntry = NULL;
64 tAttributeListRef attrListRef = 0;
65 char *pUserLocation = NULL;
66 tAttributeValueListRef valueRef = 0;
67 tDataList *pUserNode = NULL;
71 REDEBUG(
"getUserNodeRef(): No username");
75 tDataBuff = dsDataBufferAllocate(dsRef, 4096);
77 REDEBUG(
"Failed allocating buffer");
83 status = dsFindDirNodes(dsRef, tDataBuff, NULL,
84 eDSAuthenticationSearchNodeName,
86 #define OPEN_DIR_ERROR(_x) do if (status != eDSNoErr) { \
91 OPEN_DIR_ERROR(
"Failed to find directory");
94 what =
"No directories found.";
98 status = dsGetDirNodeName(dsRef, tDataBuff, 1, &nodeName);
99 OPEN_DIR_ERROR(
"Failed getting directory name");
101 status = dsOpenDirNode(dsRef, nodeName, &nodeRef);
102 dsDataListDeallocate(dsRef, nodeName);
106 OPEN_DIR_ERROR(
"Failed opening directory");
108 pRecName = dsBuildListFromStrings(dsRef, inUserName, NULL);
109 pRecType = dsBuildListFromStrings(dsRef, kDSStdRecordTypeUsers,
111 pAttrType = dsBuildListFromStrings(dsRef,
112 kDSNAttrMetaNodeLocation,
113 kDSNAttrRecordName, NULL);
116 status = dsGetRecordList(nodeRef, tDataBuff, pRecName,
117 eDSExact, pRecType, pAttrType, 0,
119 OPEN_DIR_ERROR(
"Failed getting record list");
122 what =
"No user records returned";
126 status = dsGetRecordEntry(nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry);
127 OPEN_DIR_ERROR(
"Failed getting record entry");
129 for (attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++) {
130 status = dsGetAttributeEntry(nodeRef, tDataBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry);
131 if (status == eDSNoErr && pAttrEntry != NULL) {
132 tAttributeValueEntry *pValueEntry = NULL;
134 if (strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation) == 0) {
135 status = dsGetAttributeValue(nodeRef, tDataBuff, 1, valueRef, &pValueEntry);
136 if (status == eDSNoErr && pValueEntry != NULL) {
138 pValueEntry->fAttributeValueData.fBufferData,
139 pValueEntry->fAttributeValueData.fBufferLength);
141 }
else if (strcmp(pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName) == 0) {
142 status = dsGetAttributeValue(nodeRef, tDataBuff, 1, valueRef, &pValueEntry);
143 if (status == eDSNoErr && pValueEntry != NULL) {
145 pValueEntry->fAttributeValueData.fBufferData,
146 pValueEntry->fAttributeValueData.fBufferLength);
151 dsDeallocAttributeValueEntry(dsRef, pValueEntry);
155 dsDeallocAttributeEntry(dsRef, pAttrEntry);
157 dsCloseAttributeValueList(valueRef);
162 if (!pUserLocation) {
163 DEBUG2(
"[mschap] OpenDirectory has no user location");
172 if (strncmp(pUserLocation, kActiveDirLoc, strlen(kActiveDirLoc)) == 0) {
173 DEBUG2(
"[mschap] OpenDirectory authentication returning noop. OD doesn't support MSCHAPv2 for ActiveDirectory users");
178 pUserNode = dsBuildFromPath(dsRef, pUserLocation,
"/");
180 RERROR(
"Failed building user from path");
185 status = dsOpenDirNode(dsRef, pUserNode, userNodeRef);
186 dsDataListDeallocate(dsRef, pUserNode);
189 if (status != eDSNoErr) {
191 status_name = dsCopyDirStatusName(status);
192 RERROR(
"%s: status = %s", what, status_name);
201 if (pRecEntry != NULL) dsDeallocRecordEntry(dsRef, pRecEntry);
203 if (tDataBuff != NULL) dsDataBufferDeAllocate(dsRef, tDataBuff);
205 if (pUserLocation != NULL)
208 if (pRecName != NULL) {
209 dsDataListDeallocate(dsRef, pRecName);
212 if (pRecType != NULL) {
213 dsDataListDeallocate(dsRef, pRecType);
216 if (pAttrType != NULL) {
217 dsDataListDeallocate(dsRef, pAttrType);
220 if (nodeRef != 0) dsCloseDirNode(nodeRef);
229 tDirStatus status = eDSNoErr;
230 tDirReference dsRef = 0;
231 tDirNodeReference userNodeRef = 0;
232 tDataBuffer *tDataBuff = NULL;
233 tDataBuffer *pStepBuff = NULL;
234 tDataNode *pAuthType = NULL;
237 char *username_string = NULL;
238 char *short_user_name = NULL;
246 username_string = talloc_array(request,
char, usernamepair->vp_length + 1);
249 strlcpy(username_string, usernamepair->vp_strvalue, usernamepair->vp_length + 1);
251 status = dsOpenDirService(&dsRef);
252 if (status != eDSNoErr) {
254 RERROR(
"Failed opening directory service");
258 getUserNodeRef(&rcode, request, username_string, &short_user_name, &userNodeRef, dsRef);
261 RDEBUG2(
"od_mschap_auth: getUserNodeRef() failed");
263 if (username_string != NULL)
266 dsCloseDirService(dsRef);
291 pStepBuff = dsDataBufferAllocate(dsRef, 4096);
292 tDataBuff = dsDataBufferAllocate(dsRef, 4096);
293 pAuthType = dsDataNodeAllocateString(dsRef, kDSStdAuthMSCHAP2);
296 user_id_len = (
uint32_t)(short_user_name ? strlen(short_user_name) : 0);
298 RDEBUG2(
"OD username_string = %s, OD short_user_name=%s (length = %u)",
299 username_string, short_user_name, user_id_len);
302 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
303 uiCurr +=
sizeof(user_id_len);
304 memcpy(&(tDataBuff->fBufferData[uiCurr]), short_user_name, user_id_len);
305 uiCurr += user_id_len;
308 RDEBUG2(
"Stepbuf server challenge : ");
309 for (t = 0; t < challenge->vp_length; t++) {
310 fprintf(stderr,
"%02x", (
unsigned int) challenge->vp_strvalue[t]);
312 fprintf(stderr,
"\n");
317 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
318 uiCurr +=
sizeof(user_id_len);
319 memcpy(&(tDataBuff->fBufferData[uiCurr]), &(challenge->vp_strvalue[0]),
321 uiCurr += user_id_len;
324 RDEBUG2(
"Stepbuf peer challenge : ");
325 for (t = 2; t < 18; t++) {
326 fprintf(stderr,
"%02x", (
unsigned int) response->vp_strvalue[t]);
328 fprintf(stderr,
"\n");
333 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
334 uiCurr +=
sizeof(user_id_len);
335 memcpy(&(tDataBuff->fBufferData[uiCurr]), &(response->vp_strvalue[2]),
337 uiCurr += user_id_len;
342 for (t = 26; t < 50; t++) {
343 fprintf(stderr,
"%02x", (
unsigned int) response->vp_strvalue[t]);
345 fprintf(stderr,
"\n");
350 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
351 uiCurr +=
sizeof(user_id_len);
353 memcpy(&(tDataBuff->fBufferData[uiCurr]), &(response->vp_strvalue[26]), user_id_len);
354 uiCurr += user_id_len;
357 user_id_len = (
uint32_t)strlen(username_string);
358 memcpy(&(tDataBuff->fBufferData[uiCurr]), &user_id_len,
sizeof(user_id_len));
359 uiCurr +=
sizeof(user_id_len);
360 memcpy(&(tDataBuff->fBufferData[uiCurr]), username_string, user_id_len);
361 uiCurr += user_id_len;
363 tDataBuff->fBufferLength = uiCurr;
365 status = dsDoDirNodeAuth(userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL);
366 if (status == eDSNoErr) {
367 if (pStepBuff->fBufferLength > 4) {
370 memcpy(&len, pStepBuff->fBufferData,
sizeof(len));
372 char mschap_reply[42] =
"";
373 mschap_reply[0] =
'S';
374 mschap_reply[1] =
'=';
375 memcpy(&(mschap_reply[2]), &(pStepBuff->fBufferData[4]), len);
378 mschap_reply, len + 2);
379 RDEBUG2(
"dsDoDirNodeAuth returns stepbuff: %s (len=%u)\n", mschap_reply, (
unsigned int) len);
385 if (username_string != NULL)
387 if (short_user_name != NULL)
390 if (tDataBuff != NULL)
391 dsDataBufferDeAllocate(dsRef, tDataBuff);
392 if (pStepBuff != NULL)
393 dsDataBufferDeAllocate(dsRef, pStepBuff);
394 if (pAuthType != NULL)
395 dsDataNodeDeAllocate(dsRef, pAuthType);
396 if (userNodeRef != 0)
397 dsCloseDirNode(userNodeRef);
399 dsCloseDirService(dsRef);
401 if (status != eDSNoErr) {
402 char *status_name = dsCopyDirStatusName(status);
403 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_MODULE_REJECT
#define RETURN_MODULE_RCODE(_rcode)
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.