ads questions and multiple values

2006-04-08 Thread liz

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

2006-04-08 Thread Phil Mayers

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

2006-04-08 Thread Phil Mayers

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