Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
simplesamlphp
Manage
Activity
Members
Labels
Plan
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
Perun
Perun ProxyIdP
v1
simplesamlphp
Commits
a89fcd1d
Commit
a89fcd1d
authored
9 years ago
by
Jaime Pérez Crespo
Browse files
Options
Downloads
Plain Diff
Merge pull request #340 from thijskh/radius
Several updates to the Radius module
parents
83a5a2b4
16d0bb79
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
modules/radius/docs/radius.txt
+13
-4
13 additions, 4 deletions
modules/radius/docs/radius.txt
modules/radius/lib/Auth/Source/Radius.php
+226
-205
226 additions, 205 deletions
modules/radius/lib/Auth/Source/Radius.php
with
239 additions
and
209 deletions
modules/radius/docs/radius.txt
+
13
−
4
View file @
a89fcd1d
...
...
@@ -39,9 +39,9 @@ authentication source which uses the `radius:Radius` module to
/*
* The number of times we should retry connections to the RADIUS server.
* Please note that retries would be attempted with each server before
* trying with the next server in the queue, so if you want not to wait
* before trying the next server, retries should be set to 1.
* Please note that retries would be attempted with each server before
* trying with the next server in the queue, so if you want not to wait
* before trying the next server, retries should be set to 1.
* Optional, defaults to 3 attempts.
*/
'retries' => 3,
...
...
@@ -52,6 +52,15 @@ authentication source which uses the `radius:Radius` module to
*/
'nas_identifier' => 'client.example.org',
/*
* An optional realm that will be suffixed to the username entered
* by the user. When set to "example.edu", and the user enters
* "bob" as their username, the radius server will be queried for
* the username "bob@example.edu".
* Optional, defaults to NULL.
*/
'realm' => 'example.edu',
/*
* The attribute name we should store the username in. Ths username
* will not be saved in any attribute if this is NULL.
...
...
@@ -71,7 +80,7 @@ from the RADIUS server.
The code expects one vendor-attribute with a specific vendor and a specific
vendor attribute type for each user attribute. The vendor-attribute must
contain a value o
n
the form
<name>=<value>
.
contain a value o
f
the form
`<name>=<value>`
.
The following configuration options are available for user attributes:
...
...
This diff is collapsed.
Click to expand it.
modules/radius/lib/Auth/Source/Radius.php
+
226
−
205
View file @
a89fcd1d
...
...
@@ -7,209 +7,230 @@
*
* @package SimpleSAMLphp
*/
class
sspmod_radius_Auth_Source_Radius
extends
sspmod_core_Auth_UserPassBase
{
/**
* The list of radius servers to use.
*/
private
$servers
;
/**
* The hostname of the radius server.
*/
private
$hostname
;
/**
* The port of the radius server.
*/
private
$port
;
/**
* The secret used when communicating with the radius server.
*/
private
$secret
;
/**
* The timeout for contacting the radius server.
*/
private
$timeout
;
/**
* The number of retries which should be attempted.
*/
private
$retries
;
/**
* The attribute name where the username should be stored.
*/
private
$usernameAttribute
;
/**
* The vendor for the RADIUS attributes we are interrested in.
*/
private
$vendor
;
/**
* The vendor-specific attribute for the RADIUS attributes we are interrested in.
*/
private
$vendorType
;
/**
* The NAS-Identifier that should be set in Access-Request packets.
*/
private
$nasIdentifier
;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public
function
__construct
(
$info
,
$config
)
{
assert
(
'is_array($info)'
);
assert
(
'is_array($config)'
);
// Call the parent constructor first, as required by the interface
parent
::
__construct
(
$info
,
$config
);
// Parse configuration.
$config
=
SimpleSAML_Configuration
::
loadFromArray
(
$config
,
'Authentication source '
.
var_export
(
$this
->
authId
,
TRUE
));
$this
->
servers
=
$config
->
getArray
(
'servers'
,
array
());
/* For backwards compatibility. */
if
(
empty
(
$this
->
servers
))
{
$this
->
hostname
=
$config
->
getString
(
'hostname'
);
$this
->
port
=
$config
->
getIntegerRange
(
'port'
,
1
,
65535
,
1812
);
$this
->
secret
=
$config
->
getString
(
'secret'
);
$this
->
servers
[]
=
array
(
'hostname'
=>
$this
->
hostname
,
'port'
=>
$this
->
port
,
'secret'
=>
$this
->
secret
);
}
$this
->
timeout
=
$config
->
getInteger
(
'timeout'
,
5
);
$this
->
retries
=
$config
->
getInteger
(
'retries'
,
3
);
$this
->
usernameAttribute
=
$config
->
getString
(
'username_attribute'
,
NULL
);
$this
->
nasIdentifier
=
$config
->
getString
(
'nas_identifier'
,
isset
(
$_SERVER
[
'HTTP_HOST'
])
?
$_SERVER
[
'HTTP_HOST'
]
:
'localhost'
);
$this
->
vendor
=
$config
->
getInteger
(
'attribute_vendor'
,
NULL
);
if
(
$this
->
vendor
!==
NULL
)
{
$this
->
vendorType
=
$config
->
getInteger
(
'attribute_vendor_type'
);
}
}
/**
* Attempt to log in using the given username and password.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
* @return array Associative array with the users attributes.
*/
protected
function
login
(
$username
,
$password
)
{
assert
(
'is_string($username)'
);
assert
(
'is_string($password)'
);
$radius
=
radius_auth_open
();
/* Try to add all radius servers, trigger a failure if no one works. */
$success
=
false
;
foreach
(
$this
->
servers
as
$server
)
{
if
(
!
isset
(
$server
[
'port'
]))
{
$server
[
'port'
]
=
1812
;
}
if
(
!
radius_add_server
(
$radius
,
$server
[
'hostname'
],
$server
[
'port'
],
$server
[
'secret'
],
$this
->
timeout
,
$this
->
retries
))
{
SimpleSAML_Logger
::
info
(
"Could not connect to server: "
.
radius_strerror
(
$radius
));
continue
;
}
$success
=
true
;
}
if
(
!
$success
)
{
throw
new
Exception
(
'Error connecting to radius server, no servers available'
);
}
if
(
!
radius_create_request
(
$radius
,
RADIUS_ACCESS_REQUEST
))
{
throw
new
Exception
(
'Error creating radius request: '
.
radius_strerror
(
$radius
));
}
radius_put_attr
(
$radius
,
RADIUS_USER_NAME
,
$username
);
radius_put_attr
(
$radius
,
RADIUS_USER_PASSWORD
,
$password
);
if
(
$this
->
nasIdentifier
!=
NULL
)
radius_put_attr
(
$radius
,
RADIUS_NAS_IDENTIFIER
,
$this
->
nasIdentifier
);
$res
=
radius_send_request
(
$radius
);
if
(
$res
!=
RADIUS_ACCESS_ACCEPT
)
{
switch
(
$res
)
{
case
RADIUS_ACCESS_REJECT
:
/* Invalid username or password. */
throw
new
SimpleSAML_Error_Error
(
'WRONGUSERPASS'
);
case
RADIUS_ACCESS_CHALLENGE
:
throw
new
Exception
(
'Radius authentication error: Challenge requested, but not supported.'
);
default
:
throw
new
Exception
(
'Error during radius authentication: '
.
radius_strerror
(
$radius
));
}
}
/* If we get this far, we have a valid login. */
$attributes
=
array
();
if
(
$this
->
usernameAttribute
!==
NULL
)
{
$attributes
[
$this
->
usernameAttribute
]
=
array
(
$username
);
}
if
(
$this
->
vendor
===
NULL
)
{
/*
* We aren't interested in any vendor-specific attributes. We are
* therefore done now.
*/
return
$attributes
;
}
/* get AAI attribute sets. Contributed by Stefan Winter, (c) RESTENA */
while
(
$resa
=
radius_get_attr
(
$radius
))
{
if
(
!
is_array
(
$resa
))
{
throw
new
Exception
(
'Error getting radius attributes: '
.
radius_strerror
(
$radius
));
}
/* Use the received user name */
if
(
$resa
[
'attr'
]
==
RADIUS_USER_NAME
)
{
$attributes
[
$this
->
usernameAttribute
]
=
array
(
$resa
[
'data'
]);
continue
;
}
if
(
$resa
[
'attr'
]
!==
RADIUS_VENDOR_SPECIFIC
)
{
continue
;
}
$resv
=
radius_get_vendor_attr
(
$resa
[
'data'
]);
if
(
!
is_array
(
$resv
))
{
throw
new
Exception
(
'Error getting vendor specific attribute: '
.
radius_strerror
(
$radius
));
}
$vendor
=
$resv
[
'vendor'
];
$attrv
=
$resv
[
'attr'
];
$datav
=
$resv
[
'data'
];
if
(
$vendor
!=
$this
->
vendor
||
$attrv
!=
$this
->
vendorType
)
{
continue
;
}
$attrib_name
=
strtok
(
$datav
,
'='
);
$attrib_value
=
strtok
(
'='
);
/* if the attribute name is already in result set, add another value */
if
(
array_key_exists
(
$attrib_name
,
$attributes
))
{
$attributes
[
$attrib_name
][]
=
$attrib_value
;
}
else
{
$attributes
[
$attrib_name
]
=
array
(
$attrib_value
);
}
}
/* end of contribution */
return
$attributes
;
}
class
sspmod_radius_Auth_Source_Radius
extends
sspmod_core_Auth_UserPassBase
{
/**
* The list of radius servers to use.
*/
private
$servers
;
/**
* The hostname of the radius server.
*/
private
$hostname
;
/**
* The port of the radius server.
*/
private
$port
;
/**
* The secret used when communicating with the radius server.
*/
private
$secret
;
/**
* The timeout for contacting the radius server.
*/
private
$timeout
;
/**
* The number of retries which should be attempted.
*/
private
$retries
;
/**
* The realm to be added to the entered username.
*/
private
$realm
;
/**
* The attribute name where the username should be stored.
*/
private
$usernameAttribute
;
/**
* The vendor for the RADIUS attributes we are interrested in.
*/
private
$vendor
;
/**
* The vendor-specific attribute for the RADIUS attributes we are
* interrested in.
*/
private
$vendorType
;
/**
* The NAS-Identifier that should be set in Access-Request packets.
*/
private
$nasIdentifier
;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public
function
__construct
(
$info
,
$config
)
{
assert
(
'is_array($info)'
);
assert
(
'is_array($config)'
);
// Call the parent constructor first, as required by the interface
parent
::
__construct
(
$info
,
$config
);
// Parse configuration.
$config
=
SimpleSAML_Configuration
::
loadFromArray
(
$config
,
'Authentication source '
.
var_export
(
$this
->
authId
,
true
));
$this
->
servers
=
$config
->
getArray
(
'servers'
,
array
());
/* For backwards compatibility. */
if
(
empty
(
$this
->
servers
))
{
$this
->
hostname
=
$config
->
getString
(
'hostname'
);
$this
->
port
=
$config
->
getIntegerRange
(
'port'
,
1
,
65535
,
1812
);
$this
->
secret
=
$config
->
getString
(
'secret'
);
$this
->
servers
[]
=
array
(
'hostname'
=>
$this
->
hostname
,
'port'
=>
$this
->
port
,
'secret'
=>
$this
->
secret
);
}
$this
->
timeout
=
$config
->
getInteger
(
'timeout'
,
5
);
$this
->
retries
=
$config
->
getInteger
(
'retries'
,
3
);
$this
->
realm
=
$config
->
getString
(
'realm'
,
null
);
$this
->
usernameAttribute
=
$config
->
getString
(
'username_attribute'
,
null
);
$this
->
nasIdentifier
=
$config
->
getString
(
'nas_identifier'
,
isset
(
$_SERVER
[
'HTTP_HOST'
])
?
$_SERVER
[
'HTTP_HOST'
]
:
'localhost'
);
$this
->
vendor
=
$config
->
getInteger
(
'attribute_vendor'
,
null
);
if
(
$this
->
vendor
!==
null
)
{
$this
->
vendorType
=
$config
->
getInteger
(
'attribute_vendor_type'
);
}
}
/**
* Attempt to log in using the given username and password.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
* @return array Associative array with the user's attributes.
*/
protected
function
login
(
$username
,
$password
)
{
assert
(
'is_string($username)'
);
assert
(
'is_string($password)'
);
$radius
=
radius_auth_open
();
/* Try to add all radius servers, trigger a failure if no one works. */
$success
=
false
;
foreach
(
$this
->
servers
as
$server
)
{
if
(
!
isset
(
$server
[
'port'
]))
{
$server
[
'port'
]
=
1812
;
}
if
(
!
radius_add_server
(
$radius
,
$server
[
'hostname'
],
$server
[
'port'
],
$server
[
'secret'
],
$this
->
timeout
,
$this
->
retries
))
{
SimpleSAML_Logger
::
info
(
"Could not add radius server: "
.
radius_strerror
(
$radius
));
continue
;
}
$success
=
true
;
}
if
(
!
$success
)
{
throw
new
Exception
(
'Error adding radius servers, no servers available'
);
}
if
(
!
radius_create_request
(
$radius
,
RADIUS_ACCESS_REQUEST
))
{
throw
new
Exception
(
'Error creating radius request: '
.
radius_strerror
(
$radius
));
}
if
(
$this
->
realm
===
null
)
{
radius_put_attr
(
$radius
,
RADIUS_USER_NAME
,
$username
);
}
else
{
radius_put_attr
(
$radius
,
RADIUS_USER_NAME
,
$username
.
'@'
.
$this
->
realm
);
}
radius_put_attr
(
$radius
,
RADIUS_USER_PASSWORD
,
$password
);
if
(
$this
->
nasIdentifier
!==
null
)
{
radius_put_attr
(
$radius
,
RADIUS_NAS_IDENTIFIER
,
$this
->
nasIdentifier
);
}
$res
=
radius_send_request
(
$radius
);
if
(
$res
!=
RADIUS_ACCESS_ACCEPT
)
{
switch
(
$res
)
{
case
RADIUS_ACCESS_REJECT
:
/* Invalid username or password. */
throw
new
SimpleSAML_Error_Error
(
'WRONGUSERPASS'
);
case
RADIUS_ACCESS_CHALLENGE
:
throw
new
Exception
(
'Radius authentication error: Challenge requested, but not supported.'
);
default
:
throw
new
Exception
(
'Error during radius authentication: '
.
radius_strerror
(
$radius
));
}
}
/* If we get this far, we have a valid login. */
$attributes
=
array
();
if
(
$this
->
usernameAttribute
!==
null
)
{
$attributes
[
$this
->
usernameAttribute
]
=
array
(
$username
);
}
if
(
$this
->
vendor
===
null
)
{
/*
* We aren't interested in any vendor-specific attributes. We are
* therefore done now.
*/
return
$attributes
;
}
/* get AAI attribute sets. Contributed by Stefan Winter, (c) RESTENA */
while
(
$resa
=
radius_get_attr
(
$radius
))
{
if
(
!
is_array
(
$resa
))
{
throw
new
Exception
(
'Error getting radius attributes: '
.
radius_strerror
(
$radius
));
}
/* Use the received user name */
if
(
$resa
[
'attr'
]
==
RADIUS_USER_NAME
)
{
$attributes
[
$this
->
usernameAttribute
]
=
array
(
$resa
[
'data'
]);
continue
;
}
if
(
$resa
[
'attr'
]
!==
RADIUS_VENDOR_SPECIFIC
)
{
continue
;
}
$resv
=
radius_get_vendor_attr
(
$resa
[
'data'
]);
if
(
!
is_array
(
$resv
))
{
throw
new
Exception
(
'Error getting vendor specific attribute: '
.
radius_strerror
(
$radius
));
}
$vendor
=
$resv
[
'vendor'
];
$attrv
=
$resv
[
'attr'
];
$datav
=
$resv
[
'data'
];
if
(
$vendor
!=
$this
->
vendor
||
$attrv
!=
$this
->
vendorType
)
{
continue
;
}
$attrib_name
=
strtok
(
$datav
,
'='
);
$attrib_value
=
strtok
(
'='
);
/* if the attribute name is already in result set,
add another value */
if
(
array_key_exists
(
$attrib_name
,
$attributes
))
{
$attributes
[
$attrib_name
][]
=
$attrib_value
;
}
else
{
$attributes
[
$attrib_name
]
=
array
(
$attrib_value
);
}
}
/* end of contribution */
return
$attributes
;
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment