ads questions and multiple values
Greetings, A few more questions :) I've now gone through the book ( I feel like such a snob reading it on the bus ==) and have a better understanding of how Freeradius works. I have gotten it to search for an attribute in LDAP and return it the NAS. What I would like to do is to have it be able to query the memberOf attribute in the acrtive directory server and then verify if the user is in any of those groups and than permit access based on that membership. Heres what im wondering a) When I query the attribute it returns multiple cn=... results. In the debug log I see it setting this as xxx. which is understood by our nas equipment. It does it four times, But in the reply packet I only see it sending one and not four. Am I correct to assume that it will only send one of the responses to the Nas. b) I think I can use the Users file to determine which group the user is a member of and then have it send an attribute back to the Nas telling it which role to set. Is the the attribute returning multiple groups a problem (not multiple attributes, one attribute several bits of data seperated by a delimiter) ? c) can I strip the leading cn= bit from the response the ldap server sends ( I saw an article somewhere about using an operator in the LDAP.attrmap file) and once thats done can it use the groups returned in the users file? Thanks! Liz - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
Re: ads questions and multiple values
liz wrote: What I would like to do is to have it be able to query the memberOf attribute in the acrtive directory server and then verify if the user is in any of those groups and than permit access based on that membership. The "memberOf" attribute (groups on the user entry) is supported by the "groupmembership_attribute" config item, which it seems from reading the code is ONLY consulted AFTER the searches for group objects returns no values. Since AD maintains the group objects and the memberOf in concert, you'll never reach there. The "Ldap-Group" support allows you to check if a user is in a group at the server, and works like so (you probably know this): DEFAULT Ldap-Group = "shortname" Or: DEFAULT Ldap-Group = "cn=shortname,ou=path,dc=domain,dc=com" If you use the first form, the search that's done is: base: standard LDAP baseDN filter: cn=shortname AND (GROUPMEMBERSHIP_FILTER) If you use the 2nd form, the search that's done is: base: cn=shortname,ou=path,dc=domain,dc=com filter: GROUPMEMBERSHIP_FILTER GROUPMEMBERSHIP_FILTER being the config item of the same name in the radiusd.conf - in the case of AD, an appropriate config is: groupmembership_filter = "(&(objectClass=group)(member=%{Ldap-UserDn}))" As I say, only after those searches have been done and returned no entries is memberOf consulted, which will never happen for an AD LDAP server. But the results of looking up the group entry versus looking up memberOf on the user entry should be identical. Heres what im wondering a) When I query the attribute it returns multiple cn=... results. In the debug log I see it setting this as xxx. which is understood by our nas equipment. It does it four times, But in the reply packet I only see it sending one and not four. Am I correct to assume that it will only send one of the responses to the Nas. I'm not sure I understand this part - could you expand on it? How are you putting the LDAP groups into the reply (that's not the normal use-case - you would normally do group-based checks at the server rather than the NAS, not that there's anything wrong with the latter) b) I think I can use the Users file to determine which group the user is a member of and then have it send an attribute back to the Nas telling it which role to set. Is the the attribute returning multiple groups a problem (not multiple attributes, one attribute several bits of data seperated by a delimiter) ? When doing LDAP group checks at the server side, you would normally have something like (examples using the long/DN form for group - you can just put the short name, see above): DEFAULT Ldap-Group == "cn=nasadmin,dc=domain,dc=com" NAS-Role = "Administrator" DEFAULT Ldap-Group == "cn=nasoper,dc=domain,dc=com" NAS-Role = "Operator" DEFAULT Auth-Type := Reject Reply-Message = "You are not able to admin the NAS" The fact the user may be in >1 group is not a problem - the LDAP search looks for the user and the group combination. c) can I strip the leading cn= bit from the response the ldap server sends ( I saw an article somewhere about using an operator in the LDAP.attrmap file) and once thats done can it use the groups returned in the users file? I'm not sure I understand this. The rlm_ldap module does not by default put the groups into the reply. Via the "ldap.attrmap" entry you can put anything you like into the reply, but modifying the value that comes out of the LDAP server is non-trivial. If you could describe more precisely what you're trying to do I may be able to give a more specific answer. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
Re: ads questions and multiple values
Phil Mayers wrote: If you could describe more precisely what you're trying to do I may be able to give a more specific answer. Actually I've just had a quick look at your earlier email and it's a bit clearer what you want to do - take NT groups from AD via LDAP, send them to your Aruba after stripping the name from cn=,ou=path and have it process them - correct? You could do this: ldap.attrmap: # append memberOf to radius reply as Whatever-Attribute replyItem Whatever-Attribute memberOf += radiusd.conf: modules { # bulk of modules, then ldap { # ldap config } # chop end off attr_rewrite stripGroupDn1 { attribute = Whatever-Attribute searchin = reply searchfor = ",.*" replacewith = "" ignore_case = yes new_attribute = no max_matches = 1 append = no } # chop start off attr_rewrite stripGroupDn2 { attribute = Whatever-Attribute searchin = reply searchfor = "^cn=" replacewith = "" ignore_case = yes new_attribute = no max_matches = 1 append = no } # rest of modules } authorize { preprocess ldap stripGroupDn1 stripGroupDn2 files } # rest of radiusd.conf ...however, you'll need CVS HEAD for the ldap.attrmap 4th item (operator) and for fixes to the extraction of replyItems from LDAP attributes - or the (scantily tested) backport I've just written to 1.1.0 (attached) --- src/modules/rlm_ldap/rlm_ldap.c~ 2005-12-29 21:52:53.0 + +++ src/modules/rlm_ldap/rlm_ldap.c 2006-04-08 13:01:49.0 +0100 @@ -919,7 +919,7 @@ return 1; } -if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, req, NULL)) { +if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, req, ldap_escape_func)) { DEBUG("rlm_ldap::ldap_groupcmp: unable to create basedn."); return 1; } @@ -964,7 +964,7 @@ ldap_msgfree(result); } -if(!radius_xlat(gr_filter, sizeof(gr_filter), inst->groupmemb_filt, req, NULL)){ +if(!radius_xlat(gr_filter, sizeof(gr_filter), inst->groupmemb_filt, req, ldap_escape_func)){ DEBUG("rlm_ldap::ldap_groupcmp: unable to create filter."); return 1; } @@ -1235,7 +1235,7 @@ } if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, - request, NULL)) { + request, ldap_escape_func)) { radlog (L_ERR, "rlm_ldap: unable to create basedn.\n"); return RLM_MODULE_INVALID; } @@ -1703,13 +1703,13 @@ while((vp_user_dn = pairfind(request->packet->vps, PW_LDAP_USERDN)) == NULL) { if (!radius_xlat(filter, sizeof(filter), inst->filter, -request, NULL)) { +request, ldap_escape_func)) { radlog (L_ERR, "rlm_ldap: unable to create filter.\n"); return RLM_MODULE_INVALID; } if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, - request, NULL)) { + request, ldap_escape_func)) { radlog (L_ERR, "rlm_ldap: unable to create basedn.\n"); return RLM_MODULE_INVALID; } --- src/modules/rlm_ldap/rlm_ldap.c 2006-04-08 15:12:28.0 +0100 +++ src/modules/rlm_ldap/rlm_ldap.c 2006-04-08 15:17:17.0 +0100 @@ -248,6 +248,7 @@ struct TLDAP_RADIUS { char* attr; char* radius_attr; + LRAD_TOKENoperator; struct TLDAP_RADIUS* next; }; typedef struct TLDAP_RADIUS TLDAP_RADIUS; @@ -657,6 +658,8 @@ /* all buffers are of MAX_LINE_LEN so we can use sscanf without being afraid of buffer overflows */ char buf[MAX_LINE_LEN], itemType[MAX_LINE_LEN], radiusAttribute[MAX_LINE_LEN], ldapAttribute[MAX_LINE_LEN]; int linenumber; + LRAD_TOKEN operator; + char opstring[MAX_LINE_LEN]; /* open the mappings file for reading */ @@ -688,23 +691,39 @@ if (buf[0] == 0) continue; /* extract tokens from the string */ - token_count = sscanf(buf, "%s %s %s", itemType, radiusAttribute, ldapAttribute); + token_count = sscanf(buf, "%s %s %s %s", itemType, radiusAttribute, ldapAttribute, opstring); if (token_count <= 0) /* no tokens */ continue; - if (token_count != 3) { - radlog(L_ERR, "rlm_ldap: Skipping %s line %i: %s", filename, linenumber, buf); - radlog(L_ERR, "rlm_ldap: Expected 3 tokens " - "(Item type, RADIUS Attribute and LDAP Attribute) but found only %i", token_count); + if ((token_count < 3) || (token_count > 4)) { + radlog(L_ERR, "rlm_ldap: Skipping %s line %i: %s", + filename, linenumber, buf); + radlog(L_ERR, "rlm_ldap: Expected 3 to 4 tokens " + "(Item type, RADIUS Attribute and LDAP Attribute) but found only %i", token_count); continue; } + + if (token_count == 3) { + operator = T_INVALID; /* use defaults */ + } else { + char *ptr; + + ptr = opstring; + operator = gettoken(&ptr, buf, sizeof(buf)); + if ((operator < T_OP_ADD) || (operator > T_OP_CMP_EQ)) { +radlog(L_ERR, "rl