Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
Node Radius Server
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
Node Radius Server
Commits
97ea3fad
Commit
97ea3fad
authored
Jun 25, 2020
by
simon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(eap): catch decoding errors
parent
6fc7301c
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
204 additions
and
185 deletions
+204
-185
src/radius/handler/EAPPacketHandler.ts
src/radius/handler/EAPPacketHandler.ts
+89
-84
src/radius/handler/eap/eapMethods/EAP-GTC.ts
src/radius/handler/eap/eapMethods/EAP-GTC.ts
+19
-12
src/radius/handler/eap/eapMethods/EAP-TTLS.ts
src/radius/handler/eap/eapMethods/EAP-TTLS.ts
+96
-89
No files found.
src/radius/handler/EAPPacketHandler.ts
View file @
97ea3fad
...
...
@@ -3,7 +3,7 @@
import
*
as
NodeCache
from
'
node-cache
'
;
import
debug
from
'
debug
'
;
import
{
makeid
}
from
'
../../helpers
'
;
import
{
IPacket
,
IPacketHandler
,
IPacketHandlerResult
}
from
'
../../types/PacketHandler
'
;
import
{
IPacket
,
IPacketHandler
,
IPacketHandlerResult
,
PacketResponseCode
}
from
'
../../types/PacketHandler
'
;
import
{
IEAPMethod
}
from
'
../../types/EAPMethod
'
;
import
{
buildEAPResponse
,
decodeEAPHeader
}
from
'
./eap/EAPHelper
'
;
...
...
@@ -34,99 +34,104 @@ export class EAPPacketHandler implements IPacketHandler {
// EAP MESSAGE
const
msg
=
packet
.
attributes
[
'
EAP-Message
'
]
as
Buffer
;
const
{
code
,
type
,
identifier
,
data
}
=
decodeEAPHeader
(
msg
);
const
currentState
=
this
.
eapConnectionStates
.
get
(
stateID
)
as
{
validMethods
:
IEAPMethod
[]
};
switch
(
code
)
{
case
1
:
// for request
case
2
:
// for response
switch
(
type
)
{
case
1
:
// identifiy
log
(
'
>>>>>>>>>>>> REQUEST FROM CLIENT: IDENTIFY
'
,
stateID
,
data
.
toString
());
if
(
data
)
{
this
.
identities
.
set
(
stateID
,
data
);
// use token til binary 0.);
}
else
{
log
(
'
no msg
'
);
}
// start identify
if
(
currentState
.
validMethods
.
length
>
0
)
{
return
currentState
.
validMethods
[
0
].
identify
(
identifier
,
stateID
,
data
);
}
return
buildEAPResponse
(
identifier
,
3
);
// NAK
case
2
:
// notification
log
(
'
>>>>>>>>>>>> REQUEST FROM CLIENT: notification
'
,
{});
console
.
info
(
'
notification
'
);
break
;
case
4
:
// md5-challenge
log
(
'
>>>>>>>>>>>> REQUEST FROM CLIENT: md5-challenge
'
,
{});
console
.
info
(
'
md5-challenge
'
);
break
;
case
254
:
// expanded type
console
.
error
(
'
not implemented type
'
,
type
);
break
;
case
3
:
// nak
// console.log('got NAK', data);
if
(
data
)
{
// if there is data, each data octect reprsents a eap method the clients supports,
// kick out all unsupported ones
const
supportedEAPMethods
:
number
[]
=
[];
for
(
const
supportedMethod
of
data
)
{
supportedEAPMethods
.
push
(
supportedMethod
);
try
{
const
{
code
,
type
,
identifier
,
data
}
=
decodeEAPHeader
(
msg
);
const
currentState
=
this
.
eapConnectionStates
.
get
(
stateID
)
as
{
validMethods
:
IEAPMethod
[]
};
switch
(
code
)
{
case
1
:
// for request
case
2
:
// for response
switch
(
type
)
{
case
1
:
// identifiy
log
(
'
>>>>>>>>>>>> REQUEST FROM CLIENT: IDENTIFY
'
,
stateID
,
data
.
toString
());
if
(
data
)
{
this
.
identities
.
set
(
stateID
,
data
);
// use token til binary 0.);
}
else
{
log
(
'
no msg
'
);
}
currentState
.
validMethods
=
currentState
.
validMethods
.
filter
((
method
)
=>
{
return
supportedEAPMethods
.
includes
(
method
.
getEAPType
());
// kick it out?
});
// save
this
.
eapConnectionStates
.
set
(
stateID
,
currentState
);
// new identidy request
// start identify
if
(
currentState
.
validMethods
.
length
>
0
)
{
return
currentState
.
validMethods
[
0
].
identify
(
identifier
,
stateID
,
data
);
}
}
// continue with responding a NAK and add rest of supported methods
// eslint-disable-next-line no-fallthrough
default
:
{
const
eapMethod
=
this
.
eapMethods
.
find
((
method
)
=>
{
return
type
===
method
.
getEAPType
();
});
if
(
eapMethod
)
{
return
eapMethod
.
handleMessage
(
identifier
,
stateID
,
msg
,
packet
,
this
.
identities
.
get
(
stateID
)
);
}
// we do not support this auth type, ask for something we support
const
serverSupportedMethods
=
currentState
.
validMethods
.
map
((
method
)
=>
method
.
getEAPType
()
);
return
buildEAPResponse
(
identifier
,
3
);
// NAK
case
2
:
// notification
log
(
'
>>>>>>>>>>>> REQUEST FROM CLIENT: notification
'
,
{});
console
.
info
(
'
notification
'
);
break
;
case
4
:
// md5-challenge
log
(
'
>>>>>>>>>>>> REQUEST FROM CLIENT: md5-challenge
'
,
{});
console
.
info
(
'
md5-challenge
'
);
break
;
case
254
:
// expanded type
console
.
error
(
'
not implemented type
'
,
type
);
break
;
case
3
:
// nak
// console.log('got NAK', data);
if
(
data
)
{
// if there is data, each data octect reprsents a eap method the clients supports,
// kick out all unsupported ones
const
supportedEAPMethods
:
number
[]
=
[];
for
(
const
supportedMethod
of
data
)
{
supportedEAPMethods
.
push
(
supportedMethod
);
}
currentState
.
validMethods
=
currentState
.
validMethods
.
filter
((
method
)
=>
{
return
supportedEAPMethods
.
includes
(
method
.
getEAPType
());
// kick it out?
});
// save
this
.
eapConnectionStates
.
set
(
stateID
,
currentState
);
// new identidy request
// start identify
if
(
currentState
.
validMethods
.
length
>
0
)
{
return
currentState
.
validMethods
[
0
].
identify
(
identifier
,
stateID
,
data
);
}
}
// continue with responding a NAK and add rest of supported methods
// eslint-disable-next-line no-fallthrough
default
:
{
const
eapMethod
=
this
.
eapMethods
.
find
((
method
)
=>
{
return
type
===
method
.
getEAPType
();
});
if
(
eapMethod
)
{
return
eapMethod
.
handleMessage
(
identifier
,
stateID
,
msg
,
packet
,
this
.
identities
.
get
(
stateID
)
);
}
// we do not support this auth type, ask for something we support
const
serverSupportedMethods
=
currentState
.
validMethods
.
map
((
method
)
=>
method
.
getEAPType
()
);
console
.
error
(
'
unsupported type
'
,
type
,
`requesting:
${
serverSupportedMethods
}
`
);
console
.
error
(
'
unsupported type
'
,
type
,
`requesting:
${
serverSupportedMethods
}
`
);
return
buildEAPResponse
(
identifier
,
3
,
Buffer
.
from
(
serverSupportedMethods
));
return
buildEAPResponse
(
identifier
,
3
,
Buffer
.
from
(
serverSupportedMethods
));
}
}
}
break
;
case
3
:
log
(
'
Client Auth Success
'
);
break
;
case
4
:
log
(
'
Client Auth FAILURE
'
);
break
;
default
:
break
;
case
3
:
log
(
'
Client Auth Success
'
);
break
;
case
4
:
log
(
'
Client Auth FAILURE
'
);
break
;
default
:
}
// silently ignore;
return
{};
}
catch
(
err
)
{
console
.
error
(
'
decoding of (generic) EAP package failed
'
,
msg
,
err
);
return
{};
}
// silently ignore;
return
{};
}
}
src/radius/handler/eap/eapMethods/EAP-GTC.ts
View file @
97ea3fad
...
...
@@ -37,22 +37,29 @@ export class EAPGTC implements IEAPMethod {
):
Promise
<
IPacketHandlerResult
>
{
const
username
=
identity
;
// this.loginData.get(stateID) as Buffer | undefined;
const
{
data
}
=
decodeEAPHeader
(
msg
);
try
{
const
{
data
}
=
decodeEAPHeader
(
msg
);
const
token
=
this
.
extractValue
(
data
);
const
token
=
this
.
extractValue
(
data
);
if
(
!
username
)
{
throw
new
Error
(
'
no username
'
);
}
if
(
!
username
)
{
throw
new
Error
(
'
no username
'
);
}
log
(
'
username
'
,
username
,
username
.
toString
());
log
(
'
token
'
,
token
,
token
.
toString
());
log
(
'
username
'
,
username
,
username
.
toString
());
log
(
'
token
'
,
token
,
token
.
toString
());
const
success
=
await
this
.
authentication
.
authenticate
(
username
.
toString
(),
token
.
toString
());
const
success
=
await
this
.
authentication
.
authenticate
(
username
.
toString
(),
token
.
toString
());
return
{
code
:
success
?
PacketResponseCode
.
AccessAccept
:
PacketResponseCode
.
AccessReject
,
attributes
:
(
success
&&
[[
'
User-Name
'
,
username
]])
||
undefined
,
};
return
{
code
:
success
?
PacketResponseCode
.
AccessAccept
:
PacketResponseCode
.
AccessReject
,
attributes
:
(
success
&&
[[
'
User-Name
'
,
username
]])
||
undefined
,
};
}
catch
(
err
)
{
console
.
error
(
'
decoding of EAP-GTC package failed
'
,
msg
,
err
);
return
{
code
:
PacketResponseCode
.
AccessReject
,
};
}
}
}
src/radius/handler/eap/eapMethods/EAP-TTLS.ts
View file @
97ea3fad
...
...
@@ -300,113 +300,120 @@ export class EAPTTLS implements IEAPMethod {
return
{};
}
this
.
lastProcessedIdentifier
.
set
(
stateID
,
identifier
);
const
{
data
}
=
this
.
decodeTTLSMessage
(
msg
);
// check if no data package is there and we have something in the queue, if so.. empty the queue first
if
(
!
data
||
data
.
length
===
0
)
{
const
queuedData
=
this
.
queueData
.
get
(
stateID
);
if
(
queuedData
instanceof
Buffer
&&
queuedData
.
length
>
0
)
{
log
(
`returning queued data for
${
stateID
}
`
);
return
this
.
buildEAPTTLSResponse
(
identifier
,
21
,
0x00
,
stateID
,
queuedData
,
false
);
try
{
const
{
data
}
=
this
.
decodeTTLSMessage
(
msg
);
// check if no data package is there and we have something in the queue, if so.. empty the queue first
if
(
!
data
||
data
.
length
===
0
)
{
const
queuedData
=
this
.
queueData
.
get
(
stateID
);
if
(
queuedData
instanceof
Buffer
&&
queuedData
.
length
>
0
)
{
log
(
`returning queued data for
${
stateID
}
`
);
return
this
.
buildEAPTTLSResponse
(
identifier
,
21
,
0x00
,
stateID
,
queuedData
,
false
);
}
log
(
`empty data queue for
${
stateID
}
`
);
return
{};
}
log
(
`empty data queue for
${
stateID
}
`
);
return
{};
}
let
connection
=
this
.
openTLSSockets
.
get
(
stateID
)
as
ITLSServer
;
let
connection
=
this
.
openTLSSockets
.
get
(
stateID
)
as
ITLSServer
;
if
(
!
connection
)
{
connection
=
startTLSServer
();
this
.
openTLSSockets
.
set
(
stateID
,
connection
);
if
(
!
connection
)
{
connection
=
startTLSServer
();
this
.
openTLSSockets
.
set
(
stateID
,
connection
);
connection
.
events
.
on
(
'
end
'
,
()
=>
{
// cleanup socket
log
(
'
ENDING SOCKET
'
);
this
.
openTLSSockets
.
del
(
stateID
);
});
}
connection
.
events
.
on
(
'
end
'
,
()
=>
{
// cleanup socket
log
(
'
ENDING SOCKET
'
);
this
.
openTLSSockets
.
del
(
stateID
);
});
}
const
sendResponsePromise
=
newDeferredPromise
();
const
sendResponsePromise
=
newDeferredPromise
();
const
incomingMessageHandler
=
async
(
incomingData
:
Buffer
)
=>
{
const
ret
:
any
=
{};
ret
.
attributes
=
{};
ret
.
raw_attributes
=
[];
const
incomingMessageHandler
=
async
(
incomingData
:
Buffer
)
=>
{
const
ret
:
any
=
{};
ret
.
attributes
=
{};
ret
.
raw_attributes
=
[];
const
AVPs
=
this
.
decodeAVPs
(
incomingData
);
const
AVPs
=
this
.
decodeAVPs
(
incomingData
);
// build attributes for packet handler
const
attributes
:
IPacketAttributes
=
{};
AVPs
.
forEach
((
avp
)
=>
{
attributes
[
attr_id_to_name
(
avp
.
type
)]
=
avp
.
data
;
});
// build attributes for packet handler
const
attributes
:
IPacketAttributes
=
{};
AVPs
.
forEach
((
avp
)
=>
{
attributes
[
attr_id_to_name
(
avp
.
type
)]
=
avp
.
data
;
});
attributes
.
State
=
`
${
stateID
}
-inner`
;
attributes
.
State
=
`
${
stateID
}
-inner`
;
// handle incoming package via inner tunnel
const
result
=
await
this
.
innerTunnel
.
handlePacket
(
{
attributes
,
},
this
.
getEAPType
()
);
// handle incoming package via inner tunnel
const
result
=
await
this
.
innerTunnel
.
handlePacket
(
{
attributes
,
},
this
.
getEAPType
()
);
log
(
'
inner tunnel result
'
,
result
);
log
(
'
inner tunnel result
'
,
result
);
if
(
result
.
code
===
PacketResponseCode
.
AccessReject
||
result
.
code
===
PacketResponseCode
.
AccessAccept
)
{
sendResponsePromise
.
resolve
(
this
.
authResponse
(
identifier
,
result
.
code
===
PacketResponseCode
.
AccessAccept
,
connection
.
tls
,
{
...
packet
,
attributes
:
{
...
packet
.
attributes
,
...
this
.
transformAttributesArrayToMap
(
result
.
attributes
),
},
}
)
);
return
;
}
const
eapMessage
=
result
.
attributes
?.
find
((
attr
)
=>
attr
[
0
]
===
'
EAP-Message
'
);
if
(
!
eapMessage
)
{
throw
new
Error
(
'
no eap message found
'
);
}
connection
.
events
.
emit
(
'
encrypt
'
,
this
.
buildAVP
(
attr_name_to_id
(
'
EAP-Message
'
),
eapMessage
[
1
]
as
Buffer
)
);
};
if
(
result
.
code
===
PacketResponseCode
.
AccessReject
||
result
.
code
===
PacketResponseCode
.
AccessAccept
)
{
const
responseHandler
=
(
encryptedResponseData
:
Buffer
)
=>
{
// send back...
sendResponsePromise
.
resolve
(
this
.
authResponse
(
identifier
,
result
.
code
===
PacketResponseCode
.
AccessAccept
,
connection
.
tls
,
{
...
packet
,
attributes
:
{
...
packet
.
attributes
,
...
this
.
transformAttributesArrayToMap
(
result
.
attributes
),
},
}
)
this
.
buildEAPTTLSResponse
(
identifier
,
21
,
0x00
,
stateID
,
encryptedResponseData
)
);
return
;
}
const
eapMessage
=
result
.
attributes
?.
find
((
attr
)
=>
attr
[
0
]
===
'
EAP-Message
'
);
if
(
!
eapMessage
)
{
throw
new
Error
(
'
no eap message found
'
);
}
connection
.
events
.
emit
(
'
encrypt
'
,
this
.
buildAVP
(
attr_name_to_id
(
'
EAP-Message
'
),
eapMessage
[
1
]
as
Buffer
)
);
};
const
responseHandler
=
(
encryptedResponseData
:
Buffer
)
=>
{
// send back...
sendResponsePromise
.
resolve
(
this
.
buildEAPTTLSResponse
(
identifier
,
21
,
0x00
,
stateID
,
encryptedResponseData
)
);
};
};
// register event listeners
connection
.
events
.
on
(
'
incoming
'
,
incomingMessageHandler
);
connection
.
events
.
on
(
'
response
'
,
responseHandler
);
// register event listeners
connection
.
events
.
on
(
'
incoming
'
,
incomingMessageHandler
);
connection
.
events
.
on
(
'
response
'
,
responseHandler
);
// emit data to tls server
connection
.
events
.
emit
(
'
decrypt
'
,
data
);
const
responseData
=
await
sendResponsePromise
.
promise
;
// emit data to tls server
connection
.
events
.
emit
(
'
decrypt
'
,
data
);
const
responseData
=
await
sendResponsePromise
.
promise
;
// cleanup
connection
.
events
.
off
(
'
incoming
'
,
incomingMessageHandler
);
connection
.
events
.
off
(
'
response
'
,
responseHandler
);
// cleanup
connection
.
events
.
off
(
'
incoming
'
,
incomingMessageHandler
);
connection
.
events
.
off
(
'
response
'
,
responseHandler
);
// send response
return
responseData
;
// this.buildEAPTTLSResponse(identifier, 21, 0x00, stateID, encryptedResponseData);
// send response
return
responseData
;
// this.buildEAPTTLSResponse(identifier, 21, 0x00, stateID, encryptedResponseData);
}
catch
(
err
)
{
console
.
error
(
'
decoding of EAP-TTLS package failed
'
,
msg
,
err
);
return
{
code
:
PacketResponseCode
.
AccessReject
,
};
}
}
private
transformAttributesArrayToMap
(
attributes
:
[
string
,
Buffer
|
string
][]
|
undefined
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment