mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user