radius: send user agent information as Connect-Info

That allows the radius server to store information on particular
client. Resolves #26
This commit is contained in:
Nikos Mavrogiannopoulos
2016-01-16 23:00:11 +01:00
parent 8aa55db239
commit 6c6481de40
14 changed files with 63 additions and 35 deletions

View File

@@ -43,7 +43,7 @@ static int ocserv_conv(int msg_size, const struct pam_message **msg,
return PAM_SUCCESS;
}
static int pam_acct_open_session(unsigned auth_method, const struct common_auth_info_st *ai, const void *sid, unsigned sid_size)
static int pam_acct_open_session(unsigned auth_method, const struct common_acct_info_st *ai, const void *sid, unsigned sid_size)
{
int pret;
pam_handle_t *ph;
@@ -79,7 +79,7 @@ fail1:
}
static void pam_acct_close_session(unsigned auth_method, const struct common_auth_info_st *ai, stats_st *stats, unsigned status)
static void pam_acct_close_session(unsigned auth_method, const struct common_acct_info_st *ai, stats_st *stats, unsigned status)
{
return;
}

View File

@@ -115,7 +115,7 @@ static void append_stats(rc_handle *rh, VALUE_PAIR **send, stats_st *stats)
return;
}
static void append_acct_standard(rc_handle *rh, const common_auth_info_st *ai, VALUE_PAIR **send)
static void append_acct_standard(rc_handle *rh, const common_acct_info_st *ai, VALUE_PAIR **send)
{
uint32_t i;
@@ -188,7 +188,7 @@ static void append_acct_standard(rc_handle *rh, const common_auth_info_st *ai, V
return;
}
static void radius_acct_session_stats(unsigned auth_method, const common_auth_info_st *ai, stats_st *stats)
static void radius_acct_session_stats(unsigned auth_method, const common_acct_info_st *ai, stats_st *stats)
{
int ret;
uint32_t status_type;
@@ -221,7 +221,7 @@ VALUE_PAIR *send = NULL, *recvd = NULL;
return;
}
static int radius_acct_open_session(unsigned auth_method, const common_auth_info_st *ai, const void *sid, unsigned sid_size)
static int radius_acct_open_session(unsigned auth_method, const common_acct_info_st *ai, const void *sid, unsigned sid_size)
{
int ret;
uint32_t status_type;
@@ -260,7 +260,7 @@ VALUE_PAIR *send = NULL, *recvd = NULL;
return ret;
}
static void radius_acct_close_session(unsigned auth_method, const common_auth_info_st *ai, stats_st *stats, unsigned discon_reason)
static void radius_acct_close_session(unsigned auth_method, const common_acct_info_st *ai, stats_st *stats, unsigned discon_reason)
{
int ret;
uint32_t status_type;

View File

@@ -209,7 +209,7 @@ static int verify_krb5_constraints(struct gssapi_ctx_st *pctx, gss_OID mech_type
return 0;
}
static int gssapi_auth_init(void **ctx, void *pool, const char *spnego, const char *ip, const char *our_ip, unsigned pid)
static int gssapi_auth_init(void **ctx, void *pool, const common_auth_init_st *info)
{
struct gssapi_ctx_st *pctx;
OM_uint32 minor, flags, time;
@@ -219,6 +219,7 @@ static int gssapi_auth_init(void **ctx, void *pool, const char *spnego, const ch
int ret;
size_t raw_len;
char *raw;
const char *spnego = info->username;
if (spnego == NULL || spnego[0] == 0) {
syslog(LOG_ERR, "gssapi: error in spnego data %s", __func__);

View File

@@ -150,12 +150,12 @@ wait:
}
}
static int pam_auth_init(void** ctx, void *pool, const char* user, const char* ip, const char *our_ip, unsigned pid)
static int pam_auth_init(void** ctx, void *pool, const common_auth_init_st *info)
{
int pret;
struct pam_ctx_st * pctx;
if (user == NULL || user[0] == 0) {
if (info->username == NULL || info->username[0] == 0) {
syslog(LOG_AUTH,
"pam-auth: no username present");
return ERR_AUTH_FAIL;
@@ -169,7 +169,7 @@ struct pam_ctx_st * pctx;
pctx->dc.conv = ocserv_conv;
pctx->dc.appdata_ptr = pctx;
pret = pam_start(PACKAGE, user, &pctx->dc, &pctx->ph);
pret = pam_start(PACKAGE, info->username, &pctx->dc, &pctx->ph);
if (pret != PAM_SUCCESS) {
syslog(LOG_AUTH, "PAM-auth init: %s", pam_strerror(pctx->ph, pret));
goto fail1;
@@ -179,10 +179,10 @@ struct pam_ctx_st * pctx;
if (pctx->cr == NULL)
goto fail2;
strlcpy(pctx->username, user, sizeof(pctx->username));
strlcpy(pctx->username, info->username, sizeof(pctx->username));
if (ip != NULL)
pam_set_item(pctx->ph, PAM_RHOST, ip);
if (info->ip != NULL)
pam_set_item(pctx->ph, PAM_RHOST, info->ip);
*ctx = pctx;

View File

@@ -230,12 +230,12 @@ static int read_auth_pass(struct plain_ctx_st *pctx)
return ret;
}
static int plain_auth_init(void **ctx, void *pool, const char *username, const char *ip, const char *our_ip, unsigned pid)
static int plain_auth_init(void **ctx, void *pool, const common_auth_init_st *info)
{
struct plain_ctx_st *pctx;
int ret;
if (username == NULL || username[0] == 0) {
if (info->username == NULL || info->username[0] == 0) {
syslog(LOG_AUTH,
"plain-auth: no username present");
return ERR_AUTH_FAIL;
@@ -245,7 +245,7 @@ static int plain_auth_init(void **ctx, void *pool, const char *username, const c
if (pctx == NULL)
return ERR_AUTH_FAIL;
strlcpy(pctx->username, username, sizeof(pctx->username));
strlcpy(pctx->username, info->username, sizeof(pctx->username));
pctx->pass_msg = NULL; /* use default */
/* this doesn't fail on password mismatch but sets p->failed */

View File

@@ -91,12 +91,12 @@ static void radius_global_deinit()
rc_destroy(rh);
}
static int radius_auth_init(void **ctx, void *pool, const char *username, const char *ip, const char *our_ip, unsigned id)
static int radius_auth_init(void **ctx, void *pool, const common_auth_init_st *info)
{
struct radius_ctx_st *pctx;
char *default_realm;
if (username == NULL || username[0] == 0) {
if (info->username == NULL || info->username[0] == 0) {
syslog(LOG_AUTH,
"radius-auth: no username present");
return ERR_AUTH_FAIL;
@@ -106,22 +106,22 @@ static int radius_auth_init(void **ctx, void *pool, const char *username, const
if (pctx == NULL)
return ERR_AUTH_FAIL;
strlcpy(pctx->username, username, sizeof(pctx->username));
strlcpy(pctx->remote_ip, ip, sizeof(pctx->remote_ip));
if (our_ip)
strlcpy(pctx->our_ip, our_ip, sizeof(pctx->our_ip));
strlcpy(pctx->remote_ip, info->ip, sizeof(pctx->remote_ip));
if (info->our_ip)
strlcpy(pctx->our_ip, info->our_ip, sizeof(pctx->our_ip));
pctx->pass_msg = NULL;
default_realm = rc_conf_str(rh, "default_realm");
if ((strchr(username, '@') == NULL) && default_realm &&
if ((strchr(info->username, '@') == NULL) && default_realm &&
default_realm[0] != 0) {
snprintf(pctx->username, sizeof(pctx->username), "%s@%s", username, default_realm);
snprintf(pctx->username, sizeof(pctx->username), "%s@%s", info->username, default_realm);
} else {
strcpy(pctx->username, username);
strlcpy(pctx->username, info->username, sizeof(pctx->username));
}
pctx->id = id;
pctx->id = info->id;
strlcpy(pctx->user_agent, info->user_agent, sizeof(pctx->user_agent));
*ctx = pctx;
@@ -245,6 +245,14 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
goto cleanup;
}
if (rc_avpair_add(rh, &send, PW_CONNECT_INFO, pctx->user_agent, -1, 0) == NULL) {
syslog(LOG_ERR,
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
pctx->username);
ret = ERR_AUTH_FAIL;
goto cleanup;
}
service = PW_AUTHENTICATE_ONLY;
if (rc_avpair_add(rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
syslog(LOG_ERR,

View File

@@ -26,6 +26,7 @@
struct radius_ctx_st {
char username[MAX_USERNAME_SIZE*2];
char groupname[MAX_GROUPNAME_SIZE];
char user_agent[MAX_AGENT_NAME];
char remote_ip[MAX_IP_STR];
char our_ip[MAX_IP_STR];

View File

@@ -205,6 +205,7 @@ message sec_auth_init_msg
required string ip = 8;
required uint32 auth_type = 9 [default = 0];
optional string our_ip = 10;
optional string user_agent = 11;
}
/* SEC_AUTH_CONT */

View File

@@ -31,9 +31,9 @@ typedef struct acct_mod_st {
void (*global_deinit)(void);
/* The context provided below is of the authentication method */
int (*open_session)(unsigned auth_method, const common_auth_info_st *ai, const void *sid, unsigned sid_size); /* optional, may be null */
void (*session_stats)(unsigned auth_method, const common_auth_info_st *ai, struct stats_st *stats); /* optional, may be null */
void (*close_session)(unsigned auth_method, const common_auth_info_st *ai, struct stats_st *stats, unsigned discon_reason/*REASON_*/); /* optional may be null */
int (*open_session)(unsigned auth_method, const common_acct_info_st *ai, const void *sid, unsigned sid_size); /* optional, may be null */
void (*session_stats)(unsigned auth_method, const common_acct_info_st *ai, struct stats_st *stats); /* optional, may be null */
void (*close_session)(unsigned auth_method, const common_acct_info_st *ai, struct stats_st *stats, unsigned discon_reason/*REASON_*/); /* optional may be null */
} acct_mod_st;
/* The accounting messages exchanged with the worker thread are shown in ipc.proto.

View File

@@ -747,8 +747,16 @@ int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pi
}
if (e->module) {
common_auth_init_st st;
st.username = req->user_name;
st.ip = req->ip;
st.our_ip = req->our_ip;
st.user_agent = req->user_agent;
st.id = pid;
ret =
e->module->auth_init(&e->auth_ctx, e, req->user_name, req->ip, req->our_ip, pid);
e->module->auth_init(&e->auth_ctx, e, &st);
if (ret == ERR_AUTH_CONTINUE) {
need_continue = 1;
} else if (ret < 0) {

View File

@@ -37,7 +37,7 @@ typedef struct auth_mod_st {
unsigned int allows_retries; /* whether the module allows retries of the same password */
void (*global_init)(void *pool, void* additional);
void (*global_deinit)(void);
int (*auth_init)(void** ctx, void *pool, const char* username, const char *remote_ip, const char *our_ip, unsigned id);
int (*auth_init)(void** ctx, void *pool, const common_auth_init_st *);
int (*auth_msg)(void* ctx, void *pool, passwd_msg_st *);
int (*auth_pass)(void* ctx, const char* pass, unsigned pass_len);
int (*auth_group)(void* ctx, const char *suggested, char *groupname, int groupname_size);

View File

@@ -52,7 +52,15 @@ typedef struct stats_st {
time_t uptime;
} stats_st;
typedef struct common_auth_info_st {
typedef struct common_auth_init_st {
const char *username;
const char *ip;
const char *our_ip;
const char *user_agent;
unsigned id;
} common_auth_init_st;
typedef struct common_acct_info_st {
char username[MAX_USERNAME_SIZE*2];
char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */
char psid[BASE64_ENCODE_RAW_LENGTH(SID_SIZE) + 1]; /* printable */
@@ -61,7 +69,7 @@ typedef struct common_auth_info_st {
char ipv4[MAX_IP_STR];
char ipv6[MAX_IP_STR];
unsigned id;
} common_auth_info_st;
} common_acct_info_st;
typedef struct client_entry_st {
/* A unique session identifier used to distinguish sessions
@@ -97,7 +105,7 @@ typedef struct client_entry_st {
unsigned auth_type;
unsigned discon_reason; /* reason for disconnection */
struct common_auth_info_st auth_info;
struct common_acct_info_st auth_info;
/* the module this entry is using */
const struct auth_mod_st *module;

View File

@@ -1400,6 +1400,7 @@ int post_auth_handler(worker_st * ws, unsigned http_ver)
ireq.hostname = req->hostname;
ireq.ip = ws->remote_ip_str;
ireq.our_ip = get_our_ip(ws, our_ip_str);
ireq.user_agent = req->user_agent;
sd = connect_to_secmod(ws);
if (sd == -1) {

View File

@@ -121,7 +121,7 @@ struct http_req_st {
char hostname[MAX_HOSTNAME_SIZE];
char user_agent[MAX_AGENT_NAME];
unsigned user_agent_type;;
unsigned user_agent_type;
unsigned int next_header;