#include "t_daemon.h"
#define ACCEPT_PACKET 0
#define REJECT_PACKET 1
static krad_packet *packets[3];
static const krad_packet *
iterator(void *data, krb5_boolean cancel)
{
krad_packet *tmp;
int *i = data;
if (cancel || packets[*i] == NULL)
return NULL;
tmp = packets[*i];
*i += 1;
return tmp;
}
static krb5_error_code
make_packet(krb5_context ctx, const krb5_data *username,
const krb5_data *password, krad_packet **pkt)
{
krad_attrset *set = NULL;
krad_packet *tmp = NULL;
krb5_error_code retval;
const krb5_data *data;
int i = 0;
krb5_data nas_id;
nas_id = string2data("12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
"123");
retval = krad_attrset_new(ctx, &set);
if (retval != 0)
goto out;
retval = krad_attrset_add(set, KRAD_ATTR_USER_NAME, username);
if (retval != 0)
goto out;
retval = krad_attrset_add(set, KRAD_ATTR_USER_PASSWORD,
password);
if (retval != 0)
goto out;
retval = krad_attrset_add(set, KRAD_ATTR_NAS_IDENTIFIER, &nas_id);
if (retval != 0)
goto out;
retval = krad_packet_new_request(ctx, "foo", KRAD_CODE_ACCESS_REQUEST,
set, iterator, &i, &tmp);
if (retval != 0)
goto out;
data = krad_packet_get_attr(tmp, KRAD_ATTR_USER_NAME, 0);
if (data == NULL) {
retval = ENOENT;
goto out;
}
if (data->length != username->length ||
memcmp(data->data, username->data, data->length) != 0) {
retval = EINVAL;
goto out;
}
*pkt = tmp;
tmp = NULL;
out:
krad_attrset_free(set);
krad_packet_free(tmp);
return retval;
}
static krb5_error_code
do_auth(krb5_context ctx, struct addrinfo *ai, const char *secret,
const krad_packet *rqst, krb5_boolean *auth)
{
const krad_packet *req = NULL;
char tmp[KRAD_PACKET_SIZE_MAX];
const krb5_data *request;
krad_packet *rsp = NULL;
krb5_error_code retval;
krb5_data response;
int sock = -1, i;
response = make_data(tmp, sizeof(tmp));
sock = socket(ai->ai_family, ai->ai_socktype, 0);
if (sock < 0) {
retval = errno;
goto out;
}
request = krad_packet_encode(rqst);
if (sendto(sock, request->data, request->length, 0, ai->ai_addr,
ai->ai_addrlen) < 0) {
retval = errno;
goto out;
}
i = recv(sock, response.data, sizeof(tmp), 0);
if (i < 0) {
retval = errno;
goto out;
}
response.length = i;
i = 0;
retval = krad_packet_decode_response(ctx, secret, &response, iterator, &i,
&req, &rsp);
if (retval != 0)
goto out;
if (req != rqst) {
retval = EBADMSG;
goto out;
}
*auth = krad_packet_get_code(rsp) == KRAD_CODE_ACCESS_ACCEPT;
out:
krad_packet_free(rsp);
if (sock >= 0)
close(sock);
return retval;
}
int
main(int argc, const char **argv)
{
struct addrinfo *ai = NULL, hints;
krb5_data username, password;
krb5_boolean auth = FALSE;
krb5_context ctx;
const krad_packet *dupreq;
const krb5_data *encpkt;
krad_packet *decreq;
username = string2data("testUser");
if (!daemon_start(argc, argv)) {
fprintf(stderr, "Unable to start pyrad daemon, skipping test...\n");
return 0;
}
noerror(krb5_init_context(&ctx));
password = string2data("accept");
noerror(make_packet(ctx, &username, &password, &packets[ACCEPT_PACKET]));
encpkt = krad_packet_encode(packets[ACCEPT_PACKET]);
noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
&dupreq, &decreq));
krad_packet_free(decreq);
password = string2data("reject");
noerror(make_packet(ctx, &username, &password, &packets[REJECT_PACKET]));
encpkt = krad_packet_encode(packets[REJECT_PACKET]);
noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
&dupreq, &decreq));
krad_packet_free(decreq);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
noerror(gai_error_code(getaddrinfo("127.0.0.1", "radius", &hints, &ai)));
noerror(do_auth(ctx, ai, "foo", packets[ACCEPT_PACKET], &auth));
insist(auth == TRUE);
noerror(do_auth(ctx, ai, "foo", packets[REJECT_PACKET], &auth));
insist(auth == FALSE);
krad_packet_free(packets[ACCEPT_PACKET]);
krad_packet_free(packets[REJECT_PACKET]);
krb5_free_context(ctx);
freeaddrinfo(ai);
return 0;
}