32 #include <freeradius-devel/radiusd.h>
33 #include <freeradius-devel/modules.h>
34 #include <freeradius-devel/rad_assert.h>
41 #include <sys/types.h>
44 #include <DirectoryService/DirectoryService.h>
45 #include <membership.h>
47 #ifndef HAVE_DECL_MBR_CHECK_SERVICE_MEMBERSHIP
50 #ifndef HAVE_DECL_MBR_CHECK_MEMBERSHIP_REFRESH
55 #define kRadiusSACLName "com.apple.access_radius"
56 #define kRadiusServiceName "radius"
58 #define kAuthType "opendirectory"
68 long result = eDSAuthFailed;
69 tDirReference dsRef = 0;
70 tDataBuffer *tDataBuff;
71 tDirNodeReference nodeRef = 0;
72 long status = eDSNoErr;
73 tContextData context = 0;
74 uint32_t nodeCount = 0;
75 uint32_t attrIndex = 0;
76 tDataList *nodeName = NULL;
77 tAttributeEntryPtr pAttrEntry = NULL;
78 tDataList *pRecName = NULL;
79 tDataList *pRecType = NULL;
80 tDataList *pAttrType = NULL;
81 uint32_t recCount = 0;
82 tRecordEntry *pRecEntry = NULL;
83 tAttributeListRef attrListRef = 0;
84 char *pUserLocation = NULL;
85 char *pUserName = NULL;
86 tAttributeValueListRef valueRef = 0;
87 tAttributeValueEntry *pValueEntry = NULL;
88 tDataList *pUserNode = NULL;
89 tDirNodeReference userNodeRef = 0;
90 tDataBuffer *pStepBuff = NULL;
91 tDataNode *pAuthType = NULL;
92 tAttributeValueEntry *pRecordType = NULL;
97 if (!uname || !password)
102 status = dsOpenDirService( &dsRef );
103 if ( status != eDSNoErr )
106 tDataBuff = dsDataBufferAllocate( dsRef, 4096 );
111 status = dsFindDirNodes( dsRef, tDataBuff, NULL, eDSSearchNodeName, &nodeCount, &context );
112 if (status != eDSNoErr || nodeCount < 1)
115 status = dsGetDirNodeName( dsRef, tDataBuff, 1, &nodeName );
116 if (status != eDSNoErr)
119 status = dsOpenDirNode( dsRef, nodeName, &nodeRef );
120 dsDataListDeallocate( dsRef, nodeName );
123 if (status != eDSNoErr)
126 pRecName = dsBuildListFromStrings( dsRef, uname, NULL );
127 pRecType = dsBuildListFromStrings( dsRef, kDSStdRecordTypeUsers, kDSStdRecordTypeComputers, kDSStdRecordTypeMachines, NULL );
128 pAttrType = dsBuildListFromStrings( dsRef, kDSNAttrMetaNodeLocation, kDSNAttrRecordName, kDSNAttrRecordType, NULL );
131 status = dsGetRecordList( nodeRef, tDataBuff, pRecName, eDSExact, pRecType,
132 pAttrType, 0, &recCount, &context );
133 if ( status != eDSNoErr || recCount == 0 )
136 status = dsGetRecordEntry( nodeRef, tDataBuff, 1, &attrListRef, &pRecEntry );
137 if ( status != eDSNoErr )
140 for ( attrIndex = 1; (attrIndex <= pRecEntry->fRecordAttributeCount) && (status == eDSNoErr); attrIndex++ )
142 status = dsGetAttributeEntry( nodeRef, tDataBuff, attrListRef, attrIndex, &valueRef, &pAttrEntry );
143 if ( status == eDSNoErr && pAttrEntry != NULL )
145 if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrMetaNodeLocation ) == 0 )
147 status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry );
148 if ( status == eDSNoErr && pValueEntry != NULL )
150 pUserLocation = talloc_zero_array(request,
char, pValueEntry->fAttributeValueData.fBufferLength + 1);
151 memcpy( pUserLocation, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength );
155 if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordName ) == 0 )
157 status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry );
158 if ( status == eDSNoErr && pValueEntry != NULL )
160 pUserName = talloc_zero_array(request,
char, pValueEntry->fAttributeValueData.fBufferLength + 1);
161 memcpy( pUserName, pValueEntry->fAttributeValueData.fBufferData, pValueEntry->fAttributeValueData.fBufferLength );
165 if ( strcmp( pAttrEntry->fAttributeSignature.fBufferData, kDSNAttrRecordType ) == 0 )
167 status = dsGetAttributeValue( nodeRef, tDataBuff, 1, valueRef, &pValueEntry );
168 if ( status == eDSNoErr && pValueEntry != NULL )
170 pRecordType = pValueEntry;
175 if ( pValueEntry != NULL ) {
176 dsDeallocAttributeValueEntry( dsRef, pValueEntry );
179 if ( pAttrEntry != NULL ) {
180 dsDeallocAttributeEntry( dsRef, pAttrEntry );
183 dsCloseAttributeValueList( valueRef );
188 pUserNode = dsBuildFromPath( dsRef, pUserLocation,
"/" );
189 status = dsOpenDirNode( dsRef, pUserNode, &userNodeRef );
190 dsDataListDeallocate( dsRef, pUserNode );
193 if ( status != eDSNoErr )
196 pStepBuff = dsDataBufferAllocate( dsRef, 128 );
198 pAuthType = dsDataNodeAllocateString( dsRef, kDSStdAuthNodeNativeClearTextOK );
202 RDEBUG(
"Failed to find user name");
207 uiLen = (uint32_t)strlen( pUserName );
208 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &uiLen,
sizeof(uiLen) );
209 uiCurr += (uint32_t)
sizeof( uiLen );
210 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), pUserName, uiLen );
214 pwLen = (uint32_t)strlen( password );
215 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), &pwLen,
sizeof(pwLen) );
216 uiCurr += (uint32_t)
sizeof( pwLen );
217 memcpy( &(tDataBuff->fBufferData[ uiCurr ]), password, pwLen );
220 tDataBuff->fBufferLength = uiCurr;
222 result = dsDoDirNodeAuthOnRecordType( userNodeRef, pAuthType, 1, tDataBuff, pStepBuff, NULL, &pRecordType->fAttributeValueData );
227 if (pAuthType != NULL) {
228 dsDataNodeDeAllocate( dsRef, pAuthType );
231 if (pRecordType != NULL) {
232 dsDeallocAttributeValueEntry( dsRef, pRecordType );
235 if (tDataBuff != NULL) {
236 bzero( tDataBuff, tDataBuff->fBufferSize );
237 dsDataBufferDeAllocate( dsRef, tDataBuff );
240 if (pStepBuff != NULL) {
241 dsDataBufferDeAllocate( dsRef, pStepBuff );
244 if (pUserLocation != NULL) {
245 talloc_free(pUserLocation);
246 pUserLocation = NULL;
248 if (pUserName != NULL) {
249 talloc_free(pUserName);
252 if (pRecName != NULL) {
253 dsDataListDeallocate( dsRef, pRecName );
257 if (pRecType != NULL) {
258 dsDataListDeallocate( dsRef, pRecType );
262 if (pAttrType != NULL) {
263 dsDataListDeallocate( dsRef, pAttrType );
268 dsCloseDirNode(nodeRef);
272 dsCloseDirService(dsRef);
287 long odResult = eDSAuthFailed;
293 if (!request->username) {
294 REDEBUG(
"You set 'Auth-Type = OpenDirectory' for a request that does not contain a User-Name attribute!");
301 if (!request->password ||
302 (request->password->da->attr != PW_USER_PASSWORD)) {
303 REDEBUG(
"You set 'Auth-Type = OpenDirectory' for a request that does not contain a User-Password attribute!");
308 request->password->vp_strvalue);
314 case eDSAuthUnknownUser:
315 case eDSAuthInvalidUserName:
316 case eDSAuthNewPasswordRequired:
317 case eDSAuthPasswordExpired:
318 case eDSAuthAccountDisabled:
319 case eDSAuthAccountExpired:
320 case eDSAuthAccountInactive:
321 case eDSAuthInvalidLogonHours:
322 case eDSAuthInvalidComputer:
332 RDEBUG(
"[%s]: Invalid password", request->username->vp_strvalue);
345 struct passwd *userdata = NULL;
350 uuid_t guid_nasgroup;
352 char host_ipaddr[128] = {0};
355 if (!request->username) {
356 RDEBUG(
"OpenDirectory requires a User-Name attribute");
361 uuid_clear(guid_sacl);
366 err = mbr_gid_to_uuid(gid, guid_sacl);
374 uuid_clear(guid_nasgroup);
376 rad_client = request->client;
378 if (rad_client->community[0] !=
'\0' )
384 if (uuid_parse(rad_client->community, guid_nasgroup) != 0) {
386 groupdata = getgrnam(rad_client->community);
388 AUTH(
"rlm_opendirectory: The group \"%s\" does not exist on this system.", rad_client->community);
391 err = mbr_gid_to_uuid(groupdata->gr_gid, guid_nasgroup);
393 AUTH(
"rlm_opendirectory: The group \"%s\" does not have a GUID.", rad_client->community);
402 RDEBUG(
"The client record could not be found for host %s.",
404 host_ipaddr,
sizeof(host_ipaddr)));
407 RDEBUG(
"The host %s does not have an access group.",
409 host_ipaddr,
sizeof(host_ipaddr)));
413 if (uuid_is_null(guid_sacl) && uuid_is_null(guid_nasgroup)) {
414 RDEBUG(
"no access control groups, all users allowed");
425 rad_getpwnam(request, &userdata, request->username->vp_strvalue);
426 if (userdata != NULL) {
427 err = mbr_uid_to_uuid(userdata->pw_uid, uuid);
431 talloc_free(userdata);
433 if (uuid_is_null(uuid)) {
434 REDEBUG(
"Could not get the user's uuid");
438 if (!uuid_is_null(guid_sacl)) {
441 REDEBUG(
"Failed to check group membership");
446 REDEBUG(
"User is not authorized");
451 if (!uuid_is_null(guid_nasgroup)) {
454 REDEBUG(
"Failed to check group membership");
459 REDEBUG(
"User is not authorized");
477 .name =
"opendirectory",
The module is OK, continue.
module_t rlm_opendirectory
Metadata exported by the module.
static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
Handle authorization requests using Couchbase document data.
#define RLM_TYPE_THREAD_SAFE
Module is threadsafe.
int mbr_check_membership_refresh(uuid_t const user, uuid_t group, int *ismember)
The module considers the request invalid.
static rlm_rcode_t mod_authenticate(void *instance, REQUEST *request) CC_HINT(nonnull)
int rad_getgid(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Reject the request (user is locked out).
#define pair_make_config(_a, _b, _c)
Immediately reject the request.
USES_APPLE_DEPRECATED_API int mbr_check_service_membership(uuid_t const user, char const *servicename, int *ismember)
int rad_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
Resolve a username to a passwd entry.
0 methods index for authenticate section.
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
Module succeeded without doing anything.
Describes a host allowed to send packets to the server.
uint64_t magic
Used to validate module struct.
Module failed, don't reply.
static rlm_rcode_t CC_HINT(nonnull)
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
1 methods index for authorize section.
char const * fr_inet_ntoh(fr_ipaddr_t const *src, char *out, size_t outlen)
Perform reverse resolution of an IP address.
static long od_check_passwd(REQUEST *request, char const *uname, char const *password)
#define kRadiusServiceName
#define USES_APPLE_DEPRECATED_API