Radius Protocol - 如何在第二个请求中正确设置状态?

时间:2017-09-29 08:46:01

标签: java windows-server-2012 radius tinyradius

我使用TinyRadius将我的Java WebServer(作为Radius客户端)验证到Windows Server(作为Radius服务器)。

我成功将用户Access-Request发送到服务器并收回了密码。

final RadiusClient client = new RadiusClient(
    new RadiusEndpoint(
        new InetSocketAddress(RADIUS_SERVER_ADDRESS, PORT),
        SHARED_SECRET
    )
);

final AccessRequest request = new AccessRequest(
    USERNAME,
    USER_PASS
);

request.setAuthProtocol(AccessRequest.AUTH_PAP);
request.addAttribute("NAS-IP-Address", RADIUS_CLIENT_ADDRESS);

RadiusPacket packet = null;

try {
    packet = client.authenticate(request);
} catch (final RadiusException | IOException ex) {
    System.out.println(ex.getMessage());
    ex.printStackTrace();
} 

此代码后跟一个日志,该日志表明服务器已批准用户身份验证。

Sep 29, 2017 10:05:32 AM org.tinyradius.util.RadiusClient authenticate
INFO: send Access-Request packet: Access-Request, ID 1
User-Name: mp
NAS-IP-Address: 192.168.0.58
Sep 29, 2017 10:05:33 AM org.tinyradius.util.RadiusClient authenticate
INFO: received packet: Access-Challenge, ID 1
State: 0x7b41324244344539362d453139332d344539392d413134322d4134423536364441443938437d
Reply-Message: Enter PASSCODE

我的Windows Server上的事件查看器也声明接受了访问请求。

事实上,我正确地在我的移动应用程序上收到了密码(我在使用截至观察点的短信密码时,这是无关紧要的。)

不幸的是,我在网上找不到任何TinyRadius Passcode示例,但在浏览其他库时,我偶然发现了python library,其中指出:

  

ChallengeResponse例外messagesstate属性messages可以显示给用户以提示他们   挑战回应。 state必须作为RADIUS属性回显。

  

最后使用来自用户的质询响应再次进行身份验证   代替密码。

所以我所做的就是使用上面相同的代码。我把PASSCODE而不是USER_PASS,我将state属性添加到我的AccessRequest。

final RadiusAttribute stateAttr  = new RadiusAttribute(24, STATE.getBytes());
request.addAttribute(stateAttr);

我将请求发送到服务器,我可以看到此日志。

Sep 29, 2017 10:34:04 AM org.tinyradius.util.RadiusClient authenticate
INFO: send Access-Request packet: Access-Request, ID 1
User-Name: mp
NAS-IP-Address: 192.168.0.58
State: 0x307837623431343133353330333433363334333832643433333433343339326433343432343633303264343234343335343532643330343533323337343633383332333333373332333933373764
Sep 29, 2017 10:34:04 AM org.tinyradius.util.RadiusClient authenticate
INFO: received packet: Access-Reject, ID 1
Reply-Message: Session is unknown or has expired

Windows事件查看器声明:

Event description:
    Event type:         Authentication request
    Result:             Failure
    Failure reason:     Password validation failed

所以我在4.4节阅读了RFC 2865 Access-Challenge章节,他们说:

  

收到有效证件         Access-Challenge表示新的访问请求应该是         发送[...]   用户密码属性替换为         用户的响应(加密),包括状态属性         来自Access-Challenge,如果有的话。只有0或1个实例         状态属性可以存在于Access-Request中。

因此,我猜我做的一切都是正确的。愿有人帮我吗?

1 个答案:

答案 0 :(得分:2)

我将第二个请求发送到服务器的方式存在一些问题。

这样做不起作用,因为STATE.getBytes()返回了不同编码的String

final RadiusAttribute stateAttr  = new RadiusAttribute(24, STATE.getBytes()); // BAD
request.addAttribute(stateAttr);

我必须做的是:首先将响应存储到新的Packet

final AccessRequest request = new AccessRequest(
    USERNAME,
    USER_PASS
);
packet = client.authenticate(request);

然后,创建一个新的AccessRequest来回答挑战并按以下方式设置状态

final AccessRequest challengeResponseRequest = new AccessRequest(
            USER,
            PASSCODE
);

challengeResponseRequest.addAttribute(
    new RadiusAttribute(24, packet.getAttribute(24).getAttributeData()) // GOOD
);

(注意:24是attribute code for STATUS

发送较新的AccessRequest

client.authenticate(challengeResponseRequest);

日志确认身份验证成功:

Sep 29, 2017 2:05:13 PM org.tinyradius.util.RadiusClient authenticate
INFO: received packet: Access-Accept, ID 2
Class: 0x8f8007ad0000013700010200c0a800050000000024db5d173578383201d3379907bd2a500000000000000098