[RADIATOR] AuthBy FILE + IfNotExist and/or maintaining Access response

Hugh Irvine hugh at open.com.au
Thu Oct 22 18:02:51 CDT 2009


Hello Nathan -

I would suggest a ClientHook to add an attribute to the request,  
identifying the type of device - you could use OSC-Client-Identifier  
for example.

Then set up different Handlers for each type of device:


<Handler OSC-Client-Identifier = DELL>
	.....
</Handler>

<Handler OSC-Client-Identifier = CISCO>
	.....
</Handler>

<Handler OSC-Client-Identifier = SMC>
	.....
</Handler>

<Handler>
	.....
</Handler>


Otherwise you can use AuthBy GROUP's to alter the execution sequence  
of your AuthBy clauses.

hope that helps

regards

Hugh


On 22 Oct 2009, at 22:34, Nathan Anderson wrote:

> Hola.
>
> I've got a frustrating authentication problem that I have to solve,  
> and although we have grown to love Radiator to death, I cannot seem  
> to find a way to express the logic of my request in such a way that  
> all conditions are met.  I can think of two simple features that  
> might make my problems go away.
>
> Here is the situation: we want centralized authentication for  
> administrative access to network equipment, as well as authorization  
> (privilege level).  I've got Radiator querying an LDAP server  
> (Windows AD, actually) two times with different SearchFilters in  
> order to check AD group membership.  We also desire to have a small  
> list of accounts outside of AD in a simple flat text file (less than  
> 10).  I have all of this working by stacking the two LDAP AuthBys  
> and FILE AuthBy back-to-back using the ContinueUntilAccept policy.   
> So far, so good:
>
> RADIUS.CFG
> ----------
>
> <AuthBy LDAP2>
> 	Identifier			Staff-Admin
>
> 	[...]
>
> 	SearchFilter		(&(memberOf=CN=Admins,CN=Users,DC=domain,DC=local)(%0= 
> %1))
> </AuthBy>
>
> <AuthBy LDAP2>
> 	Identifier			Staff-Normal
>
> 	[...]
>
> 	SearchFilter		(&(memberOf=CN=Staff,CN=Users,DC=domain,DC=local)(%0= 
> %1))
> </AuthBy>
>
> <AuthBy FILE>
> 	Identifier 			Global-Users
>
> 	Filename 			RADIUS-GLOBALS
> </AuthBy>
>
> <Handler>
> 	AuthByPolicy		ContinueUntilAccept
>
> 	AuthBy			Staff-Admin
> 	AuthBy			Staff-Normal
> 	AuthBy			Global-Users
> </Handler>
>
> The basic problem that I now face is that I have three different  
> pieces of networking equipment that interpret a given RADIUS reply  
> attribute differently, and I have not found a way that I can format  
> the reply packet in such a way that it satisfies all three devices.   
> So I need to massage the reply packet based on what kind of  
> equipment I think the request came from.  I have determined a way to  
> reliably identify a particular device, and now I need to be able to  
> change what needs changing.
>
> (you can skip the following if you aren't terribly interested in the  
> details...you can pick up reading again when you see my written  
> expression of frustration: "ARGH")
>
> I have three ethernet switches made by three different  
> manufacturers: Cisco, Dell, and SMC.  All are very IOS-like (well,  
> the Cisco is, obviously).  Out of the three, only the Dell can  
> reliably be identified based on the form of its RADIUS  
> authentication request.
>
> I can pass authorization parameters to the switches using one of two  
> RADIUS reply attributes:
>
> Service-Type
> cisco-avpair
>
> Generally speaking, documentation suggests that the attributes  
> SHOULD be interpreted thusly:
>
> Service-Type:
> - when it equals Login-User, the device grants base privilege level
> - when it equals Administrative-User, the device grants elevated  
> (level 15/"enable") privilege level
>
> cisco-avpair:
> - is really just a string consisting of TACACS+ value pairs  
> concatenated together (I think)
> - when it equals at least "shell:priv-lvl=1", the device grants base  
> privilege level
> - when it equals at least "shell:priv-lvl=15", the device grants  
> elevated ("enable") privilege level
>
> In reality, the different switches interpret the contents of these  
> attributes in slightly different ways (which I discovered after a  
> lot of trial and error):
>
> The Dell switches use cisco-avpair solely to determine privilege  
> level.  If Service-Type is omitted completely, it works fine.  The  
> unfortunate quirk is that if Service-Type is PRESENT and equals  
> Login-User, then the switch will claim that authentication fails.   
> If it is present and equals Administrative-User, authentication  
> passes and it still uses cisco-avpair to determine the appropriate  
> privilege-level.
>
> With the Cisco, I found that (at least with the version of IOS we  
> are running) cisco-avpair is again the only reliable way to actually  
> enforce the privilege level.  However, unlike with the Dell, the  
> Service-Type attribute MUST be present if RADIUS authorization is  
> enabled in the Cisco config, otherwise authentication fails.  Unlike  
> the Dell, it is perfectly fine with being sent Service-Type=Login- 
> User, but it CANNOT be omitted.
>
> The SMC switches do NOT look at cisco-avpair at all.  They enforce  
> base-level/read-only privileges if Service-Type=Login-User and grant  
> "enable" access if Service-Type=Administrative-User.
>
> Thus my dilemma.  I cannot leave off Service-Type or else I can't  
> log into the Ciscos (not to mention that I am given the wrong  
> privilege level when I log into the SMC).  If I include Service-Type  
> but properly set it to Login-User for accounts that shouldn't have  
> enable access, then the Dells fail.  If I leave Service-Type as  
> Administrative-User across the board to pacify the Dells (which  
> doesn't mess with the Cisco at all; it wants to see it present but  
> it looks to cisco-avpair to actually set privileges), then EVERYBODY  
> gets write access to the SMC switches.
>
> ARGH.
>
> (okay, those of you who just want the [relatively] short version can  
> tune back in now)
>
> So the plan of attack is that when I encounter the one device I can  
> reliably identify based on its RADIUS request (the Dell switches), I  
> send Service-Type=Adminstrative-User in the Access-Accept response;  
> in all other cases I leave it alone.
>
> Radiator doesn't have anything in the way of conditional expressions  
> that I've been able to find (if...then), so I cheated and instead  
> created a second AuthBy FILE that has a DEFAULT entry that checks  
> for the identifying mark of the Dells and sets Service-Type  
> appropriately; in order to keep the ContinueUntilAccept policy  
> rolling along, I also set Auth-Type to Ignore and place this  
> "special" FILE AuthBy block at the very top of my Handler:
>
> RADIUS.CFG
> ----------
>
> <Handler>
> 	AuthByPolicy 		ContinueUntilAccept
>
> 	<AuthBy FILE>
> 		Filename 		RADIUS-DELLFIX
> 	</AuthBy>
>
> 	AuthBy			Staff-Admin
> 	AuthBy			Staff-Normal
> 	AuthBy			Global-Users
> </Handler>
>
> RADIUS-DELLFIX
> --------------
>
> DEFAULT	cisco-avpair = "shell:priv-lvl=1", Auth-Type = Ignore
> 		Service-Type = Administrative-User
>
> (Yes, believe it or not: the identifying mark of the Dell is that it  
> actually SENDS a "cisco-avpair" attribute as a check attribute in  
> the request.  Why?  Who knows.)
>
> In my two LDAP AuthBys, I have an AddToReplyIfNotExist that sets  
> Service-Type appropriately assuming that the switch is not a Dell,  
> but does not override what the special Dell-checking FILE AuthBy  
> already set for that value, if in fact it was set ("IfNotExist"):
>
> RADIUS.CFG
> ----------
>
> <AuthBy LDAP2>
> 	Identifier			Staff-Admin
>
> 	[...]
>
> 	SearchFilter		(&(memberOf=CN=Admins,CN=Users,DC=domain,DC=local)(%0= 
> %1))
> 	AddToReply			cisco-avpair=shell:priv-lvl=15
> 	AddToReplyIfNotExist	Service-Type=Administrative-User
> </AuthBy>
>
> <AuthBy LDAP2>
> 	Identifier			Staff-Normal
>
> 	[...]
>
> 	SearchFilter		(&(memberOf=CN=Staff,CN=Users,DC=domain,DC=local)(%0= 
> %1))
> 	AddToReply			cisco-avpair=shell:priv-lvl=1
> 	AddToReplyIfNotExist	Service-Type=Login-User
> </AuthBy>
>
> This works GREAT for the LDAP users!  Everything goes as planned:
>
> (base-privilege LDAP account, Dell switch)
> ------------------------------------------
>
> Code:       Access-Accept
> Attributes:
>        Service-Type = Administrative-User
>        cisco-avpair = "shell:priv-lvl=1"
>
> The handful of users in the FILE AuthBy I mentioned at the beginning  
> (RADIUS-GLOBALS/Global-Users) aren't so lucky, however.  I can find  
> no equivalent to "AddToReplyIfNotExist" for the reply values in the  
> FILE, so Service-Type gets included in the reply packet TWICE:
>
> (base-privilege FILE account, Dell switch)
> ------------------------------------------
>
> Code:       Access-Accept
> Attributes:
>        Service-Type = Administrative-User
>        Service-Type = Login-User
>        cisco-avpair = "shell:priv-lvl=1"
>
> Like I explained in the section you probably skipped over ;), this  
> looks like it should work but the "Service-Type=Login-User" causes  
> the Dell to freak and it does not continue the authentication.
>
> I could solve this problem one of two ways:
>
> 1. In testing, I discovered that the Dell switches apparently only  
> pay attention to the last Service-Type attribute value in the  
> response, so if I could move the Dell "packet mangler" FILE AuthBy  
> to the end of the Handler, I'd be fine:
>
> (base-privilege FILE account, Dell switch)
> ------------------------------------------
>
> Code:       Access-Accept
> Attributes:
>        Service-Type = Login-User
>        cisco-avpair = "shell:priv-lvl=1"
>        Service-Type = Administrative-User
>
> But even with ContinueWhileAccept or ContinueUntilReject, I can't do  
> that, because regardless of what order I have the LDAP and FILE  
> AuthBys in, if the user isn't in all of them, eventually a Reject  
> will happen, and it's game over.
>
> Proposed solution: a new AuthByPolicy that goes through all AuthBys  
> without stopping, but if it encounters an Accept, that Accept cannot  
> be overridden by a later Reject or Ignore...Accepts are "locked-in"  
> once granted.
>
> 2. If only reply attributes inside of a FILE that were identical in  
> name to one(s) already added to the reply packet before it reached  
> the FILE didn't stack on top of previous ones, but were just simply  
> ignored...
>
> (sample entry from RADIUS-GLOBALS)
> ----------------------------------
>
> fred	Password = "flinstone"
> 	cisco-avpair = "shell:priv-lvl=1",
> 	Service-Type = Login-User
> -------------^ if this was already set earlier, I want this to be  
> ignored
>
> Proposed solution: a new option flag for AuthBy FILE (say,  
> "AddAttrIfNotExist") that told the AuthBy FILE module to not add to  
> or override previous reply attributes that have already been set.
>
> In a similar vein, I belive that FreeRADIUS's flat-text file format  
> allows for different operators that cause the reply attribute to be  
> treated in more fine-grained ways (I think the way it works is that  
> the '+=' stacks reply attributes, much like what Radiator is  
> currently doing; ':=' overrides an existing reply attribute; and '='  
> works like how I envision my hypothetical "AddAttrIfNotExist" flag  
> would).  Perhaps a better suggestion would be to have an AuthBy  
> FREERADIUSFILE module that allowed you to use this syntax, or  
> implement more operators in the current AuthBy FILE?
>
> Also, while I'm dreaming :), I was thinking it might be nice to have  
> an AuthBy module that allowed you to use AuthBy FILE syntax in-line  
> with the actual configuration file, only because it seems silly for  
> me to have to use a separate two-line file with a single DEFAULT  
> user to smooth over the issue with the Dell switches:
>
> (hypothetical example, RADIUS.CFG)
> ----------------------------------
>
> <AuthBy INLINE>
> 	DEFAULT	cisco-avpair = "shell:priv-lvl=1", Auth-Type = Ignore
> 			Service-Type = Administrative-User
> </AuthBy>
>
> Are there other options open to me that I have overlooked?
>
> Thanks for your time, everyone!
>
> -- 
> Nathan Anderson
> First Step Internet, LLC
> nathana at fsr.com
> _______________________________________________
> radiator mailing list
> radiator at open.com.au
> http://www.open.com.au/mailman/listinfo/radiator



NB:

Have you read the reference manual ("doc/ref.html")?
Have you searched the mailing list archive (www.open.com.au/archives/radiator 
)?
Have you had a quick look on Google (www.google.com)?
Have you included a copy of your configuration file (no secrets),
together with a trace 4 debug showing what is happening?
Have you checked the RadiusExpert wiki:
http://www.open.com.au/wiki/index.php/Main_Page

-- 
Radiator: the most portable, flexible and configurable RADIUS server
anywhere. Available on *NIX, *BSD, Windows, MacOS X.
Includes support for reliable RADIUS transport (RadSec),
and DIAMETER translation agent.
-
Nets: internetwork inventory and management - graphical, extensible,
flexible with hardware, software, platform and database independence.
-
CATool: Private Certificate Authority for Unix and Unix-like systems.




More information about the radiator mailing list