mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
Added support for session control (relevant for PAM for now)
That in effect will utilize the pam_open_session() and pam_close_session(). It is disabled by default as it requires more resources from the security module.
This commit is contained in:
@@ -347,6 +347,33 @@ struct pam_ctx_st * pctx = ctx;
|
|||||||
talloc_free(pctx);
|
talloc_free(pctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pam_auth_open_session(void* ctx)
|
||||||
|
{
|
||||||
|
struct pam_ctx_st * pctx = ctx;
|
||||||
|
int pret;
|
||||||
|
|
||||||
|
pret = pam_open_session(pctx->ph, PAM_SILENT);
|
||||||
|
if (pret != PAM_SUCCESS) {
|
||||||
|
syslog(LOG_AUTH, "PAM-auth: pam_open_session: %s", pam_strerror(pctx->ph, pret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pam_auth_close_session(void* ctx)
|
||||||
|
{
|
||||||
|
struct pam_ctx_st * pctx = ctx;
|
||||||
|
int pret;
|
||||||
|
|
||||||
|
pret = pam_close_session(pctx->ph, PAM_SILENT);
|
||||||
|
if (pret != PAM_SUCCESS) {
|
||||||
|
syslog(LOG_AUTH, "PAM-auth: pam_close_session: %s", pam_strerror(pctx->ph, pret));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static void pam_group_list(void *pool, void *_additional, char ***groupname, unsigned *groupname_size)
|
static void pam_group_list(void *pool, void *_additional, char ***groupname, unsigned *groupname_size)
|
||||||
{
|
{
|
||||||
struct group *grp;
|
struct group *grp;
|
||||||
@@ -392,6 +419,8 @@ const struct auth_mod_st pam_auth_funcs = {
|
|||||||
.auth_pass = pam_auth_pass,
|
.auth_pass = pam_auth_pass,
|
||||||
.auth_group = pam_auth_group,
|
.auth_group = pam_auth_group,
|
||||||
.auth_user = pam_auth_user,
|
.auth_user = pam_auth_user,
|
||||||
|
.open_session = pam_auth_open_session,
|
||||||
|
.close_session = pam_auth_close_session,
|
||||||
.group_list = pam_group_list
|
.group_list = pam_group_list
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ static char tmp[32];
|
|||||||
return "sm: decrypt";
|
return "sm: decrypt";
|
||||||
case SM_CMD_SIGN:
|
case SM_CMD_SIGN:
|
||||||
return "sm: sign";
|
return "sm: sign";
|
||||||
|
case SM_CMD_AUTH_SESSION_CLOSE:
|
||||||
|
return "sm: session close";
|
||||||
|
case SM_CMD_AUTH_SESSION_OPEN:
|
||||||
|
return "sm: session open";
|
||||||
default:
|
default:
|
||||||
snprintf(tmp, sizeof(tmp), "unknown (%u)", _cmd);
|
snprintf(tmp, sizeof(tmp), "unknown (%u)", _cmd);
|
||||||
return tmp;
|
return tmp;
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ static struct cfg_options available_options[] = {
|
|||||||
{ .name = "occtl-socket-file", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "occtl-socket-file", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
{ .name = "banner", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "banner", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
{ .name = "predictable-ips", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
{ .name = "predictable-ips", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
||||||
|
{ .name = "session-control", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
||||||
{ .name = "auto-select-group", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
{ .name = "auto-select-group", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
||||||
{ .name = "default-select-group", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "default-select-group", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
/* this is alias for cisco-client-compat */
|
/* this is alias for cisco-client-compat */
|
||||||
@@ -439,6 +440,8 @@ unsigned force_cert_auth;
|
|||||||
if (config->occtl_socket_file == NULL)
|
if (config->occtl_socket_file == NULL)
|
||||||
config->occtl_socket_file = talloc_strdup(config, OCCTL_UNIX_SOCKET);
|
config->occtl_socket_file = talloc_strdup(config, OCCTL_UNIX_SOCKET);
|
||||||
|
|
||||||
|
READ_TF("session-control", config->session_control, 0);
|
||||||
|
|
||||||
READ_STRING("banner", config->banner);
|
READ_STRING("banner", config->banner);
|
||||||
READ_TF("cisco-client-compat", config->cisco_client_compat, 0);
|
READ_TF("cisco-client-compat", config->cisco_client_compat, 0);
|
||||||
READ_TF("always-require-cert", force_cert_auth, 1);
|
READ_TF("always-require-cert", force_cert_auth, 1);
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ message session_info_msg
|
|||||||
/*
|
/*
|
||||||
* == Auth with username/password ==
|
* == Auth with username/password ==
|
||||||
*
|
*
|
||||||
* main worker
|
* sec-mod worker
|
||||||
* <------ AUTH_INIT (username)
|
* <------ AUTH_INIT (username)
|
||||||
* AUTH_REP(MSG,SID) ------>
|
* AUTH_REP(MSG,SID) ------>
|
||||||
* <------ AUTH_CONT (SID,password)
|
* <------ AUTH_CONT (SID,password)
|
||||||
@@ -173,3 +173,22 @@ message cookie
|
|||||||
required uint32 ipv4_seed = 7;
|
required uint32 ipv4_seed = 7;
|
||||||
required bytes sid = 8;
|
required bytes sid = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* == Session Termination ==
|
||||||
|
*
|
||||||
|
* main sec-mod
|
||||||
|
* SESSION_OPEN/CLOSE ------>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* SEC_SESSION_CLOSE */
|
||||||
|
message sec_auth_session_msg
|
||||||
|
{
|
||||||
|
required bytes sid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message sec_auth_session_reply_msg
|
||||||
|
{
|
||||||
|
required AUTH_REP reply = 1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ struct cookie_entry_st *old;
|
|||||||
memcpy(proc->dtls_session_id, cmsg->session_id.data, cmsg->session_id.len);
|
memcpy(proc->dtls_session_id, cmsg->session_id.data, cmsg->session_id.len);
|
||||||
proc->dtls_session_id_size = cmsg->session_id.len;
|
proc->dtls_session_id_size = cmsg->session_id.len;
|
||||||
memcpy(proc->sid, cmsg->sid.data, cmsg->sid.len);
|
memcpy(proc->sid, cmsg->sid.data, cmsg->sid.len);
|
||||||
|
proc->active_sid = 1;
|
||||||
|
|
||||||
/* cookie is good so far, now read config (in order to know
|
/* cookie is good so far, now read config (in order to know
|
||||||
* whether roaming is allowed or not */
|
* whether roaming is allowed or not */
|
||||||
@@ -269,6 +270,12 @@ struct cookie_entry_st *old;
|
|||||||
|
|
||||||
memcpy(proc->ipv4_seed, &cmsg->ipv4_seed, sizeof(proc->ipv4_seed));
|
memcpy(proc->ipv4_seed, &cmsg->ipv4_seed, sizeof(proc->ipv4_seed));
|
||||||
|
|
||||||
|
ret = session_openclose(s, proc, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
mslog(s, proc, LOG_INFO, "could not open session");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -610,7 +610,7 @@ static void ctl_handle_commands(main_server_st * s)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_upeer_id("ctl", cfd, 0, 0);
|
ret = check_upeer_id("ctl", cfd, 0, 0, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
mslog(s, NULL, LOG_ERR, "ctl: unauthorized connection");
|
mslog(s, NULL, LOG_ERR, "ctl: unauthorized connection");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|||||||
@@ -163,6 +163,77 @@ struct proc_st *ctmp;
|
|||||||
return ctmp;
|
return ctmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int session_openclose(main_server_st * s, struct proc_st *proc, unsigned open)
|
||||||
|
{
|
||||||
|
int sd, ret, e;
|
||||||
|
SecAuthSessionMsg ireq = SEC_AUTH_SESSION_MSG__INIT;
|
||||||
|
SecAuthSessionReplyMsg *msg = NULL;
|
||||||
|
unsigned type;
|
||||||
|
|
||||||
|
if (s->config->session_control == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (open)
|
||||||
|
type = SM_CMD_AUTH_SESSION_OPEN;
|
||||||
|
else
|
||||||
|
type = SM_CMD_AUTH_SESSION_CLOSE;
|
||||||
|
|
||||||
|
sd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (sd == -1) {
|
||||||
|
e = errno;
|
||||||
|
mslog(s, proc, LOG_ERR, "error opening unix socket (for sec-mod) %s",
|
||||||
|
strerror(e));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret =
|
||||||
|
connect(sd, (struct sockaddr *)&s->secmod_addr,
|
||||||
|
s->secmod_addr_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
e = errno;
|
||||||
|
close(sd);
|
||||||
|
mslog(s, proc, LOG_ERR,
|
||||||
|
"error connecting to sec-mod socket '%s': %s",
|
||||||
|
s->secmod_addr.sun_path, strerror(e));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ireq.sid.data = proc->sid;
|
||||||
|
ireq.sid.len = sizeof(proc->sid);
|
||||||
|
|
||||||
|
mslog(s, proc, LOG_DEBUG, "sending msg %s to sec-mod", cmd_request_to_str(type));
|
||||||
|
|
||||||
|
ret = send_msg(proc, sd, type,
|
||||||
|
&ireq, (pack_size_func)sec_auth_session_msg__get_packed_size,
|
||||||
|
(pack_func)sec_auth_session_msg__pack);
|
||||||
|
if (ret < 0) {
|
||||||
|
close(sd);
|
||||||
|
mslog(s, proc, LOG_ERR,
|
||||||
|
"error sending message to sec-mod socket '%s'",
|
||||||
|
s->secmod_addr.sun_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
ret = recv_msg(proc, sd, SM_CMD_AUTH_SESSION_REPLY,
|
||||||
|
(void *)&msg, (unpack_func) sec_auth_session_reply_msg__unpack);
|
||||||
|
close(sd);
|
||||||
|
if (ret < 0) {
|
||||||
|
mslog(s, proc, LOG_ERR, "error receiving auth reply message");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg->reply != AUTH__REP__OK) {
|
||||||
|
mslog(s, proc, LOG_INFO, "could not initiate session for '%s'", proc->username);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
close(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* k: whether to kill the process
|
/* k: whether to kill the process
|
||||||
*/
|
*/
|
||||||
void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
||||||
@@ -179,6 +250,11 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
|||||||
if (proc->username[0] != 0)
|
if (proc->username[0] != 0)
|
||||||
user_disconnected(s, proc);
|
user_disconnected(s, proc);
|
||||||
|
|
||||||
|
/* close any pending sessions */
|
||||||
|
if (s->config->session_control != 0 && proc->active_sid) {
|
||||||
|
session_openclose(s, proc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* close the intercomm fd */
|
/* close the intercomm fd */
|
||||||
if (proc->fd >= 0)
|
if (proc->fd >= 0)
|
||||||
close(proc->fd);
|
close(proc->fd);
|
||||||
@@ -197,8 +273,15 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
|||||||
if (proc->cookie_ptr) {
|
if (proc->cookie_ptr) {
|
||||||
unsigned timeout = s->config->cookie_timeout;
|
unsigned timeout = s->config->cookie_timeout;
|
||||||
|
|
||||||
proc->cookie_ptr->expiration = time(0) + timeout;
|
|
||||||
proc->cookie_ptr->proc = NULL;
|
proc->cookie_ptr->proc = NULL;
|
||||||
|
if (s->config->session_control != 0) {
|
||||||
|
/* if we use session control and we closed the session we
|
||||||
|
* need to invalidate the cookie, so that a new session is
|
||||||
|
* used on the next connection */
|
||||||
|
proc->cookie_ptr->expiration = 1;
|
||||||
|
} else {
|
||||||
|
proc->cookie_ptr->expiration = time(0) + timeout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close_tun(s, proc);
|
close_tun(s, proc);
|
||||||
|
|||||||
@@ -956,6 +956,10 @@ int main(int argc, char** argv)
|
|||||||
/* Initialize certificates */
|
/* Initialize certificates */
|
||||||
tls_load_certs(s, &creds);
|
tls_load_certs(s, &creds);
|
||||||
|
|
||||||
|
s->secmod_addr.sun_family = AF_UNIX;
|
||||||
|
snprintf(s->secmod_addr.sun_path, sizeof(s->secmod_addr.sun_path), "%s", s->socket_file);
|
||||||
|
s->secmod_addr_len = SUN_LEN(&s->secmod_addr);
|
||||||
|
|
||||||
/* initialize memory for worker process */
|
/* initialize memory for worker process */
|
||||||
worker_pool = talloc_named(main_pool, 0, "worker");
|
worker_pool = talloc_named(main_pool, 0, "worker");
|
||||||
if (worker_pool == NULL) {
|
if (worker_pool == NULL) {
|
||||||
@@ -1066,9 +1070,8 @@ int main(int argc, char** argv)
|
|||||||
kill_on_parent_kill(SIGTERM);
|
kill_on_parent_kill(SIGTERM);
|
||||||
|
|
||||||
/* write sec-mod's address */
|
/* write sec-mod's address */
|
||||||
ws->secmod_addr.sun_family = AF_UNIX;
|
memcpy(&ws->secmod_addr, &s->secmod_addr, s->secmod_addr_len);
|
||||||
snprintf(ws->secmod_addr.sun_path, sizeof(ws->secmod_addr.sun_path), "%s", s->socket_file);
|
ws->secmod_addr_len = s->secmod_addr_len;
|
||||||
ws->secmod_addr_len = SUN_LEN(&ws->secmod_addr);
|
|
||||||
|
|
||||||
ws->main_pool = main_pool;
|
ws->main_pool = main_pool;
|
||||||
ws->config = s->config;
|
ws->config = s->config;
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#include <tlslib.h>
|
#include <tlslib.h>
|
||||||
#include "ipc.pb-c.h"
|
#include "ipc.pb-c.h"
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
# include <limits.h>
|
# include <limits.h>
|
||||||
@@ -111,6 +113,7 @@ typedef struct proc_st {
|
|||||||
|
|
||||||
/* The SID present in the cookie. Used for session control only */
|
/* The SID present in the cookie. Used for session control only */
|
||||||
uint8_t sid[SID_SIZE];
|
uint8_t sid[SID_SIZE];
|
||||||
|
unsigned active_sid;
|
||||||
|
|
||||||
/* The DTLS session ID associated with the TLS session
|
/* The DTLS session ID associated with the TLS session
|
||||||
* it is either generated or restored from a cookie.
|
* it is either generated or restored from a cookie.
|
||||||
@@ -193,6 +196,9 @@ typedef struct main_server_st {
|
|||||||
char socket_file[_POSIX_PATH_MAX];
|
char socket_file[_POSIX_PATH_MAX];
|
||||||
char full_socket_file[_POSIX_PATH_MAX];
|
char full_socket_file[_POSIX_PATH_MAX];
|
||||||
pid_t sec_mod_pid;
|
pid_t sec_mod_pid;
|
||||||
|
|
||||||
|
struct sockaddr_un secmod_addr;
|
||||||
|
unsigned secmod_addr_len;
|
||||||
|
|
||||||
unsigned active_clients;
|
unsigned active_clients;
|
||||||
time_t start_time;
|
time_t start_time;
|
||||||
@@ -229,6 +235,8 @@ int handle_resume_fetch_req(main_server_st* s, struct proc_st * proc,
|
|||||||
int handle_resume_store_req(main_server_st* s, struct proc_st *proc,
|
int handle_resume_store_req(main_server_st* s, struct proc_st *proc,
|
||||||
const SessionResumeStoreReqMsg *);
|
const SessionResumeStoreReqMsg *);
|
||||||
|
|
||||||
|
int session_openclose(main_server_st * s, struct proc_st *proc, unsigned open);
|
||||||
|
|
||||||
void
|
void
|
||||||
__attribute__ ((format(printf, 4, 5)))
|
__attribute__ ((format(printf, 4, 5)))
|
||||||
_mslog(const main_server_st * s, const struct proc_st* proc,
|
_mslog(const main_server_st * s, const struct proc_st* proc,
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ An example configuration file follows.
|
|||||||
#auth = "plain[/etc/ocserv/ocpasswd]"
|
#auth = "plain[/etc/ocserv/ocpasswd]"
|
||||||
|
|
||||||
# Whether to enable the authentication method's session control (i.e., PAM).
|
# Whether to enable the authentication method's session control (i.e., PAM).
|
||||||
# That requires more resources on the server so don't enable unless you need
|
# That requires more resources on the server, and makes cookies one-time-use;
|
||||||
# it.
|
# thus don't enable unless you need it.
|
||||||
#session-control = true
|
#session-control = true
|
||||||
|
|
||||||
# A banner to be displayed on clients
|
# A banner to be displayed on clients
|
||||||
@@ -642,11 +642,8 @@ doc-section = {
|
|||||||
ds-type = 'IMPLEMENTATION NOTES';
|
ds-type = 'IMPLEMENTATION NOTES';
|
||||||
ds-format = 'texi';
|
ds-format = 'texi';
|
||||||
ds-text = <<-_EOT_
|
ds-text = <<-_EOT_
|
||||||
The support for PAM is limited to authentication only. That is, PAM is
|
Note that while this server utilizes privilege separation and password
|
||||||
used for authentication but not for session control.
|
authentication occurs on the security module, this does not apply for TLS client
|
||||||
|
|
||||||
Note also, that while this server utilizes privilege separation and password
|
|
||||||
authentication occurs on the main server, this does not apply for TLS client
|
|
||||||
certificate authentication. That is because the worker has no way to
|
certificate authentication. That is because the worker has no way to
|
||||||
prove to the main server that it performed the certificate verification.
|
prove to the main server that it performed the certificate verification.
|
||||||
_EOT_;
|
_EOT_;
|
||||||
|
|||||||
@@ -279,7 +279,10 @@ int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
del_client_entry(sec->client_db, e);
|
ret = 0;
|
||||||
|
if (sec->config->session_control == 0 || module->open_session == NULL) {
|
||||||
|
del_client_entry(sec->client_db, e);
|
||||||
|
} /* else do nothing, and wait for session close/open messages */
|
||||||
} else {
|
} else {
|
||||||
e->status = PS_AUTH_FAILED;
|
e->status = PS_AUTH_FAILED;
|
||||||
add_ip_to_ban_list(sec->ban_db, e->ip, time(0) + sec->config->min_reauth_time);
|
add_ip_to_ban_list(sec->ban_db, e->ip, time(0) + sec->config->min_reauth_time);
|
||||||
@@ -301,6 +304,44 @@ int handle_sec_auth_res(sec_mod_st * sec, client_entry_st * e, int result)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int handle_sec_auth_session_openclose(sec_mod_st * sec, const SecAuthSessionMsg * req, unsigned cmd)
|
||||||
|
{
|
||||||
|
client_entry_st *e;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (sec->config->session_control == 0 || module->open_session == NULL) {
|
||||||
|
seclog(LOG_ERR, "auth session open/close but session control is disabled!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->sid.len != SID_SIZE) {
|
||||||
|
seclog(LOG_ERR, "auth session open/close but with illegal sid size (%d)!",
|
||||||
|
(int)req->sid.len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = find_client_entry(sec->client_db, req->sid.data);
|
||||||
|
if (e == NULL) {
|
||||||
|
seclog(LOG_INFO, "session open/close but with non-existing sid!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == SM_CMD_AUTH_SESSION_OPEN) {
|
||||||
|
ret = module->open_session(e->auth_ctx);
|
||||||
|
if (ret < 0) {
|
||||||
|
e->status = PS_AUTH_FAILED;
|
||||||
|
seclog(LOG_ERR, "could not open session.");
|
||||||
|
del_client_entry(sec->client_db, e);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
e->have_session = 1;
|
||||||
|
} else {
|
||||||
|
del_client_entry(sec->client_db, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int handle_sec_auth_cont(sec_mod_st * sec, const SecAuthContMsg * req)
|
int handle_sec_auth_cont(sec_mod_st * sec, const SecAuthContMsg * req)
|
||||||
{
|
{
|
||||||
client_entry_st *e;
|
client_entry_st *e;
|
||||||
@@ -448,6 +489,9 @@ void sec_auth_user_deinit(client_entry_st * e)
|
|||||||
{
|
{
|
||||||
seclog(LOG_DEBUG, "auth deinit for user '%s'", e->username);
|
seclog(LOG_DEBUG, "auth deinit for user '%s'", e->username);
|
||||||
if (e->auth_ctx != NULL) {
|
if (e->auth_ctx != NULL) {
|
||||||
|
if (e->have_session) {
|
||||||
|
module->close_session(e->auth_ctx);
|
||||||
|
}
|
||||||
module->auth_deinit(e->auth_ctx);
|
module->auth_deinit(e->auth_ctx);
|
||||||
e->auth_ctx = NULL;
|
e->auth_ctx = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ struct auth_mod_st {
|
|||||||
int (*auth_pass)(void* ctx, const char* pass, unsigned pass_len);
|
int (*auth_pass)(void* ctx, const char* pass, unsigned pass_len);
|
||||||
int (*auth_group)(void* ctx, const char *suggested, char *groupname, int groupname_size);
|
int (*auth_group)(void* ctx, const char *suggested, char *groupname, int groupname_size);
|
||||||
int (*auth_user)(void* ctx, char *groupname, int groupname_size);
|
int (*auth_user)(void* ctx, char *groupname, int groupname_size);
|
||||||
|
|
||||||
|
int (*open_session)(void *ctx); /* optional, may be null */
|
||||||
|
void (*close_session)(void *ctx); /* optional */
|
||||||
|
|
||||||
void (*auth_deinit)(void* ctx);
|
void (*auth_deinit)(void* ctx);
|
||||||
void (*group_list)(void *pool, void *additional, char ***groupname, unsigned *groupname_size);
|
void (*group_list)(void *pool, void *additional, char ***groupname, unsigned *groupname_size);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ struct htable *db = _db;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned sec_mod_ban_db_elems(void *_db)
|
||||||
|
{
|
||||||
|
struct htable *db = _db;
|
||||||
|
|
||||||
|
if (db)
|
||||||
|
return db->elems;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void add_ip_to_ban_list(void *_db, const char *ip, time_t reenable_time)
|
void add_ip_to_ban_list(void *_db, const char *ip, time_t reenable_time)
|
||||||
{
|
{
|
||||||
struct htable *db = _db;
|
struct htable *db = _db;
|
||||||
|
|||||||
@@ -71,6 +71,17 @@ struct htable *db = _db;
|
|||||||
talloc_free(db);
|
talloc_free(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The number of elements */
|
||||||
|
unsigned sec_mod_client_db_elems(void *_db)
|
||||||
|
{
|
||||||
|
struct htable *db = _db;
|
||||||
|
|
||||||
|
if (db)
|
||||||
|
return db->elems;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
client_entry_st *new_client_entry(void *_db, const char *ip)
|
client_entry_st *new_client_entry(void *_db, const char *ip)
|
||||||
{
|
{
|
||||||
struct htable *db = _db;
|
struct htable *db = _db;
|
||||||
@@ -129,6 +140,11 @@ static void clean_entry(client_entry_st * e)
|
|||||||
talloc_free(e);
|
talloc_free(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allow few seconds prior to cleaning up entries, to avoid any race
|
||||||
|
* conditions when session control is enabled.
|
||||||
|
*/
|
||||||
|
#define SLACK_TIME 10
|
||||||
|
|
||||||
void cleanup_client_entries(void *_db)
|
void cleanup_client_entries(void *_db)
|
||||||
{
|
{
|
||||||
struct htable *db = _db;
|
struct htable *db = _db;
|
||||||
@@ -138,7 +154,8 @@ void cleanup_client_entries(void *_db)
|
|||||||
|
|
||||||
t = htable_first(db, &iter);
|
t = htable_first(db, &iter);
|
||||||
while (t != NULL) {
|
while (t != NULL) {
|
||||||
if (now - t->time > MAX_AUTH_SECS) {
|
fprintf(stderr, "entry[%d]: %s\n", t->have_session, t->username);
|
||||||
|
if (t->have_session == 0 && now - t->time > MAX_AUTH_SECS + SLACK_TIME) {
|
||||||
htable_delval(db, &iter);
|
htable_delval(db, &iter);
|
||||||
clean_entry(t);
|
clean_entry(t);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ static int handle_op(void *pool, sec_mod_st * sec, uint8_t type, uint8_t * rep,
|
|||||||
|
|
||||||
static
|
static
|
||||||
int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
||||||
uint8_t * buffer, size_t buffer_size)
|
uid_t uid, uint8_t * buffer, size_t buffer_size)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
gnutls_datum_t data, out;
|
gnutls_datum_t data, out;
|
||||||
@@ -275,6 +275,43 @@ int process_packet(void *pool, sec_mod_st * sec, cmd_request_t cmd,
|
|||||||
|
|
||||||
ret = handle_sec_auth_cont(sec, auth_cont);
|
ret = handle_sec_auth_cont(sec, auth_cont);
|
||||||
sec_auth_cont_msg__free_unpacked(auth_cont, &pa);
|
sec_auth_cont_msg__free_unpacked(auth_cont, &pa);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
case SM_CMD_AUTH_SESSION_OPEN:
|
||||||
|
case SM_CMD_AUTH_SESSION_CLOSE:{
|
||||||
|
SecAuthSessionMsg *msg;
|
||||||
|
SecAuthSessionReplyMsg rep = SEC_AUTH_SESSION_REPLY_MSG__INIT;
|
||||||
|
|
||||||
|
if (uid != 0) {
|
||||||
|
seclog(LOG_INFO, "received session open/close from unauthorized uid (%u)\n", (unsigned)uid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg =
|
||||||
|
sec_auth_session_msg__unpack(&pa, data.size,
|
||||||
|
data.data);
|
||||||
|
if (msg == NULL) {
|
||||||
|
seclog(LOG_INFO, "error unpacking session close\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = handle_sec_auth_session_openclose(sec, msg, cmd);
|
||||||
|
sec_auth_session_msg__free_unpacked(msg, &pa);
|
||||||
|
|
||||||
|
if (cmd == SM_CMD_AUTH_SESSION_OPEN) {
|
||||||
|
if (ret < 0)
|
||||||
|
rep.reply = AUTH__REP__FAILED;
|
||||||
|
else
|
||||||
|
rep.reply = AUTH__REP__OK;
|
||||||
|
|
||||||
|
ret = send_msg(pool, sec->fd, SM_CMD_AUTH_SESSION_REPLY, &rep,
|
||||||
|
(pack_size_func) sec_auth_session_reply_msg__get_packed_size,
|
||||||
|
(pack_func) sec_auth_session_reply_msg__pack);
|
||||||
|
if (ret < 0) {
|
||||||
|
seclog(LOG_WARNING, "sec-mod error in sending session reply");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -314,7 +351,11 @@ static void check_other_work(sec_mod_st *sec)
|
|||||||
seclog(LOG_DEBUG, "performing maintenance");
|
seclog(LOG_DEBUG, "performing maintenance");
|
||||||
cleanup_client_entries(sec->client_db);
|
cleanup_client_entries(sec->client_db);
|
||||||
cleanup_banned_entries(sec->ban_db);
|
cleanup_banned_entries(sec->ban_db);
|
||||||
|
seclog(LOG_DEBUG, "active sessions %d, banned entries %d",
|
||||||
|
sec_mod_client_db_elems(sec->client_db),
|
||||||
|
sec_mod_ban_db_elems(sec->ban_db));
|
||||||
alarm(MAINTAINANCE_TIME);
|
alarm(MAINTAINANCE_TIME);
|
||||||
|
need_maintainance = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,6 +394,7 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
|||||||
int cfd, ret, e;
|
int cfd, ret, e;
|
||||||
unsigned cmd, length;
|
unsigned cmd, length;
|
||||||
unsigned i, buffer_size;
|
unsigned i, buffer_size;
|
||||||
|
uid_t uid;
|
||||||
uint8_t *buffer, *tpool;
|
uint8_t *buffer, *tpool;
|
||||||
uint16_t l16;
|
uint16_t l16;
|
||||||
struct pin_st pins;
|
struct pin_st pins;
|
||||||
@@ -521,7 +563,7 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
|||||||
|
|
||||||
/* do not allow unauthorized processes to issue commands
|
/* do not allow unauthorized processes to issue commands
|
||||||
*/
|
*/
|
||||||
ret = check_upeer_id("sec-mod", cfd, config->uid, config->gid);
|
ret = check_upeer_id("sec-mod", cfd, config->uid, config->gid, &uid);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
seclog(LOG_INFO, "rejected unauthorized connection");
|
seclog(LOG_INFO, "rejected unauthorized connection");
|
||||||
goto cont;
|
goto cont;
|
||||||
@@ -558,7 +600,7 @@ void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_f
|
|||||||
|
|
||||||
tpool = talloc_new(sec);
|
tpool = talloc_new(sec);
|
||||||
sec->fd = cfd;
|
sec->fd = cfd;
|
||||||
ret = process_packet(tpool, sec, cmd, buffer, ret);
|
ret = process_packet(tpool, sec, cmd, uid, buffer, ret);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
seclog(LOG_INFO, "error processing data for '%s' command (%d)", cmd_request_to_str(cmd), ret);
|
seclog(LOG_INFO, "error processing data for '%s' command (%d)", cmd_request_to_str(cmd), ret);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ typedef struct client_entry_st {
|
|||||||
*/
|
*/
|
||||||
uint8_t sid[SID_SIZE];
|
uint8_t sid[SID_SIZE];
|
||||||
void * auth_ctx; /* the context of authentication */
|
void * auth_ctx; /* the context of authentication */
|
||||||
|
unsigned have_session; /* whether an auth session is initialized */
|
||||||
|
|
||||||
unsigned status; /* PS_AUTH_ */
|
unsigned status; /* PS_AUTH_ */
|
||||||
|
|
||||||
char ip[MAX_IP_STR]; /* the user's IP */
|
char ip[MAX_IP_STR]; /* the user's IP */
|
||||||
@@ -61,6 +63,7 @@ typedef struct client_entry_st {
|
|||||||
|
|
||||||
void *sec_mod_client_db_init(void *pool);
|
void *sec_mod_client_db_init(void *pool);
|
||||||
void sec_mod_client_db_deinit(void *db);
|
void sec_mod_client_db_deinit(void *db);
|
||||||
|
unsigned sec_mod_client_db_elems(void *_db);
|
||||||
client_entry_st * new_client_entry(void *_db, const char *ip);
|
client_entry_st * new_client_entry(void *_db, const char *ip);
|
||||||
client_entry_st * find_client_entry(void *_db, uint8_t sid[SID_SIZE]);
|
client_entry_st * find_client_entry(void *_db, uint8_t sid[SID_SIZE]);
|
||||||
void del_client_entry(void *_db, client_entry_st * e);
|
void del_client_entry(void *_db, client_entry_st * e);
|
||||||
@@ -74,10 +77,11 @@ void cleanup_client_entries(void *_db);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void sec_auth_init(struct cfg_st *config);
|
void sec_auth_init(struct cfg_st *config);
|
||||||
void sec_auth_user_deinit(client_entry_st *e);
|
|
||||||
|
|
||||||
int handle_sec_auth_init(sec_mod_st *sec, const SecAuthInitMsg * req);
|
int handle_sec_auth_init(sec_mod_st *sec, const SecAuthInitMsg * req);
|
||||||
int handle_sec_auth_cont(sec_mod_st *sec, const SecAuthContMsg * req);
|
int handle_sec_auth_cont(sec_mod_st *sec, const SecAuthContMsg * req);
|
||||||
|
int handle_sec_auth_session_openclose(sec_mod_st * sec, const SecAuthSessionMsg * req, unsigned cmd);
|
||||||
|
void sec_auth_user_deinit(client_entry_st * e);
|
||||||
|
|
||||||
void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_file,
|
void sec_mod_server(void *main_pool, struct cfg_st *config, const char *socket_file,
|
||||||
uint8_t cookie_key[COOKIE_KEY_SIZE]);
|
uint8_t cookie_key[COOKIE_KEY_SIZE]);
|
||||||
@@ -87,5 +91,6 @@ unsigned check_if_banned(void *_db, const char *ip);
|
|||||||
void add_ip_to_ban_list(void *_db, const char *ip, time_t reenable_time);
|
void add_ip_to_ban_list(void *_db, const char *ip, time_t reenable_time);
|
||||||
void *sec_mod_ban_db_init(void *pool);
|
void *sec_mod_ban_db_init(void *pool);
|
||||||
void sec_mod_ban_db_deinit(void *_db);
|
void sec_mod_ban_db_deinit(void *_db);
|
||||||
|
unsigned sec_mod_ban_db_elems(void *_db);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
10
src/system.c
10
src/system.c
@@ -54,7 +54,7 @@ SIGHANDLER_T ocsignal(int signum, SIGHANDLER_T handler)
|
|||||||
/* Checks whether the peer in a socket has the expected @uid and @gid.
|
/* Checks whether the peer in a socket has the expected @uid and @gid.
|
||||||
* Returns zero on success.
|
* Returns zero on success.
|
||||||
*/
|
*/
|
||||||
int check_upeer_id(const char *mod, int cfd, int uid, int gid)
|
int check_upeer_id(const char *mod, int cfd, uid_t uid, uid_t gid, uid_t *ruid)
|
||||||
{
|
{
|
||||||
int e, ret;
|
int e, ret;
|
||||||
#if defined(SO_PEERCRED) && defined(HAVE_STRUCT_UCRED)
|
#if defined(SO_PEERCRED) && defined(HAVE_STRUCT_UCRED)
|
||||||
@@ -78,6 +78,9 @@ int check_upeer_id(const char *mod, int cfd, int uid, int gid)
|
|||||||
"%s: received request from pid %u and uid %u",
|
"%s: received request from pid %u and uid %u",
|
||||||
mod, (unsigned)cr.pid, (unsigned)cr.uid);
|
mod, (unsigned)cr.pid, (unsigned)cr.uid);
|
||||||
|
|
||||||
|
if (ruid)
|
||||||
|
*ruid = cr.uid;
|
||||||
|
|
||||||
if (cr.uid != 0 && (cr.uid != uid || cr.gid != gid)) {
|
if (cr.uid != 0 && (cr.uid != uid || cr.gid != gid)) {
|
||||||
syslog(LOG_DEBUG,
|
syslog(LOG_DEBUG,
|
||||||
"%s: received unauthorized request from pid %u and uid %u",
|
"%s: received unauthorized request from pid %u and uid %u",
|
||||||
@@ -85,7 +88,7 @@ int check_upeer_id(const char *mod, int cfd, int uid, int gid)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#elif defined(HAVE_GETPEEREID)
|
#elif defined(HAVE_GETPEEREID)
|
||||||
pid_t euid;
|
uid_t euid;
|
||||||
gid_t egid;
|
gid_t egid;
|
||||||
|
|
||||||
ret = getpeereid(cfd, &euid, &egid);
|
ret = getpeereid(cfd, &euid, &egid);
|
||||||
@@ -97,6 +100,9 @@ int check_upeer_id(const char *mod, int cfd, int uid, int gid)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ruid)
|
||||||
|
*ruid = euid;
|
||||||
|
|
||||||
syslog(LOG_DEBUG,
|
syslog(LOG_DEBUG,
|
||||||
"%s: received request from a processes with uid %u",
|
"%s: received request from a processes with uid %u",
|
||||||
mod, (unsigned)euid);
|
mod, (unsigned)euid);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
# include <signal.h>
|
# include <signal.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
|
||||||
#ifdef HAVE_SIGHANDLER_T
|
#ifdef HAVE_SIGHANDLER_T
|
||||||
# define SIGHANDLER_T sighandler_t
|
# define SIGHANDLER_T sighandler_t
|
||||||
@@ -39,6 +40,6 @@ void kill_on_parent_kill(int sig);
|
|||||||
|
|
||||||
SIGHANDLER_T ocsignal(int signum, SIGHANDLER_T handler);
|
SIGHANDLER_T ocsignal(int signum, SIGHANDLER_T handler);
|
||||||
|
|
||||||
int check_upeer_id(const char *mod, int cfg, int uid, int gid);
|
int check_upeer_id(const char *mod, int cfg, uid_t uid, uid_t gid, uid_t *ruid);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -113,6 +113,9 @@ typedef enum {
|
|||||||
SM_CMD_AUTH_REP,
|
SM_CMD_AUTH_REP,
|
||||||
SM_CMD_DECRYPT,
|
SM_CMD_DECRYPT,
|
||||||
SM_CMD_SIGN,
|
SM_CMD_SIGN,
|
||||||
|
SM_CMD_AUTH_SESSION_OPEN,
|
||||||
|
SM_CMD_AUTH_SESSION_CLOSE,
|
||||||
|
SM_CMD_AUTH_SESSION_REPLY,
|
||||||
} cmd_request_t;
|
} cmd_request_t;
|
||||||
|
|
||||||
#define MAX_IP_STR 46
|
#define MAX_IP_STR 46
|
||||||
|
|||||||
Reference in New Issue
Block a user