mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-09 08:16:58 +08:00
Updated code to follow with kernel coding style
Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
This commit is contained in:
@@ -38,21 +38,22 @@
|
||||
#include "auth/pam.h"
|
||||
|
||||
static int ocserv_conv(int msg_size, const struct pam_message **msg,
|
||||
struct pam_response **resp, void *uptr)
|
||||
struct pam_response **resp, void *uptr)
|
||||
{
|
||||
*resp = NULL;
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
static int pam_acct_open_session(void *vctx, unsigned auth_method, const struct common_acct_info_st *ai, const void *sid, unsigned sid_size)
|
||||
static int pam_acct_open_session(void *vctx, unsigned int auth_method,
|
||||
const struct common_acct_info_st *ai,
|
||||
const void *sid, unsigned int sid_size)
|
||||
{
|
||||
int pret;
|
||||
pam_handle_t *ph;
|
||||
struct pam_conv dc;
|
||||
int pret;
|
||||
pam_handle_t *ph;
|
||||
struct pam_conv dc;
|
||||
|
||||
if (ai->username[0] == 0) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"PAM-acct: no username present");
|
||||
oc_syslog(LOG_NOTICE, "PAM-acct: no username present");
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
@@ -60,13 +61,15 @@ struct pam_conv dc;
|
||||
dc.appdata_ptr = NULL;
|
||||
pret = pam_start(PACKAGE, ai->username, &dc, &ph);
|
||||
if (pret != PAM_SUCCESS) {
|
||||
oc_syslog(LOG_NOTICE, "PAM-acct init: %s", pam_strerror(ph, pret));
|
||||
oc_syslog(LOG_NOTICE, "PAM-acct init: %s",
|
||||
pam_strerror(ph, pret));
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
pret = pam_acct_mgmt(ph, PAM_DISALLOW_NULL_AUTHTOK);
|
||||
if (pret != PAM_SUCCESS) {
|
||||
oc_syslog(LOG_INFO, "PAM-acct account error: %s", pam_strerror(ph, pret));
|
||||
oc_syslog(LOG_INFO, "PAM-acct account error: %s",
|
||||
pam_strerror(ph, pret));
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
@@ -77,18 +80,19 @@ fail2:
|
||||
pam_end(ph, pret);
|
||||
fail1:
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
static void pam_acct_close_session(void *vctx, unsigned auth_method, const struct common_acct_info_st *ai, stats_st *stats, unsigned status)
|
||||
static void pam_acct_close_session(void *vctx, unsigned int auth_method,
|
||||
const struct common_acct_info_st *ai,
|
||||
stats_st *stats, unsigned int status)
|
||||
{
|
||||
}
|
||||
|
||||
const struct acct_mod_st pam_acct_funcs = {
|
||||
.type = ACCT_TYPE_PAM,
|
||||
.auth_types = ALL_AUTH_TYPES,
|
||||
.open_session = pam_acct_open_session,
|
||||
.close_session = pam_acct_close_session,
|
||||
.type = ACCT_TYPE_PAM,
|
||||
.auth_types = ALL_AUTH_TYPES,
|
||||
.open_session = pam_acct_open_session,
|
||||
.close_session = pam_acct_close_session,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
#ifdef HAVE_RADIUS
|
||||
|
||||
#ifdef LEGACY_RADIUS
|
||||
# include <freeradius-client.h>
|
||||
#include <freeradius-client.h>
|
||||
#else
|
||||
# include <radcli/radcli.h>
|
||||
#include <radcli/radcli.h>
|
||||
#endif
|
||||
|
||||
#include <sec-mod-acct.h>
|
||||
@@ -61,19 +61,21 @@ static void acct_radius_vhost_init(void **_vctx, void *pool, void *additional)
|
||||
}
|
||||
|
||||
if (config->nas_identifier) {
|
||||
strlcpy(vctx->nas_identifier, config->nas_identifier, sizeof(vctx->nas_identifier));
|
||||
strlcpy(vctx->nas_identifier, config->nas_identifier,
|
||||
sizeof(vctx->nas_identifier));
|
||||
} else {
|
||||
vctx->nas_identifier[0] = 0;
|
||||
}
|
||||
|
||||
if (rc_read_dictionary(vctx->rh, rc_conf_str(vctx->rh, "dictionary")) != 0) {
|
||||
if (rc_read_dictionary(vctx->rh, rc_conf_str(vctx->rh, "dictionary")) !=
|
||||
0) {
|
||||
fprintf(stderr, "error reading the radius dictionary\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*_vctx = vctx;
|
||||
|
||||
return;
|
||||
fail:
|
||||
fail:
|
||||
fprintf(stderr, "radius initialization error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -108,12 +110,15 @@ static void append_stats(rc_handle *rh, VALUE_PAIR **send, stats_st *stats)
|
||||
rc_avpair_add(rh, send, PW_ACCT_OUTPUT_GIGAWORDS, &uout, -1, 0);
|
||||
}
|
||||
|
||||
static void append_acct_standard(struct radius_vhost_ctx *vctx, rc_handle *rh, const common_acct_info_st *ai, VALUE_PAIR **send)
|
||||
static void append_acct_standard(struct radius_vhost_ctx *vctx, rc_handle *rh,
|
||||
const common_acct_info_st *ai,
|
||||
VALUE_PAIR **send)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (vctx->nas_identifier[0] != 0) {
|
||||
rc_avpair_add(rh, send, PW_NAS_IDENTIFIER, vctx->nas_identifier, -1, 0);
|
||||
rc_avpair_add(rh, send, PW_NAS_IDENTIFIER, vctx->nas_identifier,
|
||||
-1, 0);
|
||||
}
|
||||
|
||||
if (ai->our_ip[0] != 0) {
|
||||
@@ -122,9 +127,11 @@ static void append_acct_standard(struct radius_vhost_ctx *vctx, rc_handle *rh, c
|
||||
|
||||
if (inet_pton(AF_INET, ai->our_ip, &in) != 0) {
|
||||
in.s_addr = ntohl(in.s_addr);
|
||||
rc_avpair_add(rh, send, PW_NAS_IP_ADDRESS, (char*)&in, sizeof(struct in_addr), 0);
|
||||
rc_avpair_add(rh, send, PW_NAS_IP_ADDRESS, (char *)&in,
|
||||
sizeof(struct in_addr), 0);
|
||||
} else if (inet_pton(AF_INET6, ai->our_ip, &in6) != 0) {
|
||||
rc_avpair_add(rh, send, PW_NAS_IPV6_ADDRESS, (char*)&in6, sizeof(struct in6_addr), 0);
|
||||
rc_avpair_add(rh, send, PW_NAS_IPV6_ADDRESS,
|
||||
(char *)&in6, sizeof(struct in6_addr), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,9 +145,11 @@ static void append_acct_standard(struct radius_vhost_ctx *vctx, rc_handle *rh, c
|
||||
|
||||
if (ai->ipv4[0] != 0) {
|
||||
struct in_addr in;
|
||||
|
||||
if (inet_pton(AF_INET, ai->ipv4, &in) == 1) {
|
||||
in.s_addr = ntohl(in.s_addr);
|
||||
if (rc_avpair_add(rh, send, PW_FRAMED_IP_ADDRESS, &in, sizeof(in), 0) == NULL) {
|
||||
if (rc_avpair_add(rh, send, PW_FRAMED_IP_ADDRESS, &in,
|
||||
sizeof(in), 0) == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -149,8 +158,10 @@ static void append_acct_standard(struct radius_vhost_ctx *vctx, rc_handle *rh, c
|
||||
#ifndef LEGACY_RADIUS /* bug in freeradius-client */
|
||||
if (ai->ipv6[0] != 0) {
|
||||
struct in6_addr in;
|
||||
|
||||
if (inet_pton(AF_INET6, ai->ipv6, &in) == 1) {
|
||||
if (rc_avpair_add(rh, send, PW_FRAMED_IPV6_ADDRESS, &in, sizeof(in), 0) == NULL) {
|
||||
if (rc_avpair_add(rh, send, PW_FRAMED_IPV6_ADDRESS, &in,
|
||||
sizeof(in), 0) == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -164,7 +175,9 @@ static void append_acct_standard(struct radius_vhost_ctx *vctx, rc_handle *rh, c
|
||||
rc_avpair_add(rh, send, PW_ACCT_AUTHENTIC, &i, -1, 0);
|
||||
}
|
||||
|
||||
static void radius_acct_session_stats(void *_vctx, unsigned auth_method, const common_acct_info_st *ai, stats_st *stats)
|
||||
static void radius_acct_session_stats(void *_vctx, unsigned int auth_method,
|
||||
const common_acct_info_st *ai,
|
||||
stats_st *stats)
|
||||
{
|
||||
int ret;
|
||||
uint32_t status_type;
|
||||
@@ -175,7 +188,8 @@ static void radius_acct_session_stats(void *_vctx, unsigned auth_method, const c
|
||||
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: sending session interim update");
|
||||
|
||||
if (rc_avpair_add(vctx->rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
|
||||
if (rc_avpair_add(vctx->rh, &send, PW_ACCT_STATUS_TYPE, &status_type,
|
||||
-1, 0) == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -188,15 +202,18 @@ static void radius_acct_session_stats(void *_vctx, unsigned auth_method, const c
|
||||
rc_avpair_free(recvd);
|
||||
|
||||
if (ret != OK_RC) {
|
||||
oc_syslog(LOG_NOTICE, "radius-auth: radius_open_session: %d", ret);
|
||||
oc_syslog(LOG_NOTICE, "radius-auth: radius_open_session: %d",
|
||||
ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
rc_avpair_free(send);
|
||||
}
|
||||
|
||||
static int radius_acct_open_session(void *_vctx, unsigned auth_method, const common_acct_info_st *ai, const void *sid, unsigned sid_size)
|
||||
static int radius_acct_open_session(void *_vctx, unsigned int auth_method,
|
||||
const common_acct_info_st *ai,
|
||||
const void *sid, unsigned int sid_size)
|
||||
{
|
||||
int ret;
|
||||
uint32_t status_type;
|
||||
@@ -212,13 +229,15 @@ static int radius_acct_open_session(void *_vctx, unsigned auth_method, const com
|
||||
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: opening session %s", ai->safe_id);
|
||||
|
||||
if (rc_avpair_add(vctx->rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
|
||||
if (rc_avpair_add(vctx->rh, &send, PW_ACCT_STATUS_TYPE, &status_type,
|
||||
-1, 0) == NULL) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ai->user_agent[0] != 0) {
|
||||
rc_avpair_add(vctx->rh, &send, PW_CONNECT_INFO, ai->user_agent, -1, 0);
|
||||
rc_avpair_add(vctx->rh, &send, PW_CONNECT_INFO, ai->user_agent,
|
||||
-1, 0);
|
||||
}
|
||||
|
||||
append_acct_standard(vctx, vctx->rh, ai, &send);
|
||||
@@ -229,18 +248,22 @@ static int radius_acct_open_session(void *_vctx, unsigned auth_method, const com
|
||||
rc_avpair_free(recvd);
|
||||
|
||||
if (ret != OK_RC) {
|
||||
oc_syslog(LOG_NOTICE, "radius-auth: radius_open_session: %d", ret);
|
||||
oc_syslog(LOG_NOTICE, "radius-auth: radius_open_session: %d",
|
||||
ret);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
cleanup:
|
||||
rc_avpair_free(send);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void radius_acct_close_session(void *_vctx, unsigned auth_method, const common_acct_info_st *ai, stats_st *stats, unsigned discon_reason)
|
||||
static void radius_acct_close_session(void *_vctx, unsigned int auth_method,
|
||||
const common_acct_info_st *ai,
|
||||
stats_st *stats,
|
||||
unsigned int discon_reason)
|
||||
{
|
||||
int ret;
|
||||
uint32_t status_type;
|
||||
@@ -250,7 +273,8 @@ static void radius_acct_close_session(void *_vctx, unsigned auth_method, const c
|
||||
status_type = PW_STATUS_STOP;
|
||||
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: closing session");
|
||||
if (rc_avpair_add(vctx->rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL)
|
||||
if (rc_avpair_add(vctx->rh, &send, PW_ACCT_STATUS_TYPE, &status_type,
|
||||
-1, 0) == NULL)
|
||||
return;
|
||||
|
||||
if (discon_reason == REASON_USER_DISCONNECT)
|
||||
@@ -277,11 +301,12 @@ static void radius_acct_close_session(void *_vctx, unsigned auth_method, const c
|
||||
rc_avpair_free(recvd);
|
||||
|
||||
if (ret != OK_RC) {
|
||||
oc_syslog(LOG_INFO, "radius-auth: radius_close_session: %d", ret);
|
||||
oc_syslog(LOG_INFO, "radius-auth: radius_close_session: %d",
|
||||
ret);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
rc_avpair_free(send);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,10 +35,10 @@
|
||||
int get_user_auth_group(const char *username, const char *suggested,
|
||||
char *groupname, int groupname_size)
|
||||
{
|
||||
struct passwd * pwd;
|
||||
struct group *grp;
|
||||
int ret;
|
||||
unsigned found;
|
||||
struct passwd *pwd;
|
||||
struct group *grp;
|
||||
int ret;
|
||||
unsigned int found;
|
||||
|
||||
groupname[0] = 0;
|
||||
|
||||
@@ -47,61 +47,69 @@ unsigned found;
|
||||
if (suggested != NULL) {
|
||||
gid_t groups[MAX_GROUPS];
|
||||
int ngroups = ARRAY_SIZE(groups);
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
ret = getgrouplist(username, pwd->pw_gid, groups, &ngroups);
|
||||
ret = getgrouplist(username, pwd->pw_gid, groups,
|
||||
&ngroups);
|
||||
if (ret <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
found = 0;
|
||||
for (i=0;i<ngroups;i++) {
|
||||
for (i = 0; i < ngroups; i++) {
|
||||
grp = getgrgid(groups[i]);
|
||||
if (grp != NULL && strcmp(suggested, grp->gr_name) == 0) {
|
||||
strlcpy(groupname, grp->gr_name, groupname_size);
|
||||
if (grp != NULL &&
|
||||
strcmp(suggested, grp->gr_name) == 0) {
|
||||
strlcpy(groupname, grp->gr_name,
|
||||
groupname_size);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"user '%s' requested group '%s' but is not a member",
|
||||
username, suggested);
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"user '%s' requested group '%s' but is not a member",
|
||||
username, suggested);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
struct group* grp = getgrgid(pwd->pw_gid);
|
||||
struct group *grp = getgrgid(pwd->pw_gid);
|
||||
|
||||
if (grp != NULL)
|
||||
strlcpy(groupname, grp->gr_name, groupname_size);
|
||||
strlcpy(groupname, grp->gr_name,
|
||||
groupname_size);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unix_group_list(void *pool, unsigned gid_min, char ***groupname, unsigned *groupname_size)
|
||||
void unix_group_list(void *pool, unsigned int gid_min, char ***groupname,
|
||||
unsigned int *groupname_size)
|
||||
{
|
||||
struct group *grp;
|
||||
|
||||
setgrent();
|
||||
|
||||
*groupname_size = 0;
|
||||
*groupname = talloc_size(pool, sizeof(char*)*MAX_GROUPS);
|
||||
*groupname = talloc_size(pool, sizeof(char *) * MAX_GROUPS);
|
||||
if (*groupname == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while ((grp = getgrent()) != NULL && (*groupname_size) < MAX_GROUPS) {
|
||||
if (grp->gr_gid >= gid_min) {
|
||||
(*groupname)[(*groupname_size)] = talloc_strdup(*groupname, grp->gr_name);
|
||||
(*groupname)[(*groupname_size)] =
|
||||
talloc_strdup(*groupname, grp->gr_name);
|
||||
if ((*groupname)[(*groupname_size)] == NULL)
|
||||
break;
|
||||
(*groupname_size)++;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
exit:
|
||||
endgrent();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#ifndef OC_AUTH_UNIX_H
|
||||
# define OC_AUTH_UNIX_H
|
||||
#define OC_AUTH_UNIX_H
|
||||
|
||||
# include <config.h>
|
||||
#include <config.h>
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(HAVE_PAM)
|
||||
# define HAVE_GET_USER_AUTH_GROUP
|
||||
#define HAVE_GET_USER_AUTH_GROUP
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GET_USER_AUTH_GROUP
|
||||
int get_user_auth_group(const char *username, const char *suggested,
|
||||
char *groupname, int groupname_size);
|
||||
void unix_group_list(void *pool, unsigned gid_min, char ***groupname, unsigned *groupname_size);
|
||||
void unix_group_list(void *pool, unsigned int gid_min, char ***groupname,
|
||||
unsigned int *groupname_size);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef AUTH_COMMON_H
|
||||
# define AUTH_COMMON_H
|
||||
#define AUTH_COMMON_H
|
||||
|
||||
#define MAX_PASSWORD_TRIES 3
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
@@ -42,7 +41,7 @@
|
||||
struct gssapi_vhost_ctx_st {
|
||||
gss_cred_id_t creds;
|
||||
gss_OID_set oids;
|
||||
unsigned no_local_map;
|
||||
unsigned int no_local_map;
|
||||
time_t ticket_freshness_secs;
|
||||
};
|
||||
|
||||
@@ -57,8 +56,7 @@ struct gssapi_ctx_st {
|
||||
};
|
||||
|
||||
/* Taken from openconnect's gssapi */
|
||||
static void print_gss_err(const char *where,
|
||||
gss_OID mech, OM_uint32 err_maj,
|
||||
static void print_gss_err(const char *where, gss_OID mech, OM_uint32 err_maj,
|
||||
OM_uint32 err_min)
|
||||
{
|
||||
OM_uint32 major, minor, msg_ctx = 0;
|
||||
@@ -69,7 +67,8 @@ static void print_gss_err(const char *where,
|
||||
mech, &msg_ctx, &status);
|
||||
if (GSS_ERROR(major))
|
||||
break;
|
||||
oc_syslog(LOG_ERR, "gssapi: %s[maj]: %s\n", where, (char *)status.value);
|
||||
oc_syslog(LOG_ERR, "gssapi: %s[maj]: %s\n", where,
|
||||
(char *)status.value);
|
||||
gss_release_buffer(&minor, &status);
|
||||
} while (msg_ctx);
|
||||
|
||||
@@ -79,16 +78,15 @@ static void print_gss_err(const char *where,
|
||||
mech, &msg_ctx, &status);
|
||||
if (GSS_ERROR(major))
|
||||
break;
|
||||
oc_syslog(LOG_ERR, "gssapi: %s[min]: %s\n", where, (char *)status.value);
|
||||
oc_syslog(LOG_ERR, "gssapi: %s[min]: %s\n", where,
|
||||
(char *)status.value);
|
||||
gss_release_buffer(&minor, &status);
|
||||
} while (msg_ctx);
|
||||
}
|
||||
|
||||
const gss_OID_desc spnego_mech = {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
|
||||
const gss_OID_set_desc desired_mechs = {
|
||||
.count = 1,
|
||||
.elements = (gss_OID)&spnego_mech
|
||||
};
|
||||
const gss_OID_desc spnego_mech = { 6, (void *)"\x2b\x06\x01\x05\x05\x02" };
|
||||
const gss_OID_set_desc desired_mechs = { .count = 1,
|
||||
.elements = (gss_OID)&spnego_mech };
|
||||
|
||||
static void gssapi_vhost_init(void **_vctx, void *pool, void *additional)
|
||||
{
|
||||
@@ -118,21 +116,26 @@ static void gssapi_vhost_init(void **_vctx, void *pool, void *additional)
|
||||
cred_store.count = 1;
|
||||
cred_store.elements = &element;
|
||||
|
||||
ret = gss_acquire_cred_from(&minor, name, 0, (gss_OID_set)&desired_mechs, 2,
|
||||
&cred_store, &vctx->creds, &vctx->oids, &time);
|
||||
ret = gss_acquire_cred_from(&minor, name, 0,
|
||||
(gss_OID_set)&desired_mechs, 2,
|
||||
&cred_store, &vctx->creds,
|
||||
&vctx->oids, &time);
|
||||
|
||||
if (ret != GSS_S_COMPLETE) {
|
||||
ret = -1;
|
||||
print_gss_err("gss_acquire_cred(keytab)", GSS_C_NO_OID, ret, minor);
|
||||
print_gss_err("gss_acquire_cred(keytab)", GSS_C_NO_OID,
|
||||
ret, minor);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
ret = gss_acquire_cred(&minor, name, 0, (gss_OID_set)&desired_mechs, 2,
|
||||
&vctx->creds, &vctx->oids, &time);
|
||||
ret = gss_acquire_cred(&minor, name, 0,
|
||||
(gss_OID_set)&desired_mechs, 2,
|
||||
&vctx->creds, &vctx->oids, &time);
|
||||
|
||||
if (ret != GSS_S_COMPLETE) {
|
||||
ret = -1;
|
||||
print_gss_err("gss_acquire_cred", GSS_C_NO_OID, ret, minor);
|
||||
print_gss_err("gss_acquire_cred", GSS_C_NO_OID, ret,
|
||||
minor);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -149,7 +152,8 @@ static void gssapi_vhost_deinit(void *_vctx)
|
||||
gss_release_cred(&minor, &vctx->creds);
|
||||
}
|
||||
|
||||
static int get_name(struct gssapi_ctx_st *pctx, gss_name_t client, gss_OID mech_type)
|
||||
static int get_name(struct gssapi_ctx_st *pctx, gss_name_t client,
|
||||
gss_OID mech_type)
|
||||
{
|
||||
int ret;
|
||||
OM_uint32 minor;
|
||||
@@ -168,20 +172,24 @@ static int get_name(struct gssapi_ctx_st *pctx, gss_name_t client, gss_OID mech_
|
||||
pctx->username[name.length] = 0;
|
||||
}
|
||||
|
||||
oc_syslog(LOG_DEBUG, "gssapi: authenticated GSSAPI user: %.*s", (unsigned)name.length, (char*)name.value);
|
||||
oc_syslog(LOG_DEBUG, "gssapi: authenticated GSSAPI user: %.*s",
|
||||
(unsigned int)name.length, (char *)name.value);
|
||||
gss_release_buffer(&minor, &name);
|
||||
|
||||
if (pctx->vctx->no_local_map == 0) {
|
||||
ret = gss_localname(&minor, client, mech_type, &name);
|
||||
if (GSS_ERROR(ret) || name.length >= MAX_USERNAME_SIZE) {
|
||||
print_gss_err("gss_localname", mech_type, ret, minor);
|
||||
oc_syslog(LOG_INFO, "gssapi: authenticated user doesn't map to a local user");
|
||||
oc_syslog(
|
||||
LOG_INFO,
|
||||
"gssapi: authenticated user doesn't map to a local user");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(pctx->username, name.value, name.length);
|
||||
pctx->username[name.length] = 0;
|
||||
oc_syslog(LOG_INFO, "gssapi: authenticated local user: %s", pctx->username);
|
||||
oc_syslog(LOG_INFO, "gssapi: authenticated local user: %s",
|
||||
pctx->username);
|
||||
|
||||
gss_release_buffer(&minor, &name);
|
||||
}
|
||||
@@ -192,38 +200,49 @@ static int get_name(struct gssapi_ctx_st *pctx, gss_name_t client, gss_OID mech_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_krb5_constraints(struct gssapi_ctx_st *pctx, gss_OID mech_type)
|
||||
static int verify_krb5_constraints(struct gssapi_ctx_st *pctx,
|
||||
gss_OID mech_type)
|
||||
{
|
||||
int ret;
|
||||
OM_uint32 minor;
|
||||
krb5_timestamp authtime;
|
||||
|
||||
if (mech_type == NULL ||
|
||||
((mech_type->length != gss_mech_krb5->length || memcmp(mech_type->elements, gss_mech_krb5->elements, mech_type->length) != 0) &&
|
||||
(mech_type->length != gss_mech_krb5_old->length || memcmp(mech_type->elements, gss_mech_krb5_old->elements, mech_type->length) != 0)) ||
|
||||
((mech_type->length != gss_mech_krb5->length ||
|
||||
memcmp(mech_type->elements, gss_mech_krb5->elements,
|
||||
mech_type->length) != 0) &&
|
||||
(mech_type->length != gss_mech_krb5_old->length ||
|
||||
memcmp(mech_type->elements, gss_mech_krb5_old->elements,
|
||||
mech_type->length) != 0)) ||
|
||||
pctx->vctx->ticket_freshness_secs == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = gsskrb5_extract_authtime_from_sec_context (&minor, pctx->gssctx, &authtime);
|
||||
ret = gsskrb5_extract_authtime_from_sec_context(&minor, pctx->gssctx,
|
||||
&authtime);
|
||||
if (GSS_ERROR(ret)) {
|
||||
print_gss_err("gsskrb5_extract_authtime_from_sec_context", mech_type, ret, minor);
|
||||
print_gss_err("gsskrb5_extract_authtime_from_sec_context",
|
||||
mech_type, ret, minor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (time(NULL) > authtime + pctx->vctx->ticket_freshness_secs) {
|
||||
oc_syslog(LOG_INFO, "gssapi: the presented kerberos ticket for %s is too old", pctx->username);
|
||||
oc_syslog(
|
||||
LOG_INFO,
|
||||
"gssapi: the presented kerberos ticket for %s is too old",
|
||||
pctx->username);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gssapi_auth_init(void **ctx, void *pool, void *_vctx, const common_auth_init_st *info)
|
||||
static int gssapi_auth_init(void **ctx, void *pool, void *_vctx,
|
||||
const common_auth_init_st *info)
|
||||
{
|
||||
struct gssapi_ctx_st *pctx;
|
||||
OM_uint32 minor, flags, time;
|
||||
gss_buffer_desc buf= GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc buf = GSS_C_EMPTY_BUFFER;
|
||||
gss_name_t client = GSS_C_NO_NAME;
|
||||
gss_OID mech_type = GSS_C_NO_OID;
|
||||
int ret;
|
||||
@@ -243,20 +262,22 @@ static int gssapi_auth_init(void **ctx, void *pool, void *_vctx, const common_au
|
||||
|
||||
pctx->vctx = vctx;
|
||||
|
||||
ret = oc_base64_decode_alloc(pctx, spnego, strlen(spnego), &raw, &raw_len);
|
||||
ret = oc_base64_decode_alloc(pctx, spnego, strlen(spnego), &raw,
|
||||
&raw_len);
|
||||
if (ret == 0) {
|
||||
oc_syslog(LOG_ERR, "gssapi: error in base64 decoding %s", __func__);
|
||||
oc_syslog(LOG_ERR, "gssapi: error in base64 decoding %s",
|
||||
__func__);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
buf.value = raw;
|
||||
buf.length = raw_len;
|
||||
ret = gss_accept_sec_context(&minor, &pctx->gssctx, vctx->creds, &buf,
|
||||
GSS_C_NO_CHANNEL_BINDINGS, &client, &mech_type, &pctx->msg,
|
||||
&flags, &time, &pctx->delegated_creds);
|
||||
GSS_C_NO_CHANNEL_BINDINGS, &client,
|
||||
&mech_type, &pctx->msg, &flags, &time,
|
||||
&pctx->delegated_creds);
|
||||
talloc_free(raw);
|
||||
|
||||
|
||||
if (ret == GSS_S_CONTINUE_NEEDED) {
|
||||
gss_release_name(&minor, &client);
|
||||
ret = ERR_AUTH_CONTINUE;
|
||||
@@ -277,11 +298,13 @@ static int gssapi_auth_init(void **ctx, void *pool, void *_vctx, const common_au
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gssapi_auth_group(void *ctx, const char *suggested, char *groupname, int groupname_size)
|
||||
static int gssapi_auth_group(void *ctx, const char *suggested, char *groupname,
|
||||
int groupname_size)
|
||||
{
|
||||
struct gssapi_ctx_st *pctx = ctx;
|
||||
|
||||
return get_user_auth_group(pctx->username, suggested, groupname, groupname_size);
|
||||
return get_user_auth_group(pctx->username, suggested, groupname,
|
||||
groupname_size);
|
||||
}
|
||||
|
||||
static int gssapi_auth_user(void *ctx, char *username, int username_size)
|
||||
@@ -294,7 +317,8 @@ static int gssapi_auth_user(void *ctx, char *username, int username_size)
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name.
|
||||
*/
|
||||
static int gssapi_auth_pass(void *ctx, const char *spnego, unsigned spnego_len)
|
||||
static int gssapi_auth_pass(void *ctx, const char *spnego,
|
||||
unsigned int spnego_len)
|
||||
{
|
||||
struct gssapi_ctx_st *pctx = ctx;
|
||||
OM_uint32 minor, flags, time;
|
||||
@@ -308,15 +332,17 @@ static int gssapi_auth_pass(void *ctx, const char *spnego, unsigned spnego_len)
|
||||
/* nothing to be done */
|
||||
ret = oc_base64_decode_alloc(pctx, spnego, spnego_len, &raw, &raw_len);
|
||||
if (ret == 0) {
|
||||
oc_syslog(LOG_ERR, "gssapi: error in base64 decoding %s", __func__);
|
||||
oc_syslog(LOG_ERR, "gssapi: error in base64 decoding %s",
|
||||
__func__);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
buf.value = raw;
|
||||
buf.length = raw_len;
|
||||
ret = gss_accept_sec_context(&minor, &pctx->gssctx, pctx->vctx->creds, &buf,
|
||||
GSS_C_NO_CHANNEL_BINDINGS, &client, &mech_type, &pctx->msg,
|
||||
&flags, &time, &pctx->delegated_creds);
|
||||
ret = gss_accept_sec_context(&minor, &pctx->gssctx, pctx->vctx->creds,
|
||||
&buf, GSS_C_NO_CHANNEL_BINDINGS, &client,
|
||||
&mech_type, &pctx->msg, &flags, &time,
|
||||
&pctx->delegated_creds);
|
||||
talloc_free(raw);
|
||||
|
||||
if (ret == GSS_S_CONTINUE_NEEDED) {
|
||||
@@ -340,15 +366,15 @@ static int gssapi_auth_msg(void *ctx, void *pool, passwd_msg_st *pst)
|
||||
{
|
||||
struct gssapi_ctx_st *pctx = ctx;
|
||||
OM_uint32 min;
|
||||
unsigned length;
|
||||
unsigned int length;
|
||||
|
||||
/* our msg is our SPNEGO reply */
|
||||
if (pctx->msg.value != NULL) {
|
||||
length = BASE64_ENCODE_RAW_LENGTH(pctx->msg.length)+1;
|
||||
length = BASE64_ENCODE_RAW_LENGTH(pctx->msg.length) + 1;
|
||||
pst->msg_str = talloc_size(pool, length);
|
||||
|
||||
oc_base64_encode(pctx->msg.value, pctx->msg.length,
|
||||
pst->msg_str, length);
|
||||
pst->msg_str, length);
|
||||
|
||||
gss_release_buffer(&min, &pctx->msg);
|
||||
pctx->msg.value = NULL;
|
||||
@@ -367,7 +393,8 @@ static void gssapi_auth_deinit(void *ctx)
|
||||
talloc_free(ctx);
|
||||
}
|
||||
|
||||
static void gssapi_group_list(void *pool, void *_additional, char ***groupname, unsigned *groupname_size)
|
||||
static void gssapi_group_list(void *pool, void *_additional, char ***groupname,
|
||||
unsigned int *groupname_size)
|
||||
{
|
||||
gssapi_cfg_st *config = _additional;
|
||||
gid_t min = 0;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
typedef struct oidc_vctx_st {
|
||||
json_t *config;
|
||||
json_t *jwks;
|
||||
void * pool;
|
||||
void *pool;
|
||||
int minimum_jwk_refresh_time;
|
||||
time_t last_jwks_load_time;
|
||||
} oidc_vctx_st;
|
||||
@@ -49,10 +49,10 @@ typedef struct oidc_ctx_st {
|
||||
int token_verified;
|
||||
} oidc_ctx_st;
|
||||
|
||||
static bool oidc_fetch_oidc_keys(oidc_vctx_st * vctx);
|
||||
static bool oidc_verify_token(oidc_vctx_st * vctx, const char *token,
|
||||
size_t token_length,
|
||||
char user_name[MAX_USERNAME_SIZE]);
|
||||
static bool oidc_fetch_oidc_keys(oidc_vctx_st *vctx);
|
||||
static bool oidc_verify_token(oidc_vctx_st *vctx, const char *token,
|
||||
size_t token_length,
|
||||
char user_name[MAX_USERNAME_SIZE]);
|
||||
|
||||
static void oidc_vhost_init(void **vctx, void *pool, void *additional)
|
||||
{
|
||||
@@ -76,30 +76,35 @@ static void oidc_vhost_init(void **vctx, void *pool, void *additional)
|
||||
|
||||
vc->config = json_load_file(config, 0, &err);
|
||||
if (vc->config == NULL) {
|
||||
oc_syslog(LOG_ERR, "ocserv-oidc: failed to load config file: %s\n", config);
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to load config file: %s\n",
|
||||
config);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!json_object_get(vc->config, "openid_configuration_url")) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: config file missing openid_configuration_url\n");
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: config file missing openid_configuration_url\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!json_object_get(vc->config, "required_claims")) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: config file missing required_claims\n");
|
||||
"ocserv-oidc: config file missing required_claims\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!json_object_get(vc->config, "user_name_claim")) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: config file missing user_name_claim\n");
|
||||
"ocserv-oidc: config file missing user_name_claim\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (json_object_get(vc->config, "minimum_jwk_refresh_time")) {
|
||||
vc->minimum_jwk_refresh_time = json_integer_value(json_object_get(vc->config, "minimum_jwk_refresh_time"));
|
||||
vc->minimum_jwk_refresh_time = json_integer_value(
|
||||
json_object_get(vc->config,
|
||||
"minimum_jwk_refresh_time"));
|
||||
} else {
|
||||
vc->minimum_jwk_refresh_time = MINIMUM_KEY_REFRESH_INTERVAL;
|
||||
}
|
||||
@@ -114,7 +119,7 @@ static void oidc_vhost_init(void **vctx, void *pool, void *additional)
|
||||
|
||||
static void oidc_vhost_deinit(void *ctx)
|
||||
{
|
||||
oidc_vctx_st *vctx = (oidc_vctx_st *) ctx;
|
||||
oidc_vctx_st *vctx = (oidc_vctx_st *)ctx;
|
||||
|
||||
if (!vctx) {
|
||||
return;
|
||||
@@ -132,10 +137,11 @@ static void oidc_vhost_deinit(void *ctx)
|
||||
}
|
||||
|
||||
static int oidc_auth_init(void **ctx, void *pool, void *vctx,
|
||||
const common_auth_init_st * info)
|
||||
const common_auth_init_st *info)
|
||||
{
|
||||
oidc_vctx_st *vt = (oidc_vctx_st *) vctx;
|
||||
oidc_vctx_st *vt = (oidc_vctx_st *)vctx;
|
||||
oidc_ctx_st *ct;
|
||||
|
||||
ct = talloc_zero(pool, struct oidc_ctx_st);
|
||||
if (!ct) {
|
||||
return ERR_AUTH_FAIL;
|
||||
@@ -143,7 +149,8 @@ static int oidc_auth_init(void **ctx, void *pool, void *vctx,
|
||||
ct->vctx_st = vt;
|
||||
*ctx = (void *)ct;
|
||||
|
||||
if (oidc_verify_token(ct->vctx_st, info->username, strlen(info->username), ct->username)) {
|
||||
if (oidc_verify_token(ct->vctx_st, info->username,
|
||||
strlen(info->username), ct->username)) {
|
||||
ct->token_verified = 1;
|
||||
return 0;
|
||||
} else {
|
||||
@@ -153,7 +160,7 @@ static int oidc_auth_init(void **ctx, void *pool, void *vctx,
|
||||
|
||||
static int oidc_auth_user(void *ctx, char *username, int username_size)
|
||||
{
|
||||
oidc_ctx_st *ct = (oidc_ctx_st *) ctx;
|
||||
oidc_ctx_st *ct = (oidc_ctx_st *)ctx;
|
||||
|
||||
if (ct->token_verified) {
|
||||
strlcpy(username, ct->username, username_size);
|
||||
@@ -162,14 +169,14 @@ static int oidc_auth_user(void *ctx, char *username, int username_size)
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
static int oidc_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
static int oidc_auth_pass(void *ctx, const char *pass, unsigned int pass_len)
|
||||
{
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
static int oidc_auth_msg(void *ctx, void *pool, passwd_msg_st * pst)
|
||||
static int oidc_auth_msg(void *ctx, void *pool, passwd_msg_st *pst)
|
||||
{
|
||||
pst->counter = 0; /* we support a single password */
|
||||
pst->counter = 0; /* we support a single password */
|
||||
|
||||
/* use the default prompt */
|
||||
return 0;
|
||||
@@ -180,19 +187,17 @@ static void oidc_auth_deinit(void *ctx)
|
||||
talloc_free(ctx);
|
||||
}
|
||||
|
||||
const struct auth_mod_st oidc_auth_funcs = {
|
||||
.type = AUTH_TYPE_OIDC,
|
||||
.allows_retries = 1,
|
||||
.vhost_init = oidc_vhost_init,
|
||||
.vhost_deinit = oidc_vhost_deinit,
|
||||
.auth_init = oidc_auth_init,
|
||||
.auth_deinit = oidc_auth_deinit,
|
||||
.auth_msg = oidc_auth_msg,
|
||||
.auth_pass = oidc_auth_pass,
|
||||
.auth_user = oidc_auth_user,
|
||||
.auth_group = NULL,
|
||||
.group_list = NULL
|
||||
};
|
||||
const struct auth_mod_st oidc_auth_funcs = { .type = AUTH_TYPE_OIDC,
|
||||
.allows_retries = 1,
|
||||
.vhost_init = oidc_vhost_init,
|
||||
.vhost_deinit = oidc_vhost_deinit,
|
||||
.auth_init = oidc_auth_init,
|
||||
.auth_deinit = oidc_auth_deinit,
|
||||
.auth_msg = oidc_auth_msg,
|
||||
.auth_pass = oidc_auth_pass,
|
||||
.auth_user = oidc_auth_user,
|
||||
.auth_group = NULL,
|
||||
.group_list = NULL };
|
||||
|
||||
// Key management
|
||||
typedef struct oidc_json_parser_context {
|
||||
@@ -204,10 +209,10 @@ typedef struct oidc_json_parser_context {
|
||||
|
||||
// Callback from CURL for each block as it is downloaded
|
||||
static size_t oidc_json_parser_context_callback(char *ptr, size_t size,
|
||||
size_t nmemb, void *userdata)
|
||||
size_t nmemb, void *userdata)
|
||||
{
|
||||
oidc_json_parser_context *context =
|
||||
(oidc_json_parser_context *) userdata;
|
||||
(oidc_json_parser_context *)userdata;
|
||||
size_t new_offset = context->offset + nmemb;
|
||||
|
||||
// Check for buffer overflow
|
||||
@@ -217,7 +222,9 @@ static size_t oidc_json_parser_context_callback(char *ptr, size_t size,
|
||||
|
||||
if (context->offset + nmemb > context->length) {
|
||||
size_t new_size = (nmemb + context->length) * 3 / 2;
|
||||
void * new_buffer = talloc_realloc_size(context->pool, context->buffer, new_size);
|
||||
void *new_buffer = talloc_realloc_size(
|
||||
context->pool, context->buffer, new_size);
|
||||
|
||||
if (new_buffer) {
|
||||
context->buffer = new_buffer;
|
||||
context->length = new_size;
|
||||
@@ -233,7 +240,7 @@ static size_t oidc_json_parser_context_callback(char *ptr, size_t size,
|
||||
}
|
||||
|
||||
// Download a JSON file from the provided URI and return it in a jansson object
|
||||
static json_t *oidc_fetch_json_from_uri(void * pool, const char *uri)
|
||||
static json_t *oidc_fetch_json_from_uri(void *pool, const char *uri)
|
||||
{
|
||||
oidc_json_parser_context context = { pool, NULL, 0, 0 };
|
||||
json_t *json = NULL;
|
||||
@@ -250,55 +257,60 @@ static json_t *oidc_fetch_json_from_uri(void * pool, const char *uri)
|
||||
|
||||
curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s\n",
|
||||
uri);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s\n",
|
||||
uri);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
res = curl_easy_setopt(curl, CURLOPT_URL, uri);
|
||||
if (res != CURLE_OK) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
res =
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
|
||||
oidc_json_parser_context_callback);
|
||||
res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
|
||||
oidc_json_parser_context_callback);
|
||||
if (res != CURLE_OK) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &context);
|
||||
if (res != CURLE_OK) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
if (res != CURLE_OK) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: failed to download JSON document: URI %s, CURLcode %d\n",
|
||||
uri, res);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
json = json_loadb(context.buffer, context.offset, 0, &err);
|
||||
if (!json) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to parse JSON document: URI %s\n",
|
||||
uri);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: failed to parse JSON document: URI %s\n",
|
||||
uri);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (context.buffer) {
|
||||
talloc_free(context.buffer);
|
||||
}
|
||||
@@ -311,47 +323,50 @@ static json_t *oidc_fetch_json_from_uri(void * pool, const char *uri)
|
||||
}
|
||||
|
||||
// Download and parse the JWT keys for this virtual server context
|
||||
static bool oidc_fetch_oidc_keys(oidc_vctx_st * vctx)
|
||||
static bool oidc_fetch_oidc_keys(oidc_vctx_st *vctx)
|
||||
{
|
||||
bool result = false;
|
||||
json_t *jwks = NULL;
|
||||
json_t *oidc_config = NULL;
|
||||
json_t *openid_configuration_url =
|
||||
json_object_get(vctx->config, "openid_configuration_url");
|
||||
json_object_get(vctx->config, "openid_configuration_url");
|
||||
|
||||
json_t *array;
|
||||
size_t index;
|
||||
json_t *value;
|
||||
|
||||
if (!openid_configuration_url) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: openid_configuration_url missing from config\n");
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: openid_configuration_url missing from config\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
oidc_config =
|
||||
oidc_fetch_json_from_uri(vctx->pool,
|
||||
json_string_value
|
||||
(openid_configuration_url));
|
||||
oidc_config = oidc_fetch_json_from_uri(
|
||||
vctx->pool, json_string_value(openid_configuration_url));
|
||||
|
||||
if (!oidc_config) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: Unable to fetch config doc from %s\n", json_string_value(openid_configuration_url));
|
||||
"ocserv-oidc: Unable to fetch config doc from %s\n",
|
||||
json_string_value(openid_configuration_url));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
json_t *jwks_uri = json_object_get(oidc_config, "jwks_uri");
|
||||
|
||||
if (!jwks_uri || !json_string_value(jwks_uri)) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: jwks_uri missing from config doc\n");
|
||||
"ocserv-oidc: jwks_uri missing from config doc\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
jwks = oidc_fetch_json_from_uri(vctx->pool, json_string_value(jwks_uri));
|
||||
jwks = oidc_fetch_json_from_uri(vctx->pool,
|
||||
json_string_value(jwks_uri));
|
||||
if (!jwks) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"ocserv-oidc: failed to fetch keys from jwks_uri %s\n",
|
||||
json_string_value(jwks_uri));
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"ocserv-oidc: failed to fetch keys from jwks_uri %s\n",
|
||||
json_string_value(jwks_uri));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -362,12 +377,12 @@ static bool oidc_fetch_oidc_keys(oidc_vctx_st * vctx)
|
||||
}
|
||||
|
||||
// Log the keys obtained
|
||||
json_array_foreach(array, index, value) {
|
||||
json_array_foreach(array, index, value)
|
||||
{
|
||||
json_t *key_kid = json_object_get(value, "kid");
|
||||
oc_syslog(LOG_INFO,
|
||||
"ocserv-oidc: fetched new JWK %s\n",
|
||||
json_string_value(key_kid)
|
||||
);
|
||||
|
||||
oc_syslog(LOG_INFO, "ocserv-oidc: fetched new JWK %s\n",
|
||||
json_string_value(key_kid));
|
||||
}
|
||||
|
||||
if (vctx->jwks) {
|
||||
@@ -380,7 +395,7 @@ static bool oidc_fetch_oidc_keys(oidc_vctx_st * vctx)
|
||||
jwks = NULL;
|
||||
result = true;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (oidc_config) {
|
||||
json_decref(oidc_config);
|
||||
}
|
||||
@@ -391,7 +406,7 @@ static bool oidc_fetch_oidc_keys(oidc_vctx_st * vctx)
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool oidc_verify_lifetime(json_t * token_claims)
|
||||
static bool oidc_verify_lifetime(json_t *token_claims)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
@@ -402,38 +417,42 @@ static bool oidc_verify_lifetime(json_t * token_claims)
|
||||
time_t current_time = time(NULL);
|
||||
|
||||
if (!token_nbf || !json_integer_value(token_nbf)) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token missing 'nbf' claim\n");
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token missing 'nbf' claim\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!token_exp || !json_integer_value(token_exp)) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token missing 'exp' claim\n");
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token missing 'exp' claim\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!token_iat || !json_integer_value(token_iat)) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token missing 'iat' claim\n");
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token missing 'iat' claim\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Check to ensure the token is within it's validity
|
||||
if (json_integer_value(token_nbf) > current_time
|
||||
|| json_integer_value(token_exp) < current_time) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token not within validity period NBF: %lld EXP: %lld Current: %ld\n",
|
||||
json_integer_value(token_nbf),
|
||||
json_integer_value(token_exp), current_time);
|
||||
if (json_integer_value(token_nbf) > current_time ||
|
||||
json_integer_value(token_exp) < current_time) {
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"ocserv-oidc: Token not within validity period NBF: %lld EXP: %lld Current: %ld\n",
|
||||
json_integer_value(token_nbf),
|
||||
json_integer_value(token_exp), current_time);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool oidc_verify_required_claims(json_t * required_claims,
|
||||
json_t * token_claims)
|
||||
static bool oidc_verify_required_claims(json_t *required_claims,
|
||||
json_t *token_claims)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
@@ -443,36 +462,38 @@ static bool oidc_verify_required_claims(json_t * required_claims,
|
||||
|
||||
// Ensure all the required claims are present in the token
|
||||
json_object_foreach(required_claims, required_claim_name,
|
||||
required_claim_value) {
|
||||
required_claim_value)
|
||||
{
|
||||
token_claim_value =
|
||||
json_object_get(token_claims, required_claim_name);
|
||||
json_object_get(token_claims, required_claim_name);
|
||||
if (!json_equal(required_claim_value, token_claim_value)) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Required claim not met. Claim: %s Expected Value: %s\n",
|
||||
required_claim_name,
|
||||
json_string_value(required_claim_value));
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"ocserv-oidc: Required claim not met. Claim: %s Expected Value: %s\n",
|
||||
required_claim_name,
|
||||
json_string_value(required_claim_value));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool oidc_map_user_name(json_t * user_name_claim,
|
||||
json_t * token_claims,
|
||||
char user_name[MAX_USERNAME_SIZE])
|
||||
static bool oidc_map_user_name(json_t *user_name_claim, json_t *token_claims,
|
||||
char user_name[MAX_USERNAME_SIZE])
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// Pull the user name from the token
|
||||
json_t *token_user_name_claim =
|
||||
json_object_get(token_claims, json_string_value(user_name_claim));
|
||||
if (!token_user_name_claim || !json_string_value(token_user_name_claim)) {
|
||||
json_t *token_user_name_claim = json_object_get(
|
||||
token_claims, json_string_value(user_name_claim));
|
||||
if (!token_user_name_claim ||
|
||||
!json_string_value(token_user_name_claim)) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token missing '%s' claim\n",
|
||||
json_string_value(user_name_claim));
|
||||
json_string_value(user_name_claim));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -480,11 +501,11 @@ static bool oidc_map_user_name(json_t * user_name_claim,
|
||||
MAX_USERNAME_SIZE);
|
||||
result = true;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
return result;
|
||||
}
|
||||
|
||||
static json_t *oidc_extract_claims(cjose_jws_t * jws)
|
||||
static json_t *oidc_extract_claims(cjose_jws_t *jws)
|
||||
{
|
||||
cjose_err err;
|
||||
json_error_t json_err;
|
||||
@@ -493,26 +514,27 @@ static json_t *oidc_extract_claims(cjose_jws_t * jws)
|
||||
json_t *token_claims = NULL;
|
||||
|
||||
// Extract the claim portion from the token
|
||||
if (!cjose_jws_get_plaintext(jws, &plain_text, &plain_text_size, &err)) {
|
||||
if (!cjose_jws_get_plaintext(jws, &plain_text, &plain_text_size,
|
||||
&err)) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Failed to get plain text from token\n");
|
||||
"ocserv-oidc: Failed to get plain text from token\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Parse the claim JSON
|
||||
token_claims =
|
||||
json_loadb((char *)plain_text, plain_text_size, 0, &json_err);
|
||||
json_loadb((char *)plain_text, plain_text_size, 0, &json_err);
|
||||
if (!token_claims) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Failed to get claims from token\n");
|
||||
"ocserv-oidc: Failed to get claims from token\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
return token_claims;
|
||||
}
|
||||
|
||||
static bool oidc_verify_signature(oidc_vctx_st * vctx, cjose_jws_t * jws)
|
||||
static bool oidc_verify_signature(oidc_vctx_st *vctx, cjose_jws_t *jws)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
@@ -540,26 +562,31 @@ static bool oidc_verify_signature(oidc_vctx_st * vctx, cjose_jws_t * jws)
|
||||
token_header = cjose_jws_get_protected(jws);
|
||||
if (token_header == NULL) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token malformed - no header\n");
|
||||
"ocserv-oidc: Token malformed - no header\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Get the kid of the key used to sign this token
|
||||
token_kid = json_object_get(token_header, "kid");
|
||||
if (token_kid == NULL || !json_string_value(token_kid)) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token malformed - no kid\n");
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token malformed - no kid\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
token_typ = json_object_get(token_header, "typ");
|
||||
if (token_typ == NULL || !json_string_value(token_typ) || strcmp(json_string_value(token_typ), "JWT")) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token malformed - wrong typ claim\n");
|
||||
if (token_typ == NULL || !json_string_value(token_typ) ||
|
||||
strcmp(json_string_value(token_typ), "JWT")) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token malformed - wrong typ claim\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Find the signing key in the keys collection
|
||||
json_array_foreach(array, index, value) {
|
||||
json_array_foreach(array, index, value)
|
||||
{
|
||||
json_t *key_kid = json_object_get(value, "kid");
|
||||
|
||||
if (json_equal(key_kid, token_kid)) {
|
||||
jwk = cjose_jwk_import_json(value, &err);
|
||||
break;
|
||||
@@ -568,16 +595,20 @@ static bool oidc_verify_signature(oidc_vctx_st * vctx, cjose_jws_t * jws)
|
||||
|
||||
if (jwk == NULL) {
|
||||
time_t now;
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: JWK with kid=%s not found\n",
|
||||
json_string_value(token_kid));
|
||||
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: attempting to download new JWKs");
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: JWK with kid=%s not found\n",
|
||||
json_string_value(token_kid));
|
||||
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: attempting to download new JWKs");
|
||||
now = time(NULL);
|
||||
if ((now - vctx->last_jwks_load_time) > vctx->minimum_jwk_refresh_time) {
|
||||
if ((now - vctx->last_jwks_load_time) >
|
||||
vctx->minimum_jwk_refresh_time) {
|
||||
oidc_fetch_oidc_keys(vctx);
|
||||
}
|
||||
else {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: skipping JWK refresh");
|
||||
} else {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: skipping JWK refresh");
|
||||
}
|
||||
|
||||
// Fail the request and let the client try again.
|
||||
@@ -585,14 +616,15 @@ static bool oidc_verify_signature(oidc_vctx_st * vctx, cjose_jws_t * jws)
|
||||
}
|
||||
|
||||
if (!cjose_jws_verify(jws, jwk, &err)) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token failed validation %s\n",
|
||||
err.message);
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token failed validation %s\n",
|
||||
err.message);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (jwk) {
|
||||
cjose_jwk_release(jwk);
|
||||
}
|
||||
@@ -601,9 +633,9 @@ static bool oidc_verify_signature(oidc_vctx_st * vctx, cjose_jws_t * jws)
|
||||
}
|
||||
|
||||
// Verify that the provided token is signed
|
||||
static bool oidc_verify_token(oidc_vctx_st * vctx, const char *token,
|
||||
size_t token_length,
|
||||
char user_name[MAX_USERNAME_SIZE])
|
||||
static bool oidc_verify_token(oidc_vctx_st *vctx, const char *token,
|
||||
size_t token_length,
|
||||
char user_name[MAX_USERNAME_SIZE])
|
||||
{
|
||||
bool result = false;
|
||||
cjose_err err;
|
||||
@@ -613,47 +645,49 @@ static bool oidc_verify_token(oidc_vctx_st * vctx, const char *token,
|
||||
jws = cjose_jws_import(token, token_length, &err);
|
||||
if (jws == NULL) {
|
||||
oc_syslog(LOG_NOTICE, "ocserv-oidc: Token malformed - %s\n",
|
||||
err.message);
|
||||
err.message);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!oidc_verify_signature(vctx, jws)) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token signature validation failed\n");
|
||||
"ocserv-oidc: Token signature validation failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
token_claims = oidc_extract_claims(jws);
|
||||
if (!token_claims) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Unable to access token claims\n");
|
||||
"ocserv-oidc: Unable to access token claims\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!oidc_verify_lifetime(token_claims)) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token lifetime validation failed\n");
|
||||
"ocserv-oidc: Token lifetime validation failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!oidc_verify_required_claims
|
||||
(json_object_get(vctx->config, "required_claims"), token_claims)) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Token required claims validation failed\n");
|
||||
if (!oidc_verify_required_claims(json_object_get(vctx->config,
|
||||
"required_claims"),
|
||||
token_claims)) {
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"ocserv-oidc: Token required claims validation failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!oidc_map_user_name
|
||||
(json_object_get(vctx->config, "user_name_claim"), token_claims,
|
||||
user_name)) {
|
||||
if (!oidc_map_user_name(json_object_get(vctx->config,
|
||||
"user_name_claim"),
|
||||
token_claims, user_name)) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"ocserv-oidc: Unable to map user name claim\n");
|
||||
"ocserv-oidc: Unable to map user name claim\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = true;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (jws) {
|
||||
cjose_jws_release(jws);
|
||||
}
|
||||
|
||||
142
src/auth/pam.c
142
src/auth/pam.c
@@ -48,7 +48,7 @@
|
||||
#include "auth/pam.h"
|
||||
#include "auth-unix.h"
|
||||
|
||||
#define PAM_STACK_SIZE (1024*1024)
|
||||
#define PAM_STACK_SIZE (1024 * 1024)
|
||||
|
||||
#define MAX_REPLIES 2
|
||||
|
||||
@@ -59,10 +59,10 @@ enum {
|
||||
};
|
||||
|
||||
static int ocserv_conv(int msg_size, const struct pam_message **msg,
|
||||
struct pam_response **resp, void *uptr)
|
||||
struct pam_response **resp, void *uptr)
|
||||
{
|
||||
struct pam_ctx_st * pctx = uptr;
|
||||
unsigned i;
|
||||
struct pam_ctx_st *pctx = uptr;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (msg_size == 0)
|
||||
@@ -70,15 +70,16 @@ static int ocserv_conv(int msg_size, const struct pam_message **msg,
|
||||
|
||||
str_reset(&pctx->msg);
|
||||
|
||||
pctx->replies = calloc(1, msg_size*sizeof(*pctx->replies));
|
||||
pctx->replies = calloc(1, msg_size * sizeof(*pctx->replies));
|
||||
if (pctx->replies == NULL)
|
||||
return PAM_BUF_ERR;
|
||||
|
||||
for (i=0;i<msg_size;i++) {
|
||||
for (i = 0; i < msg_size; i++) {
|
||||
switch (msg[i]->msg_style) {
|
||||
case PAM_ERROR_MSG:
|
||||
case PAM_TEXT_INFO:
|
||||
oc_syslog(LOG_DEBUG, "PAM-auth conv info: %s", msg[i]->msg);
|
||||
oc_syslog(LOG_DEBUG, "PAM-auth conv info: %s",
|
||||
msg[i]->msg);
|
||||
|
||||
// That should never happen, but also not a big deal if we fail to add message here.
|
||||
// coverity[check_return : FALSE]
|
||||
@@ -87,7 +88,8 @@ static int ocserv_conv(int msg_size, const struct pam_message **msg,
|
||||
ret = str_append_data(&pctx->msg, " ", 1);
|
||||
|
||||
if (ret < 0) {
|
||||
oc_syslog(LOG_ERR, "Error in memory allocation in PAM");
|
||||
oc_syslog(LOG_ERR,
|
||||
"Error in memory allocation in PAM");
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
|
||||
@@ -99,18 +101,24 @@ static int ocserv_conv(int msg_size, const struct pam_message **msg,
|
||||
/* no message, just asking for password */
|
||||
str_reset(&pctx->msg);
|
||||
pctx->sent_msg = 1;
|
||||
|
||||
}
|
||||
|
||||
if (msg[i]->msg) {
|
||||
ret = str_append_str(&pctx->msg, msg[i]->msg);
|
||||
if (ret < 0) {
|
||||
oc_syslog(LOG_ERR, "Error in memory allocation in PAM");
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"Error in memory allocation in PAM");
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
oc_syslog(LOG_DEBUG, "PAM-auth conv: echo-%s, msg: '%s'", (msg[i]->msg_style==PAM_PROMPT_ECHO_ON)?"on":"off", msg[i]->msg!=NULL?msg[i]->msg:"");
|
||||
oc_syslog(LOG_DEBUG,
|
||||
"PAM-auth conv: echo-%s, msg: '%s'",
|
||||
(msg[i]->msg_style == PAM_PROMPT_ECHO_ON) ?
|
||||
"on" :
|
||||
"off",
|
||||
msg[i]->msg != NULL ? msg[i]->msg : "");
|
||||
|
||||
pctx->state = PAM_S_WAIT_FOR_PASS;
|
||||
pctx->cr_ret = PAM_SUCCESS;
|
||||
@@ -120,13 +128,15 @@ static int ocserv_conv(int msg_size, const struct pam_message **msg,
|
||||
if (pctx->password[0] != 0) {
|
||||
pctx->replies[i].resp = strdup(pctx->password);
|
||||
if (pctx->replies[i].resp == NULL) {
|
||||
oc_syslog(LOG_ERR, "Error in memory allocation in PAM");
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"Error in memory allocation in PAM");
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
}
|
||||
pctx->sent_msg = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*resp = pctx->replies;
|
||||
@@ -134,16 +144,17 @@ static int ocserv_conv(int msg_size, const struct pam_message **msg,
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
static void co_auth_user(void* data)
|
||||
static void co_auth_user(void *data)
|
||||
{
|
||||
struct pam_ctx_st * pctx = data;
|
||||
int pret;
|
||||
struct pam_ctx_st *pctx = data;
|
||||
int pret;
|
||||
|
||||
pctx->state = PAM_S_INIT;
|
||||
|
||||
pret = pam_authenticate(pctx->ph, 0);
|
||||
if (pret != PAM_SUCCESS) {
|
||||
oc_syslog(LOG_INFO, "PAM authenticate error for '%s': %s", pctx->username, pam_strerror(pctx->ph, pret));
|
||||
oc_syslog(LOG_INFO, "PAM authenticate error for '%s': %s",
|
||||
pctx->username, pam_strerror(pctx->ph, pret));
|
||||
pctx->cr_ret = pret;
|
||||
goto wait;
|
||||
}
|
||||
@@ -151,14 +162,18 @@ int pret;
|
||||
pret = pam_acct_mgmt(pctx->ph, 0);
|
||||
if (pret == PAM_NEW_AUTHTOK_REQD) {
|
||||
/* change password */
|
||||
oc_syslog(LOG_INFO, "Password for user '%s' is expired. Attempting to update...", pctx->username);
|
||||
oc_syslog(
|
||||
LOG_INFO,
|
||||
"Password for user '%s' is expired. Attempting to update...",
|
||||
pctx->username);
|
||||
|
||||
pctx->changing = 1;
|
||||
pret = pam_chauthtok(pctx->ph, PAM_CHANGE_EXPIRED_AUTHTOK);
|
||||
}
|
||||
|
||||
if (pret != PAM_SUCCESS) {
|
||||
oc_syslog(LOG_INFO, "PAM acct-mgmt error for '%s': %s", pctx->username, pam_strerror(pctx->ph, pret));
|
||||
oc_syslog(LOG_INFO, "PAM acct-mgmt error for '%s': %s",
|
||||
pctx->username, pam_strerror(pctx->ph, pret));
|
||||
pctx->cr_ret = pret;
|
||||
goto wait;
|
||||
}
|
||||
@@ -166,21 +181,21 @@ int pret;
|
||||
pctx->state = PAM_S_COMPLETE;
|
||||
pctx->cr_ret = PAM_SUCCESS;
|
||||
|
||||
wait:
|
||||
wait:
|
||||
/* give control back to the main process */
|
||||
while (1) {
|
||||
co_resume();
|
||||
}
|
||||
}
|
||||
|
||||
static int pam_auth_init(void** ctx, void *pool, void *vctx, const common_auth_init_st *info)
|
||||
static int pam_auth_init(void **ctx, void *pool, void *vctx,
|
||||
const common_auth_init_st *info)
|
||||
{
|
||||
int pret;
|
||||
struct pam_ctx_st * pctx;
|
||||
int pret;
|
||||
struct pam_ctx_st *pctx;
|
||||
|
||||
if (info->username == NULL || info->username[0] == 0) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"pam-auth: no username present");
|
||||
oc_syslog(LOG_NOTICE, "pam-auth: no username present");
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
@@ -194,7 +209,8 @@ struct pam_ctx_st * pctx;
|
||||
pctx->dc.appdata_ptr = pctx;
|
||||
pret = pam_start(PACKAGE, info->username, &pctx->dc, &pctx->ph);
|
||||
if (pret != PAM_SUCCESS) {
|
||||
oc_syslog(LOG_NOTICE, "PAM-auth init: %s", pam_strerror(pctx->ph, pret));
|
||||
oc_syslog(LOG_NOTICE, "PAM-auth init: %s",
|
||||
pam_strerror(pctx->ph, pret));
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
@@ -218,10 +234,10 @@ fail1:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int pam_auth_msg(void* ctx, void *pool, passwd_msg_st *pst)
|
||||
static int pam_auth_msg(void *ctx, void *pool, passwd_msg_st *pst)
|
||||
{
|
||||
struct pam_ctx_st * pctx = ctx;
|
||||
size_t prompt_hash = 0;
|
||||
struct pam_ctx_st *pctx = ctx;
|
||||
size_t prompt_hash = 0;
|
||||
|
||||
if (pctx->state != PAM_S_INIT && pctx->state != PAM_S_WAIT_FOR_PASS) {
|
||||
return 0;
|
||||
@@ -233,22 +249,24 @@ size_t prompt_hash = 0;
|
||||
co_call(pctx->cr);
|
||||
|
||||
if (pctx->cr_ret != PAM_SUCCESS) {
|
||||
oc_syslog(LOG_NOTICE, "PAM-auth pam_auth_msg: %s", pam_strerror(pctx->ph, pctx->cr_ret));
|
||||
oc_syslog(LOG_NOTICE, "PAM-auth pam_auth_msg: %s",
|
||||
pam_strerror(pctx->ph, pctx->cr_ret));
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx->msg.length == 0) {
|
||||
if (pctx->changing)
|
||||
pst->msg_str = talloc_strdup(pool, "Please enter the new password.");
|
||||
/* else use the default prompt */
|
||||
if (pctx->changing)
|
||||
pst->msg_str = talloc_strdup(
|
||||
pool, "Please enter the new password.");
|
||||
/* else use the default prompt */
|
||||
} else {
|
||||
if (str_append_data(&pctx->msg, "\0", 1) < 0)
|
||||
return -1;
|
||||
|
||||
prompt_hash = hash_any(pctx->msg.data, pctx->msg.length, 0);
|
||||
|
||||
pst->msg_str = talloc_strdup(pool, (char*)pctx->msg.data);
|
||||
pst->msg_str = talloc_strdup(pool, (char *)pctx->msg.data);
|
||||
}
|
||||
|
||||
pst->counter = pctx->passwd_counter;
|
||||
@@ -265,15 +283,18 @@ size_t prompt_hash = 0;
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated
|
||||
*/
|
||||
static int pam_auth_pass(void* ctx, const char* pass, unsigned pass_len)
|
||||
static int pam_auth_pass(void *ctx, const char *pass, unsigned int pass_len)
|
||||
{
|
||||
struct pam_ctx_st * pctx = ctx;
|
||||
struct pam_ctx_st *pctx = ctx;
|
||||
|
||||
if (pass == NULL || pass_len+1 > sizeof(pctx->password))
|
||||
if (pass == NULL || pass_len + 1 > sizeof(pctx->password))
|
||||
return -1;
|
||||
|
||||
if (pctx->state != PAM_S_WAIT_FOR_PASS) {
|
||||
oc_syslog(LOG_NOTICE, "PAM auth: conversation left in wrong state (%d/expecting %d)", pctx->state, PAM_S_WAIT_FOR_PASS);
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"PAM auth: conversation left in wrong state (%d/expecting %d)",
|
||||
pctx->state, PAM_S_WAIT_FOR_PASS);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
@@ -284,7 +305,8 @@ struct pam_ctx_st * pctx = ctx;
|
||||
co_call(pctx->cr);
|
||||
|
||||
if (pctx->cr_ret != PAM_SUCCESS) {
|
||||
oc_syslog(LOG_NOTICE, "PAM-auth pam_auth_pass: %s", pam_strerror(pctx->ph, pctx->cr_ret));
|
||||
oc_syslog(LOG_NOTICE, "PAM-auth pam_auth_pass: %s",
|
||||
pam_strerror(pctx->ph, pctx->cr_ret));
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
@@ -296,18 +318,20 @@ struct pam_ctx_st * pctx = ctx;
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated
|
||||
*/
|
||||
static int pam_auth_group(void* ctx, const char *suggested, char *groupname, int groupname_size)
|
||||
static int pam_auth_group(void *ctx, const char *suggested, char *groupname,
|
||||
int groupname_size)
|
||||
{
|
||||
struct pam_ctx_st * pctx = ctx;
|
||||
struct pam_ctx_st *pctx = ctx;
|
||||
|
||||
return get_user_auth_group(pctx->username, suggested, groupname, groupname_size);
|
||||
return get_user_auth_group(pctx->username, suggested, groupname,
|
||||
groupname_size);
|
||||
}
|
||||
|
||||
static int pam_auth_user(void* ctx, char *username, int username_size)
|
||||
static int pam_auth_user(void *ctx, char *username, int username_size)
|
||||
{
|
||||
const char* user = NULL;
|
||||
struct pam_ctx_st * pctx = ctx;
|
||||
int pret;
|
||||
const char *user = NULL;
|
||||
struct pam_ctx_st *pctx = ctx;
|
||||
int pret;
|
||||
|
||||
username[0] = 0;
|
||||
|
||||
@@ -326,9 +350,9 @@ int pret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void pam_auth_deinit(void* ctx)
|
||||
static void pam_auth_deinit(void *ctx)
|
||||
{
|
||||
struct pam_ctx_st * pctx = ctx;
|
||||
struct pam_ctx_st *pctx = ctx;
|
||||
|
||||
pam_end(pctx->ph, pctx->cr_ret);
|
||||
free(pctx->replies);
|
||||
@@ -338,7 +362,8 @@ struct pam_ctx_st * pctx = ctx;
|
||||
talloc_free(pctx);
|
||||
}
|
||||
|
||||
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 int *groupname_size)
|
||||
{
|
||||
struct pam_cfg_st *config = _additional;
|
||||
gid_t min = 0;
|
||||
@@ -349,15 +374,14 @@ static void pam_group_list(void *pool, void *_additional, char ***groupname, uns
|
||||
unix_group_list(pool, min, groupname, groupname_size);
|
||||
}
|
||||
|
||||
const struct auth_mod_st pam_auth_funcs = {
|
||||
.type = AUTH_TYPE_PAM | AUTH_TYPE_USERNAME_PASS,
|
||||
.auth_init = pam_auth_init,
|
||||
.auth_deinit = pam_auth_deinit,
|
||||
.auth_msg = pam_auth_msg,
|
||||
.auth_pass = pam_auth_pass,
|
||||
.auth_group = pam_auth_group,
|
||||
.auth_user = pam_auth_user,
|
||||
.group_list = pam_group_list
|
||||
};
|
||||
const struct auth_mod_st pam_auth_funcs = { .type = AUTH_TYPE_PAM |
|
||||
AUTH_TYPE_USERNAME_PASS,
|
||||
.auth_init = pam_auth_init,
|
||||
.auth_deinit = pam_auth_deinit,
|
||||
.auth_msg = pam_auth_msg,
|
||||
.auth_pass = pam_auth_pass,
|
||||
.auth_group = pam_auth_group,
|
||||
.auth_user = pam_auth_user,
|
||||
.group_list = pam_group_list };
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,17 +35,17 @@ extern const struct auth_mod_st pam_auth_funcs;
|
||||
struct pam_ctx_st {
|
||||
char password[MAX_PASSWORD_SIZE];
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
pam_handle_t * ph;
|
||||
pam_handle_t *ph;
|
||||
struct pam_conv dc;
|
||||
coroutine_t cr;
|
||||
int cr_ret;
|
||||
unsigned changing; /* whether we are entering a new password */
|
||||
unsigned int changing; /* whether we are entering a new password */
|
||||
str_st msg;
|
||||
str_st prompt;
|
||||
unsigned sent_msg;
|
||||
unsigned int sent_msg;
|
||||
struct pam_response *replies; /* for safety */
|
||||
unsigned state; /* PAM_S_ */
|
||||
unsigned passwd_counter;
|
||||
unsigned int state; /* PAM_S_ */
|
||||
unsigned int passwd_counter;
|
||||
size_t prev_prompt_hash;
|
||||
};
|
||||
|
||||
|
||||
160
src/auth/plain.c
160
src/auth/plain.c
@@ -31,12 +31,12 @@
|
||||
#include <ccan/htable/htable.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
#ifdef HAVE_LIBOATH
|
||||
# include <liboath/oath.h>
|
||||
#include <liboath/oath.h>
|
||||
#endif
|
||||
#ifdef HAVE_CRYPT_H
|
||||
/* libcrypt in Fedora28 does not provide prototype
|
||||
/* libcrypt in Fedora28 does not provide prototype
|
||||
* in unistd.h */
|
||||
# include <crypt.h>
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
#include "log.h"
|
||||
|
||||
@@ -45,14 +45,14 @@
|
||||
|
||||
struct plain_ctx_st {
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
char cpass[MAX_CPASS_SIZE]; /* crypt() passwd */
|
||||
char cpass[MAX_CPASS_SIZE]; /* crypt() passwd */
|
||||
|
||||
char *groupnames[MAX_GROUPS];
|
||||
unsigned groupnames_size;
|
||||
unsigned int groupnames_size;
|
||||
|
||||
const char *pass_msg;
|
||||
unsigned retries;
|
||||
unsigned failed; /* non-zero if the username is wrong */
|
||||
unsigned int retries;
|
||||
unsigned int failed; /* non-zero if the username is wrong */
|
||||
|
||||
const struct plain_cfg_st *config;
|
||||
};
|
||||
@@ -68,7 +68,7 @@ static void plain_vhost_init(void **vctx, void *pool, void *additional)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
*vctx = (void*)config;
|
||||
*vctx = (void *)config;
|
||||
|
||||
#ifdef HAVE_LIBOATH
|
||||
oath_init();
|
||||
@@ -78,13 +78,13 @@ static void plain_vhost_init(void **vctx, void *pool, void *additional)
|
||||
/* Breaks a list of "xxx", "yyy", to a character array, of
|
||||
* MAX_COMMA_SEP_ELEMENTS size; Note that the given string is modified.
|
||||
*/
|
||||
static void
|
||||
break_group_list(void *pool, char *text,
|
||||
char *broken_text[MAX_GROUPS], unsigned *elements)
|
||||
static void break_group_list(void *pool, char *text,
|
||||
char *broken_text[MAX_GROUPS],
|
||||
unsigned int *elements)
|
||||
{
|
||||
char *p = talloc_strdup(pool, text);
|
||||
char *p2;
|
||||
unsigned len;
|
||||
unsigned int len;
|
||||
|
||||
*elements = 0;
|
||||
|
||||
@@ -98,16 +98,16 @@ break_group_list(void *pool, char *text,
|
||||
p = strchr(p, ',');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
len = p - broken_text[*elements-1];
|
||||
len = p - broken_text[*elements - 1];
|
||||
|
||||
/* remove any trailing space */
|
||||
p2 = p-1;
|
||||
p2 = p - 1;
|
||||
while (isspace(*p2)) {
|
||||
*p2 = 0;
|
||||
p2--;
|
||||
}
|
||||
|
||||
p++; /* move to next entry and skip white
|
||||
p++; /* move to next entry and skip white
|
||||
* space.
|
||||
*/
|
||||
while (isspace(*p))
|
||||
@@ -118,7 +118,7 @@ break_group_list(void *pool, char *text,
|
||||
(*elements)--;
|
||||
}
|
||||
} else {
|
||||
p2 = strrchr(broken_text[(*elements)-1], ' ');
|
||||
p2 = strrchr(broken_text[(*elements) - 1], ' ');
|
||||
if (p2 != NULL) {
|
||||
while (isspace(*p2)) {
|
||||
*p2 = 0;
|
||||
@@ -126,13 +126,12 @@ break_group_list(void *pool, char *text,
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(broken_text[(*elements)-1]) == 1) {
|
||||
if (strlen(broken_text[(*elements) - 1]) == 1) {
|
||||
/* skip the group */
|
||||
(*elements)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (p != NULL && *elements < MAX_GROUPS);
|
||||
} while (p != NULL && *elements < MAX_GROUPS);
|
||||
}
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name.
|
||||
@@ -155,13 +154,13 @@ static int read_auth_pass(struct plain_ctx_st *pctx)
|
||||
fp = fopen(pctx->config->passwd, "r");
|
||||
if (fp == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"error in plain authentication; cannot open: %s",
|
||||
pctx->config->passwd);
|
||||
"error in plain authentication; cannot open: %s",
|
||||
pctx->config->passwd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
line[sizeof(line)-1] = 0;
|
||||
while ((p=fgets(line, sizeof(line)-1, fp)) != NULL) {
|
||||
line[sizeof(line) - 1] = 0;
|
||||
while ((p = fgets(line, sizeof(line) - 1, fp)) != NULL) {
|
||||
ll = strlen(p);
|
||||
|
||||
if (ll <= 4)
|
||||
@@ -182,11 +181,13 @@ static int read_auth_pass(struct plain_ctx_st *pctx)
|
||||
if (p != NULL && strcmp(pctx->username, p) == 0) {
|
||||
p = strsep(&sp, ":");
|
||||
if (p != NULL) {
|
||||
break_group_list(pctx, p, pctx->groupnames, &pctx->groupnames_size);
|
||||
break_group_list(pctx, p, pctx->groupnames,
|
||||
&pctx->groupnames_size);
|
||||
|
||||
p = strsep(&sp, ":");
|
||||
if (p != NULL) {
|
||||
strlcpy(pctx->cpass, p, sizeof(pctx->cpass));
|
||||
strlcpy(pctx->cpass, p,
|
||||
sizeof(pctx->cpass));
|
||||
pctx->failed = 0;
|
||||
ret = 0;
|
||||
goto exit;
|
||||
@@ -200,11 +201,13 @@ static int read_auth_pass(struct plain_ctx_st *pctx)
|
||||
if (p != NULL && strcmp(pctx->username, p) == 0) {
|
||||
p = strtok_r(NULL, ":", &sp);
|
||||
if (p != NULL) {
|
||||
break_group_list(pctx, p, pctx->groupnames, &pctx->groupnames_size);
|
||||
break_group_list(pctx, p, pctx->groupnames,
|
||||
&pctx->groupnames_size);
|
||||
|
||||
p = strtok_r(NULL, ":", &sp);
|
||||
if (p != NULL) {
|
||||
strlcpy(pctx->cpass, p, sizeof(pctx->cpass));
|
||||
strlcpy(pctx->cpass, p,
|
||||
sizeof(pctx->cpass));
|
||||
pctx->failed = 0;
|
||||
ret = 0;
|
||||
goto exit;
|
||||
@@ -216,20 +219,20 @@ static int read_auth_pass(struct plain_ctx_st *pctx)
|
||||
|
||||
/* always succeed */
|
||||
ret = 0;
|
||||
exit:
|
||||
exit:
|
||||
safe_memset(line, 0, sizeof(line));
|
||||
fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int plain_auth_init(void **ctx, void *pool, void *vctx, const common_auth_init_st *info)
|
||||
static int plain_auth_init(void **ctx, void *pool, void *vctx,
|
||||
const common_auth_init_st *info)
|
||||
{
|
||||
struct plain_ctx_st *pctx;
|
||||
int ret;
|
||||
|
||||
if (info->username == NULL || info->username[0] == 0) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"plain-auth: no username present");
|
||||
oc_syslog(LOG_ERR, "plain-auth: no username present");
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
@@ -262,26 +265,29 @@ static int plain_auth_init(void **ctx, void *pool, void *vctx, const common_auth
|
||||
return ERR_AUTH_CONTINUE;
|
||||
}
|
||||
|
||||
static int plain_auth_group(void *ctx, const char *suggested, char *groupname, int groupname_size)
|
||||
static int plain_auth_group(void *ctx, const char *suggested, char *groupname,
|
||||
int groupname_size)
|
||||
{
|
||||
struct plain_ctx_st *pctx = ctx;
|
||||
unsigned i, found = 0;
|
||||
unsigned int i, found = 0;
|
||||
|
||||
groupname[0] = 0;
|
||||
|
||||
if (suggested != NULL) {
|
||||
for (i=0;i<pctx->groupnames_size;i++) {
|
||||
for (i = 0; i < pctx->groupnames_size; i++) {
|
||||
if (strcmp(suggested, pctx->groupnames[i]) == 0) {
|
||||
strlcpy(groupname, pctx->groupnames[i], groupname_size);
|
||||
strlcpy(groupname, pctx->groupnames[i],
|
||||
groupname_size);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"user '%s' requested group '%s' but is not a member",
|
||||
pctx->username, suggested);
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"user '%s' requested group '%s' but is not a member",
|
||||
pctx->username, suggested);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -300,7 +306,7 @@ static int plain_auth_user(void *ctx, char *username, int username_size)
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name.
|
||||
*/
|
||||
static int plain_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
static int plain_auth_pass(void *ctx, const char *pass, unsigned int pass_len)
|
||||
{
|
||||
struct plain_ctx_st *pctx = ctx;
|
||||
const char *p;
|
||||
@@ -314,21 +320,22 @@ static int plain_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
}
|
||||
|
||||
if (pctx->failed) {
|
||||
if (pctx->retries++ < MAX_PASSWORD_TRIES-1) {
|
||||
if (pctx->retries++ < MAX_PASSWORD_TRIES - 1) {
|
||||
pctx->pass_msg = pass_msg_failed;
|
||||
return ERR_AUTH_CONTINUE;
|
||||
} else {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"plain-auth: error authenticating user '%s'",
|
||||
pctx->username);
|
||||
"plain-auth: error authenticating user '%s'",
|
||||
pctx->username);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pctx->cpass[0] == 0 && pctx->config->otp_file == NULL) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"plain-auth: user '%s' has empty password and no OTP file configured",
|
||||
pctx->username);
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"plain-auth: user '%s' has empty password and no OTP file configured",
|
||||
pctx->username);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
@@ -344,12 +351,13 @@ static int plain_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
}
|
||||
|
||||
/* no primary password -> check OTP */
|
||||
ret = oath_authenticate_usersfile(pctx->config->otp_file, pctx->username,
|
||||
pass, HOTP_WINDOW, NULL, &last);
|
||||
ret = oath_authenticate_usersfile(pctx->config->otp_file,
|
||||
pctx->username, pass,
|
||||
HOTP_WINDOW, NULL, &last);
|
||||
if (ret != OATH_OK) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"plain-auth: OTP auth failed for '%s': %s",
|
||||
pctx->username, oath_strerror(ret));
|
||||
"plain-auth: OTP auth failed for '%s': %s",
|
||||
pctx->username, oath_strerror(ret));
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
}
|
||||
@@ -381,10 +389,11 @@ static void plain_auth_deinit(void *ctx)
|
||||
static size_t rehash(const void *_e, void *unused)
|
||||
{
|
||||
const char *e = _e;
|
||||
|
||||
return hash_any(e, strlen(e), 0);
|
||||
}
|
||||
|
||||
static bool str_cmp(const void* _c1, void* _c2)
|
||||
static bool str_cmp(const void *_c1, void *_c2)
|
||||
{
|
||||
const char *c1 = _c1, *c2 = _c2;
|
||||
|
||||
@@ -393,17 +402,18 @@ static bool str_cmp(const void* _c1, void* _c2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void plain_group_list(void *pool, void *additional, char ***groupname, unsigned *groupname_size)
|
||||
static void plain_group_list(void *pool, void *additional, char ***groupname,
|
||||
unsigned int *groupname_size)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[512];
|
||||
ssize_t ll;
|
||||
char *p, *sp;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
size_t hval;
|
||||
struct htable_iter iter;
|
||||
char *tgroup[MAX_GROUPS];
|
||||
unsigned tgroup_size;
|
||||
unsigned int tgroup_size;
|
||||
struct htable hash;
|
||||
struct plain_cfg_st *config = additional;
|
||||
|
||||
@@ -413,13 +423,13 @@ static void plain_group_list(void *pool, void *additional, char ***groupname, un
|
||||
fp = fopen(config->passwd, "r");
|
||||
if (fp == NULL) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"error in plain authentication; cannot open: %s",
|
||||
(char*)config->passwd);
|
||||
"error in plain authentication; cannot open: %s",
|
||||
(char *)config->passwd);
|
||||
return;
|
||||
}
|
||||
|
||||
line[sizeof(line)-1] = 0;
|
||||
while ((p=fgets(line, sizeof(line)-1, fp)) != NULL) {
|
||||
line[sizeof(line) - 1] = 0;
|
||||
while ((p = fgets(line, sizeof(line) - 1, fp)) != NULL) {
|
||||
ll = strlen(p);
|
||||
|
||||
if (ll <= 4)
|
||||
@@ -449,12 +459,15 @@ static void plain_group_list(void *pool, void *additional, char ***groupname, un
|
||||
if (p != NULL) {
|
||||
break_group_list(pool, p, tgroup, &tgroup_size);
|
||||
|
||||
for (i=0;i<tgroup_size;i++) {
|
||||
for (i = 0; i < tgroup_size; i++) {
|
||||
hval = rehash(tgroup[i], NULL);
|
||||
|
||||
if (htable_get(&hash, hval, str_cmp, tgroup[i]) == NULL) {
|
||||
if (htable_get(&hash, hval, str_cmp,
|
||||
tgroup[i]) == NULL) {
|
||||
if (strlen(tgroup[i]) > 1)
|
||||
(void)htable_add(&hash, hval, tgroup[i]);
|
||||
(void)htable_add(
|
||||
&hash, hval,
|
||||
tgroup[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -462,7 +475,7 @@ static void plain_group_list(void *pool, void *additional, char ***groupname, un
|
||||
}
|
||||
|
||||
*groupname_size = 0;
|
||||
*groupname = talloc_size(pool, sizeof(char*)*MAX_GROUPS);
|
||||
*groupname = talloc_size(pool, sizeof(char *) * MAX_GROUPS);
|
||||
if (*groupname == NULL) {
|
||||
goto exit;
|
||||
}
|
||||
@@ -475,21 +488,20 @@ static void plain_group_list(void *pool, void *additional, char ***groupname, un
|
||||
}
|
||||
|
||||
/* always succeed */
|
||||
exit:
|
||||
exit:
|
||||
htable_clear(&hash);
|
||||
safe_memset(line, 0, sizeof(line));
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
const struct auth_mod_st plain_auth_funcs = {
|
||||
.type = AUTH_TYPE_PLAIN | AUTH_TYPE_USERNAME_PASS,
|
||||
.allows_retries = 1,
|
||||
.vhost_init = plain_vhost_init,
|
||||
.auth_init = plain_auth_init,
|
||||
.auth_deinit = plain_auth_deinit,
|
||||
.auth_msg = plain_auth_msg,
|
||||
.auth_pass = plain_auth_pass,
|
||||
.auth_user = plain_auth_user,
|
||||
.auth_group = plain_auth_group,
|
||||
.group_list = plain_group_list
|
||||
};
|
||||
const struct auth_mod_st plain_auth_funcs = { .type = AUTH_TYPE_PLAIN |
|
||||
AUTH_TYPE_USERNAME_PASS,
|
||||
.allows_retries = 1,
|
||||
.vhost_init = plain_vhost_init,
|
||||
.auth_init = plain_auth_init,
|
||||
.auth_deinit = plain_auth_deinit,
|
||||
.auth_msg = plain_auth_msg,
|
||||
.auth_pass = plain_auth_pass,
|
||||
.auth_user = plain_auth_user,
|
||||
.auth_group = plain_auth_group,
|
||||
.group_list = plain_group_list };
|
||||
|
||||
@@ -36,39 +36,40 @@
|
||||
#include "common-config.h"
|
||||
|
||||
#ifdef LEGACY_RADIUS
|
||||
# include <freeradius-client.h>
|
||||
#include <freeradius-client.h>
|
||||
#else
|
||||
# include <radcli/radcli.h>
|
||||
#include <radcli/radcli.h>
|
||||
#endif
|
||||
|
||||
#ifndef VENDOR_BIT_SIZE
|
||||
# define VENDOR_BIT_SIZE 16
|
||||
# define VENDOR_MASK 0xffff
|
||||
#define VENDOR_BIT_SIZE 16
|
||||
#define VENDOR_MASK 0xffff
|
||||
#else
|
||||
# define VENDOR_MASK 0xffffffff
|
||||
#define VENDOR_MASK 0xffffffff
|
||||
#endif
|
||||
|
||||
#define VATTRID_SET(a,v) ((a)|((uint64_t)((v)&VENDOR_MASK)) << VENDOR_BIT_SIZE)
|
||||
#define VATTRID_SET(a, v) \
|
||||
((a) | ((uint64_t)((v) & VENDOR_MASK)) << VENDOR_BIT_SIZE)
|
||||
|
||||
#define RAD_GROUP_NAME PW_CLASS
|
||||
/* Microsoft - RFC 2548 */
|
||||
#define MS_PRIMARY_DNS_SERVER VATTRID_SET(28, 311)
|
||||
#define MS_SECONDARY_DNS_SERVER VATTRID_SET(29, 311)
|
||||
/* Roaring Penguin */
|
||||
#define RP_UPSTREAM_SPEED_LIMIT VATTRID_SET(1, 10055)
|
||||
#define RP_UPSTREAM_SPEED_LIMIT VATTRID_SET(1, 10055)
|
||||
#define RP_DOWNSTREAM_SPEED_LIMIT VATTRID_SET(2, 10055)
|
||||
|
||||
#if defined(LEGACY_RADIUS)
|
||||
# ifndef PW_DELEGATED_IPV6_PREFIX
|
||||
# define PW_DELEGATED_IPV6_PREFIX 123
|
||||
# endif
|
||||
# ifndef PW_ACCT_INTERIM_INTERVAL
|
||||
# define PW_ACCT_INTERIM_INTERVAL 85
|
||||
# endif
|
||||
#ifndef PW_DELEGATED_IPV6_PREFIX
|
||||
#define PW_DELEGATED_IPV6_PREFIX 123
|
||||
#endif
|
||||
#ifndef PW_ACCT_INTERIM_INTERVAL
|
||||
#define PW_ACCT_INTERIM_INTERVAL 85
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if RADCLI_VERSION_NUMBER < 0x010207
|
||||
# define CHALLENGE_RC 3
|
||||
#define CHALLENGE_RC 3
|
||||
#endif
|
||||
|
||||
#define MAX_CHALLENGES 16
|
||||
@@ -91,19 +92,21 @@ static void radius_vhost_init(void **_vctx, void *pool, void *additional)
|
||||
}
|
||||
|
||||
if (config->nas_identifier) {
|
||||
strlcpy(vctx->nas_identifier, config->nas_identifier, sizeof(vctx->nas_identifier));
|
||||
strlcpy(vctx->nas_identifier, config->nas_identifier,
|
||||
sizeof(vctx->nas_identifier));
|
||||
} else {
|
||||
vctx->nas_identifier[0] = 0;
|
||||
}
|
||||
|
||||
if (rc_read_dictionary(vctx->rh, rc_conf_str(vctx->rh, "dictionary")) != 0) {
|
||||
if (rc_read_dictionary(vctx->rh, rc_conf_str(vctx->rh, "dictionary")) !=
|
||||
0) {
|
||||
fprintf(stderr, "error reading the radius dictionary\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*_vctx = vctx;
|
||||
|
||||
return;
|
||||
fail:
|
||||
fail:
|
||||
fprintf(stderr, "radius initialization error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -116,15 +119,15 @@ static void radius_vhost_deinit(void *_vctx)
|
||||
rc_destroy(vctx->rh);
|
||||
}
|
||||
|
||||
static int radius_auth_init(void **ctx, void *pool, void *_vctx, const common_auth_init_st *info)
|
||||
static int radius_auth_init(void **ctx, void *pool, void *_vctx,
|
||||
const common_auth_init_st *info)
|
||||
{
|
||||
struct radius_ctx_st *pctx;
|
||||
char *default_realm;
|
||||
struct radius_vhost_ctx *vctx = _vctx;
|
||||
|
||||
if (info->username == NULL || info->username[0] == 0) {
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"radius-auth: no username present");
|
||||
oc_syslog(LOG_NOTICE, "radius-auth: no username present");
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
@@ -145,38 +148,43 @@ static int radius_auth_init(void **ctx, void *pool, void *_vctx, const common_au
|
||||
|
||||
if ((strchr(info->username, '@') == NULL) && default_realm &&
|
||||
default_realm[0] != 0) {
|
||||
snprintf(pctx->username, sizeof(pctx->username), "%s@%s", info->username, default_realm);
|
||||
snprintf(pctx->username, sizeof(pctx->username), "%s@%s",
|
||||
info->username, default_realm);
|
||||
} else {
|
||||
strlcpy(pctx->username, info->username, sizeof(pctx->username));
|
||||
}
|
||||
pctx->id = info->id;
|
||||
|
||||
if (info->user_agent)
|
||||
strlcpy(pctx->user_agent, info->user_agent, sizeof(pctx->user_agent));
|
||||
strlcpy(pctx->user_agent, info->user_agent,
|
||||
sizeof(pctx->user_agent));
|
||||
|
||||
*ctx = pctx;
|
||||
|
||||
return ERR_AUTH_CONTINUE;
|
||||
}
|
||||
|
||||
static int radius_auth_group(void *ctx, const char *suggested, char *groupname, int groupname_size)
|
||||
static int radius_auth_group(void *ctx, const char *suggested, char *groupname,
|
||||
int groupname_size)
|
||||
{
|
||||
struct radius_ctx_st *pctx = ctx;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
groupname[0] = 0;
|
||||
|
||||
if (suggested != NULL) {
|
||||
for (i=0;i<pctx->groupnames_size;i++) {
|
||||
for (i = 0; i < pctx->groupnames_size; i++) {
|
||||
if (strcmp(suggested, pctx->groupnames[i]) == 0) {
|
||||
strlcpy(groupname, pctx->groupnames[i], groupname_size);
|
||||
strlcpy(groupname, pctx->groupnames[i],
|
||||
groupname_size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"radius-auth: user '%s' requested group '%s' but is not a member",
|
||||
pctx->username, suggested);
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"radius-auth: user '%s' requested group '%s' but is not a member",
|
||||
pctx->username, suggested);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -193,13 +201,15 @@ static int radius_auth_user(void *ctx, char *username, int username_size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void append_route(struct radius_ctx_st *pctx, const char *route, unsigned len)
|
||||
static void append_route(struct radius_ctx_st *pctx, const char *route,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
char *p;
|
||||
|
||||
/* accept route/mask */
|
||||
if ((p=strchr(route, '/')) == 0)
|
||||
p = strchr(route, '/');
|
||||
if (p == 0)
|
||||
return;
|
||||
|
||||
p = strchr(p, ' ');
|
||||
@@ -208,10 +218,11 @@ static void append_route(struct radius_ctx_st *pctx, const char *route, unsigned
|
||||
}
|
||||
|
||||
if (pctx->routes_size == 0) {
|
||||
pctx->routes = talloc_size(pctx, sizeof(char*));
|
||||
pctx->routes = talloc_size(pctx, sizeof(char *));
|
||||
} else {
|
||||
pctx->routes = talloc_realloc_size(pctx, pctx->routes,
|
||||
(pctx->routes_size+1)*sizeof(char*));
|
||||
(pctx->routes_size + 1) *
|
||||
sizeof(char *));
|
||||
}
|
||||
|
||||
if (pctx->routes != NULL) {
|
||||
@@ -228,11 +239,13 @@ static void parse_groupnames(struct radius_ctx_st *pctx, const char *full)
|
||||
char *p, *p2;
|
||||
|
||||
if (pctx->groupnames_size >= MAX_GROUPS) {
|
||||
oc_syslog(LOG_WARNING,
|
||||
"radius-auth: cannot handle more than %d groups, ignoring group string %s",
|
||||
MAX_GROUPS, full);
|
||||
oc_syslog(
|
||||
LOG_WARNING,
|
||||
"radius-auth: cannot handle more than %d groups, ignoring group string %s",
|
||||
MAX_GROUPS, full);
|
||||
} else if (strncmp(full, "OU=", 3) == 0) {
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: found group string %s", full);
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: found group string %s",
|
||||
full);
|
||||
full += 3;
|
||||
|
||||
p = talloc_strdup(pctx, full);
|
||||
@@ -249,14 +262,16 @@ static void parse_groupnames(struct radius_ctx_st *pctx, const char *full)
|
||||
|
||||
if (pctx->groupnames_size == MAX_GROUPS) {
|
||||
if (p2)
|
||||
oc_syslog(LOG_WARNING,
|
||||
"radius-auth: cannot handle more than %d groups, ignoring trailing group(s) %s",
|
||||
MAX_GROUPS, p2);
|
||||
oc_syslog(
|
||||
LOG_WARNING,
|
||||
"radius-auth: cannot handle more than %d groups, ignoring trailing group(s) %s",
|
||||
MAX_GROUPS, p2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: found group string %s", full);
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: found group string %s",
|
||||
full);
|
||||
p = talloc_strdup(pctx, full);
|
||||
if (p == NULL)
|
||||
return;
|
||||
@@ -266,7 +281,7 @@ static void parse_groupnames(struct radius_ctx_st *pctx, const char *full)
|
||||
|
||||
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name.
|
||||
*/
|
||||
static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
static int radius_auth_pass(void *ctx, const char *pass, unsigned int pass_len)
|
||||
{
|
||||
struct radius_ctx_st *pctx = ctx;
|
||||
VALUE_PAIR *send = NULL, *recvd = NULL;
|
||||
@@ -277,18 +292,24 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
int ret;
|
||||
|
||||
/* send Access-Request */
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: communicating username (%s) and password", pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_USER_NAME, pctx->username, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
oc_syslog(LOG_DEBUG,
|
||||
"radius-auth: communicating username (%s) and password",
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_USER_NAME, pctx->username,
|
||||
-1, 0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
return ERR_AUTH_FAIL;
|
||||
}
|
||||
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_USER_PASSWORD, (char*)pass, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_USER_PASSWORD, (char *)pass,
|
||||
-1, 0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -299,18 +320,24 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
|
||||
if (inet_pton(AF_INET, pctx->our_ip, &in) != 0) {
|
||||
in.s_addr = ntohl(in.s_addr);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_NAS_IP_ADDRESS, (char*)&in, sizeof(struct in_addr), 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send,
|
||||
PW_NAS_IP_ADDRESS, (char *)&in,
|
||||
sizeof(struct in_addr), 0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
} else if (inet_pton(AF_INET6, pctx->our_ip, &in6) != 0) {
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_NAS_IPV6_ADDRESS, (char*)&in6, sizeof(struct in6_addr), 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send,
|
||||
PW_NAS_IPV6_ADDRESS, (char *)&in6,
|
||||
sizeof(struct in6_addr), 0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -318,56 +345,68 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
}
|
||||
|
||||
if (pctx->vctx->nas_identifier[0] != 0) {
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_NAS_IDENTIFIER, pctx->vctx->nas_identifier, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_NAS_IDENTIFIER,
|
||||
pctx->vctx->nas_identifier, -1, 0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_CALLING_STATION_ID, pctx->remote_ip, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_CALLING_STATION_ID,
|
||||
pctx->remote_ip, -1, 0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (pctx->user_agent[0] != 0) {
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_CONNECT_INFO, pctx->user_agent, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_CONNECT_INFO,
|
||||
pctx->user_agent, -1, 0) == NULL) {
|
||||
oc_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(pctx->vctx->rh, &send, PW_SERVICE_TYPE, &service, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_SERVICE_TYPE, &service, -1,
|
||||
0) == NULL) {
|
||||
oc_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_ASYNC;
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_NAS_PORT_TYPE, &service, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_NAS_PORT_TYPE, &service, -1,
|
||||
0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (pctx->state != NULL) {
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_STATE, pctx->state, -1, 0) == NULL) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'", __func__, __LINE__,
|
||||
pctx->username);
|
||||
if (rc_avpair_add(pctx->vctx->rh, &send, PW_STATE, pctx->state,
|
||||
-1, 0) == NULL) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: error in constructing radius message for user '%s'",
|
||||
__func__, __LINE__, pctx->username);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -376,7 +415,8 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
}
|
||||
|
||||
pctx->pass_msg[0] = 0;
|
||||
ret = rc_aaa(pctx->vctx->rh, 0, send, &recvd, pctx->pass_msg, 0, PW_ACCESS_REQUEST);
|
||||
ret = rc_aaa(pctx->vctx->rh, 0, send, &recvd, pctx->pass_msg, 0,
|
||||
PW_ACCESS_REQUEST);
|
||||
|
||||
if (ret == OK_RC) {
|
||||
uint32_t ipv4;
|
||||
@@ -385,90 +425,144 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
vp = recvd;
|
||||
|
||||
while (vp != NULL) {
|
||||
if (vp->attribute == PW_SERVICE_TYPE && vp->lvalue != PW_FRAMED) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: unknown radius service type '%d'", __func__, __LINE__,
|
||||
(int)vp->lvalue);
|
||||
if (vp->attribute == PW_SERVICE_TYPE &&
|
||||
vp->lvalue != PW_FRAMED) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: unknown radius service type '%d'",
|
||||
__func__, __LINE__, (int)vp->lvalue);
|
||||
goto fail;
|
||||
} else if (vp->attribute == RAD_GROUP_NAME && vp->type == PW_TYPE_STRING) {
|
||||
} else if (vp->attribute == RAD_GROUP_NAME &&
|
||||
vp->type == PW_TYPE_STRING) {
|
||||
/* Group-Name */
|
||||
parse_groupnames(pctx, vp->strvalue);
|
||||
} else if (vp->attribute == PW_FRAMED_IPV6_ADDRESS && vp->type == PW_TYPE_IPV6ADDR) {
|
||||
} else if (vp->attribute == PW_FRAMED_IPV6_ADDRESS &&
|
||||
vp->type == PW_TYPE_IPV6ADDR) {
|
||||
/* Framed-IPv6-Address */
|
||||
if (inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6, sizeof(pctx->ipv6)) != NULL) {
|
||||
if (inet_ntop(AF_INET6, vp->strvalue,
|
||||
pctx->ipv6,
|
||||
sizeof(pctx->ipv6)) != NULL) {
|
||||
pctx->ipv6_subnet_prefix = 64;
|
||||
strlcpy(pctx->ipv6_net, pctx->ipv6, sizeof(pctx->ipv6_net));
|
||||
strlcpy(pctx->ipv6_net, pctx->ipv6,
|
||||
sizeof(pctx->ipv6_net));
|
||||
}
|
||||
} else if (vp->attribute == PW_DELEGATED_IPV6_PREFIX && vp->type == PW_TYPE_IPV6PREFIX) {
|
||||
} else if (vp->attribute == PW_DELEGATED_IPV6_PREFIX &&
|
||||
vp->type == PW_TYPE_IPV6PREFIX) {
|
||||
/* Delegated-IPv6-Prefix */
|
||||
if (inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6, sizeof(pctx->ipv6)) != NULL) {
|
||||
if (inet_ntop(AF_INET6, vp->strvalue,
|
||||
pctx->ipv6,
|
||||
sizeof(pctx->ipv6)) != NULL) {
|
||||
memset(ipv6, 0, sizeof(ipv6));
|
||||
memcpy(ipv6, vp->strvalue+2, vp->lvalue-2);
|
||||
if (inet_ntop(AF_INET6, ipv6, pctx->ipv6, sizeof(pctx->ipv6)) != NULL) {
|
||||
pctx->ipv6_subnet_prefix = (unsigned)(unsigned char)vp->strvalue[1];
|
||||
memcpy(ipv6, vp->strvalue + 2,
|
||||
vp->lvalue - 2);
|
||||
if (inet_ntop(AF_INET6, ipv6,
|
||||
pctx->ipv6,
|
||||
sizeof(pctx->ipv6)) !=
|
||||
NULL) {
|
||||
pctx->ipv6_subnet_prefix =
|
||||
(unsigned int)(unsigned char)
|
||||
vp->strvalue[1];
|
||||
}
|
||||
}
|
||||
} else if (vp->attribute == PW_FRAMED_IPV6_PREFIX && vp->type == PW_TYPE_IPV6PREFIX) {
|
||||
} else if (vp->attribute == PW_FRAMED_IPV6_PREFIX &&
|
||||
vp->type == PW_TYPE_IPV6PREFIX) {
|
||||
if (vp->lvalue > 2 && vp->lvalue <= 18) {
|
||||
/* Framed-IPv6-Prefix */
|
||||
memset(ipv6, 0, sizeof(ipv6));
|
||||
memcpy(ipv6, vp->strvalue+2, vp->lvalue-2);
|
||||
if (inet_ntop(AF_INET6, ipv6, txt, sizeof(txt)) != NULL) {
|
||||
snprintf(route, sizeof(route), "%s/%u", txt, (unsigned)(unsigned char)vp->strvalue[1]);
|
||||
append_route(pctx, vp->strvalue, vp->lvalue);
|
||||
memcpy(ipv6, vp->strvalue + 2,
|
||||
vp->lvalue - 2);
|
||||
if (inet_ntop(AF_INET6, ipv6, txt,
|
||||
sizeof(txt)) != NULL) {
|
||||
snprintf(
|
||||
route, sizeof(route),
|
||||
"%s/%u", txt,
|
||||
(unsigned int)(unsigned char)
|
||||
vp->strvalue[1]);
|
||||
append_route(pctx, vp->strvalue,
|
||||
vp->lvalue);
|
||||
}
|
||||
}
|
||||
} else if (vp->attribute == PW_DNS_SERVER_IPV6_ADDRESS && vp->type == PW_TYPE_IPV6ADDR) {
|
||||
} else if (vp->attribute ==
|
||||
PW_DNS_SERVER_IPV6_ADDRESS &&
|
||||
vp->type == PW_TYPE_IPV6ADDR) {
|
||||
/* DNS-Server-IPv6-Address */
|
||||
if (pctx->ipv6_dns1[0] == 0)
|
||||
inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6_dns1, sizeof(pctx->ipv6_dns1));
|
||||
inet_ntop(AF_INET6, vp->strvalue,
|
||||
pctx->ipv6_dns1,
|
||||
sizeof(pctx->ipv6_dns1));
|
||||
else if (pctx->ipv6_dns2[0] == 0)
|
||||
inet_ntop(AF_INET6, vp->strvalue, pctx->ipv6_dns2, sizeof(pctx->ipv6_dns2));
|
||||
inet_ntop(AF_INET6, vp->strvalue,
|
||||
pctx->ipv6_dns2,
|
||||
sizeof(pctx->ipv6_dns2));
|
||||
else {
|
||||
char dst[MAX_IP_STR];
|
||||
inet_ntop(AF_INET6, vp->strvalue, dst, sizeof(dst));
|
||||
oc_syslog(LOG_NOTICE, "radius-auth: cannot handle more than 2 DNS servers, ignoring additional DNS server from RADIUS: %s", dst);
|
||||
|
||||
inet_ntop(AF_INET6, vp->strvalue, dst,
|
||||
sizeof(dst));
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"radius-auth: cannot handle more than 2 DNS servers, ignoring additional DNS server from RADIUS: %s",
|
||||
dst);
|
||||
}
|
||||
} else if (vp->attribute == PW_FRAMED_IP_ADDRESS && vp->type == PW_TYPE_IPADDR) {
|
||||
} else if (vp->attribute == PW_FRAMED_IP_ADDRESS &&
|
||||
vp->type == PW_TYPE_IPADDR) {
|
||||
/* Framed-IP-Address */
|
||||
if (vp->lvalue != 0xffffffff && vp->lvalue != 0xfffffffe) {
|
||||
if (vp->lvalue != 0xffffffff &&
|
||||
vp->lvalue != 0xfffffffe) {
|
||||
/* According to RFC2865 the values above (fe) instruct the
|
||||
* server to assign an address from the pool of the server,
|
||||
* and (ff) to assign address as negotiated with the client.
|
||||
* We don't negotiate with clients.
|
||||
*/
|
||||
ipv4 = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4, sizeof(pctx->ipv4));
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4,
|
||||
sizeof(pctx->ipv4));
|
||||
}
|
||||
} else if (vp->attribute == PW_FRAMED_IP_NETMASK && vp->type == PW_TYPE_IPADDR) {
|
||||
} else if (vp->attribute == PW_FRAMED_IP_NETMASK &&
|
||||
vp->type == PW_TYPE_IPADDR) {
|
||||
/* Framed-IP-Netmask */
|
||||
ipv4 = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4_mask, sizeof(pctx->ipv4_mask));
|
||||
} else if (vp->attribute == MS_PRIMARY_DNS_SERVER && vp->type == PW_TYPE_IPADDR) {
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4_mask,
|
||||
sizeof(pctx->ipv4_mask));
|
||||
} else if (vp->attribute == MS_PRIMARY_DNS_SERVER &&
|
||||
vp->type == PW_TYPE_IPADDR) {
|
||||
/* MS-Primary-DNS-Server */
|
||||
ipv4 = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4_dns1, sizeof(pctx->ipv4_dns1));
|
||||
} else if (vp->attribute == MS_SECONDARY_DNS_SERVER && vp->type == PW_TYPE_IPADDR) {
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4_dns1,
|
||||
sizeof(pctx->ipv4_dns1));
|
||||
} else if (vp->attribute == MS_SECONDARY_DNS_SERVER &&
|
||||
vp->type == PW_TYPE_IPADDR) {
|
||||
/* MS-Secondary-DNS-Server */
|
||||
ipv4 = htonl(vp->lvalue);
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4_dns2, sizeof(pctx->ipv4_dns2));
|
||||
} else if (vp->attribute == PW_FRAMED_ROUTE && vp->type == PW_TYPE_STRING) {
|
||||
inet_ntop(AF_INET, &ipv4, pctx->ipv4_dns2,
|
||||
sizeof(pctx->ipv4_dns2));
|
||||
} else if (vp->attribute == PW_FRAMED_ROUTE &&
|
||||
vp->type == PW_TYPE_STRING) {
|
||||
/* Framed-Route */
|
||||
append_route(pctx, vp->strvalue, vp->lvalue);
|
||||
} else if (vp->attribute == PW_FRAMED_IPV6_ROUTE && vp->type == PW_TYPE_STRING) {
|
||||
} else if (vp->attribute == PW_FRAMED_IPV6_ROUTE &&
|
||||
vp->type == PW_TYPE_STRING) {
|
||||
/* Framed-IPv6-Route */
|
||||
append_route(pctx, vp->strvalue, vp->lvalue);
|
||||
} else if (vp->attribute == PW_ACCT_INTERIM_INTERVAL && vp->type == PW_TYPE_INTEGER) {
|
||||
} else if (vp->attribute == PW_ACCT_INTERIM_INTERVAL &&
|
||||
vp->type == PW_TYPE_INTEGER) {
|
||||
pctx->interim_interval_secs = vp->lvalue;
|
||||
} else if (vp->attribute == PW_SESSION_TIMEOUT && vp->type == PW_TYPE_INTEGER) {
|
||||
} else if (vp->attribute == PW_SESSION_TIMEOUT &&
|
||||
vp->type == PW_TYPE_INTEGER) {
|
||||
pctx->session_timeout_secs = vp->lvalue;
|
||||
} else if (vp->attribute == RP_UPSTREAM_SPEED_LIMIT && vp->type == PW_TYPE_INTEGER) {
|
||||
} else if (vp->attribute == RP_UPSTREAM_SPEED_LIMIT &&
|
||||
vp->type == PW_TYPE_INTEGER) {
|
||||
pctx->rx_per_sec = vp->lvalue;
|
||||
} else if (vp->attribute == RP_DOWNSTREAM_SPEED_LIMIT && vp->type == PW_TYPE_INTEGER) {
|
||||
} else if (vp->attribute == RP_DOWNSTREAM_SPEED_LIMIT &&
|
||||
vp->type == PW_TYPE_INTEGER) {
|
||||
pctx->tx_per_sec = vp->lvalue;
|
||||
} else {
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: ignoring server's attribute (%u,%u) of type %u",
|
||||
(unsigned)ATTRID(vp->attribute), (unsigned)VENDOR(vp->attribute), (unsigned)vp->type);
|
||||
oc_syslog(
|
||||
LOG_DEBUG,
|
||||
"radius-auth: ignoring server's attribute (%u,%u) of type %u",
|
||||
(unsigned int)ATTRID(vp->attribute),
|
||||
(unsigned int)VENDOR(vp->attribute),
|
||||
(unsigned int)vp->type);
|
||||
}
|
||||
vp = vp->next;
|
||||
}
|
||||
@@ -476,47 +570,58 @@ static int radius_auth_pass(void *ctx, const char *pass, unsigned pass_len)
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
} else if (ret == CHALLENGE_RC) {
|
||||
|
||||
vp = recvd;
|
||||
|
||||
while (vp != NULL) {
|
||||
if (vp->attribute == PW_STATE && vp->type == PW_TYPE_STRING) {
|
||||
if (vp->attribute == PW_STATE &&
|
||||
vp->type == PW_TYPE_STRING) {
|
||||
/* State */
|
||||
if (vp->lvalue > 0)
|
||||
pctx->state = talloc_strdup(pctx, vp->strvalue);
|
||||
pctx->state = talloc_strdup(
|
||||
pctx, vp->strvalue);
|
||||
|
||||
pctx->id++;
|
||||
oc_syslog(LOG_DEBUG, "radius-auth: Access-Challenge response stage %u, State %s", pctx->passwd_counter, vp->strvalue);
|
||||
oc_syslog(
|
||||
LOG_DEBUG,
|
||||
"radius-auth: Access-Challenge response stage %u, State %s",
|
||||
pctx->passwd_counter, vp->strvalue);
|
||||
ret = ERR_AUTH_CONTINUE;
|
||||
}
|
||||
vp = vp->next;
|
||||
}
|
||||
|
||||
/* PW_STATE or PW_REPLY_MESSAGE is empty or MAX_CHALLENGES limit exceeded */
|
||||
if ((pctx->pass_msg[0] == 0) || (pctx->state == NULL) || (pctx->passwd_counter >= MAX_CHALLENGES)) {
|
||||
strlcpy(pctx->pass_msg, pass_msg_failed, sizeof(pctx->pass_msg));
|
||||
oc_syslog(LOG_ERR, "radius-auth: Access-Challenge with invalid State or Reply-Message, or max number of password requests exceeded");
|
||||
if ((pctx->pass_msg[0] == 0) || (pctx->state == NULL) ||
|
||||
(pctx->passwd_counter >= MAX_CHALLENGES)) {
|
||||
strlcpy(pctx->pass_msg, pass_msg_failed,
|
||||
sizeof(pctx->pass_msg));
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"radius-auth: Access-Challenge with invalid State or Reply-Message, or max number of password requests exceeded");
|
||||
ret = ERR_AUTH_FAIL;
|
||||
}
|
||||
goto cleanup;
|
||||
} else {
|
||||
fail:
|
||||
fail:
|
||||
if (pctx->pass_msg[0] == 0)
|
||||
strlcpy(pctx->pass_msg, pass_msg_failed, sizeof(pctx->pass_msg));
|
||||
strlcpy(pctx->pass_msg, pass_msg_failed,
|
||||
sizeof(pctx->pass_msg));
|
||||
|
||||
if (pctx->retries++ < MAX_PASSWORD_TRIES-1 && pctx->passwd_counter == 0) {
|
||||
if (pctx->retries++ < MAX_PASSWORD_TRIES - 1 &&
|
||||
pctx->passwd_counter == 0) {
|
||||
ret = ERR_AUTH_CONTINUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
oc_syslog(LOG_NOTICE,
|
||||
"radius-auth: error authenticating user '%s' (code %d)",
|
||||
pctx->username, ret);
|
||||
oc_syslog(
|
||||
LOG_NOTICE,
|
||||
"radius-auth: error authenticating user '%s' (code %d)",
|
||||
pctx->username, ret);
|
||||
ret = ERR_AUTH_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (send != NULL)
|
||||
rc_avpair_free(send);
|
||||
if (recvd != NULL)
|
||||
@@ -533,11 +638,11 @@ static int radius_auth_msg(void *ctx, void *pool, passwd_msg_st *pst)
|
||||
pst->msg_str = talloc_strdup(pool, pctx->pass_msg);
|
||||
|
||||
if (pctx->state != NULL) {
|
||||
|
||||
/* differentiate password prompts, if the hash of the prompt
|
||||
* is different.
|
||||
*/
|
||||
prompt_hash = hash_any(pctx->pass_msg, strlen(pctx->pass_msg), 0);
|
||||
prompt_hash =
|
||||
hash_any(pctx->pass_msg, strlen(pctx->pass_msg), 0);
|
||||
if (pctx->prev_prompt_hash != prompt_hash)
|
||||
pctx->passwd_counter++;
|
||||
pctx->prev_prompt_hash = prompt_hash;
|
||||
@@ -551,6 +656,7 @@ static int radius_auth_msg(void *ctx, void *pool, passwd_msg_st *pst)
|
||||
static void radius_auth_deinit(void *ctx)
|
||||
{
|
||||
struct radius_ctx_st *pctx = ctx;
|
||||
|
||||
talloc_free(pctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,18 +19,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef RADIUS_H
|
||||
# define RADIUS_H
|
||||
#define RADIUS_H
|
||||
|
||||
# include <sec-mod-auth.h>
|
||||
# include "common/common.h"
|
||||
#include <sec-mod-auth.h>
|
||||
#include "common/common.h"
|
||||
|
||||
# ifdef HAVE_RADIUS
|
||||
#ifdef HAVE_RADIUS
|
||||
|
||||
# ifdef LEGACY_RADIUS
|
||||
# include <freeradius-client.h>
|
||||
# else
|
||||
# include <radcli/radcli.h>
|
||||
# endif
|
||||
#ifdef LEGACY_RADIUS
|
||||
#include <freeradius-client.h>
|
||||
#else
|
||||
#include <radcli/radcli.h>
|
||||
#endif
|
||||
|
||||
struct radius_vhost_ctx {
|
||||
rc_handle *rh;
|
||||
@@ -38,16 +38,16 @@ struct radius_vhost_ctx {
|
||||
};
|
||||
|
||||
struct radius_ctx_st {
|
||||
char username[MAX_USERNAME_SIZE*2];
|
||||
char username[MAX_USERNAME_SIZE * 2];
|
||||
char user_agent[MAX_AGENT_NAME];
|
||||
|
||||
char *groupnames[MAX_GROUPS];
|
||||
unsigned groupnames_size;
|
||||
unsigned int groupnames_size;
|
||||
|
||||
char remote_ip[MAX_IP_STR];
|
||||
char our_ip[MAX_IP_STR];
|
||||
unsigned interim_interval_secs;
|
||||
unsigned session_timeout_secs;
|
||||
unsigned int interim_interval_secs;
|
||||
unsigned int session_timeout_secs;
|
||||
|
||||
/* variables for configuration */
|
||||
char ipv4[MAX_IP_STR];
|
||||
@@ -65,19 +65,19 @@ struct radius_ctx_st {
|
||||
uint32_t tx_per_sec;
|
||||
|
||||
char **routes;
|
||||
unsigned routes_size;
|
||||
unsigned int routes_size;
|
||||
|
||||
char pass_msg[PW_MAX_MSG_SIZE];
|
||||
unsigned retries;
|
||||
unsigned id;
|
||||
unsigned int retries;
|
||||
unsigned int id;
|
||||
|
||||
struct radius_vhost_ctx *vctx;
|
||||
char *state;
|
||||
unsigned passwd_counter;
|
||||
unsigned int passwd_counter;
|
||||
size_t prev_prompt_hash;
|
||||
};
|
||||
|
||||
extern const struct auth_mod_st radius_auth_funcs;
|
||||
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_COMMON_CONFIG_H
|
||||
# define OC_COMMON_CONFIG_H
|
||||
#define OC_COMMON_CONFIG_H
|
||||
|
||||
#include <config.h>
|
||||
#include <vpn.h>
|
||||
@@ -27,8 +27,9 @@
|
||||
|
||||
char *sanitize_config_value(void *pool, const char *value);
|
||||
int _add_multi_line_val(void *pool, char ***varname, size_t *num,
|
||||
const char *val);
|
||||
int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const char *str);
|
||||
const char *val);
|
||||
int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports,
|
||||
const char *str);
|
||||
|
||||
#define MAX_SUBOPTIONS 5
|
||||
|
||||
@@ -39,7 +40,7 @@ typedef struct subcfg_val_st {
|
||||
|
||||
typedef struct gssapi_cfg_st {
|
||||
char *keytab;
|
||||
unsigned no_local_map;
|
||||
unsigned int no_local_map;
|
||||
time_t ticket_freshness_secs;
|
||||
int gid_min;
|
||||
} gssapi_cfg_st;
|
||||
@@ -58,17 +59,27 @@ typedef struct pam_cfg_st {
|
||||
int gid_min;
|
||||
} pam_cfg_st;
|
||||
|
||||
#define CHECK_TRUE(str) ((str != NULL && (strcasecmp(str, "true") == 0 || strcasecmp(str, "yes") == 0))?1:0)
|
||||
#define CHECK_TRUE(str) \
|
||||
((str != NULL && \
|
||||
(strcasecmp(str, "true") == 0 || strcasecmp(str, "yes") == 0)) ? \
|
||||
1 : \
|
||||
0)
|
||||
|
||||
struct perm_cfg_st;
|
||||
|
||||
void *get_brackets_string1(void *pool, const char *str);
|
||||
void *gssapi_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str);
|
||||
void *radius_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str);
|
||||
void *pam_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str);
|
||||
void *plain_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str);
|
||||
void *oidc_get_brackets_string(void * pool, struct perm_cfg_st *config, const char *str);
|
||||
void *gssapi_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str);
|
||||
void *radius_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str);
|
||||
void *pam_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str);
|
||||
void *plain_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str);
|
||||
void *oidc_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str);
|
||||
|
||||
void parse_kkdcp_string(char *str, int *socktype, char **_port, char **_server, char **_path, char **_realm);
|
||||
void parse_kkdcp_string(char *str, int *socktype, char **_port, char **_server,
|
||||
char **_path, char **_realm);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,21 +22,20 @@
|
||||
#include <talloc.h>
|
||||
#include "base64-helper.h"
|
||||
|
||||
void oc_base64_encode (const char *in, size_t inlen,
|
||||
char *out, size_t outlen)
|
||||
void oc_base64_encode(const char *in, size_t inlen, char *out, size_t outlen)
|
||||
{
|
||||
unsigned raw = BASE64_ENCODE_RAW_LENGTH(inlen);
|
||||
if (outlen < raw+1) {
|
||||
unsigned int raw = BASE64_ENCODE_RAW_LENGTH(inlen);
|
||||
|
||||
if (outlen < raw + 1) {
|
||||
snprintf(out, outlen, "(too long data)");
|
||||
return;
|
||||
}
|
||||
base64_encode_raw((void*)out, inlen, (uint8_t*)in);
|
||||
base64_encode_raw((void *)out, inlen, (uint8_t *)in);
|
||||
out[raw] = 0;
|
||||
}
|
||||
|
||||
int
|
||||
oc_base64_decode(const uint8_t *src, unsigned src_length,
|
||||
uint8_t *dst, size_t *dst_length)
|
||||
int oc_base64_decode(const uint8_t *src, unsigned int src_length, uint8_t *dst,
|
||||
size_t *dst_length)
|
||||
{
|
||||
struct base64_decode_ctx ctx;
|
||||
int ret;
|
||||
@@ -46,12 +45,14 @@ oc_base64_decode(const uint8_t *src, unsigned src_length,
|
||||
#ifdef NETTLE_OLD_BASE64_API
|
||||
{
|
||||
unsigned int len = *dst_length;
|
||||
|
||||
ret = base64_decode_update(&ctx, &len, dst, src_length, src);
|
||||
if (ret != 0)
|
||||
*dst_length = len;
|
||||
}
|
||||
#else
|
||||
ret = base64_decode_update(&ctx, dst_length, dst, src_length, (void*)src);
|
||||
ret = base64_decode_update(&ctx, dst_length, dst, src_length,
|
||||
(void *)src);
|
||||
#endif
|
||||
|
||||
if (ret == 0)
|
||||
@@ -60,8 +61,8 @@ oc_base64_decode(const uint8_t *src, unsigned src_length,
|
||||
return base64_decode_final(&ctx);
|
||||
}
|
||||
|
||||
int oc_base64_decode_alloc(void *pool, const char *in, size_t inlen,
|
||||
char **out, size_t *outlen)
|
||||
int oc_base64_decode_alloc(void *pool, const char *in, size_t inlen, char **out,
|
||||
size_t *outlen)
|
||||
{
|
||||
int len, ret;
|
||||
void *tmp;
|
||||
@@ -73,7 +74,7 @@ int oc_base64_decode_alloc(void *pool, const char *in, size_t inlen,
|
||||
return 0;
|
||||
|
||||
*outlen = len;
|
||||
ret = oc_base64_decode((void*)in, inlen, tmp, outlen);
|
||||
ret = oc_base64_decode((void *)in, inlen, tmp, outlen);
|
||||
if (ret == 0) {
|
||||
talloc_free(tmp);
|
||||
return 0;
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef BASE64_HELPER_H
|
||||
# define BASE64_HELPER_H
|
||||
#define BASE64_HELPER_H
|
||||
|
||||
#include <nettle/base64.h>
|
||||
|
||||
/* Prototypes compatible with the gnulib's */
|
||||
|
||||
int
|
||||
oc_base64_decode(const uint8_t *src, unsigned src_length,
|
||||
uint8_t *dst, size_t *dst_length);
|
||||
int oc_base64_decode(const uint8_t *src, unsigned int src_length, uint8_t *dst,
|
||||
size_t *dst_length);
|
||||
|
||||
int oc_base64_decode_alloc(void *pool, const char *in, size_t inlen,
|
||||
char **out, size_t *outlen);
|
||||
int oc_base64_decode_alloc(void *pool, const char *in, size_t inlen, char **out,
|
||||
size_t *outlen);
|
||||
|
||||
void oc_base64_encode (const char *in, size_t inlen,
|
||||
char *out, size_t outlen);
|
||||
void oc_base64_encode(const char *in, size_t inlen, char *out, size_t outlen);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,49 +35,44 @@
|
||||
open or pipe2 that accept flags like O_CLOEXEC to create DESC
|
||||
non-inheritable in the first place. */
|
||||
|
||||
int
|
||||
set_cloexec_flag (int desc, bool value)
|
||||
int set_cloexec_flag(int desc, bool value)
|
||||
{
|
||||
#ifdef F_SETFD
|
||||
|
||||
int flags = fcntl (desc, F_GETFD, 0);
|
||||
int flags = fcntl(desc, F_GETFD, 0);
|
||||
|
||||
if (0 <= flags)
|
||||
{
|
||||
int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
|
||||
if (flags >= 0) {
|
||||
int newflags =
|
||||
(value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
|
||||
|
||||
if (flags == newflags
|
||||
|| fcntl (desc, F_SETFD, newflags) != -1)
|
||||
return 0;
|
||||
}
|
||||
if (flags == newflags || fcntl(desc, F_SETFD, newflags) != -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
#else /* !F_SETFD */
|
||||
|
||||
/* Use dup2 to reject invalid file descriptors; the cloexec flag
|
||||
/* Use dup2 to reject invalid file descriptors; the cloexec flag
|
||||
will be unaffected. */
|
||||
if (desc < 0)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if (dup2 (desc, desc) < 0)
|
||||
/* errno is EBADF here. */
|
||||
return -1;
|
||||
if (desc < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if (dup2(desc, desc) < 0)
|
||||
/* errno is EBADF here. */
|
||||
return -1;
|
||||
|
||||
/* There is nothing we can do on this kind of platform. Punt. */
|
||||
return 0;
|
||||
/* There is nothing we can do on this kind of platform. Punt. */
|
||||
return 0;
|
||||
#endif /* !F_SETFD */
|
||||
}
|
||||
|
||||
|
||||
/* Duplicates a file handle FD, while marking the copy to be closed
|
||||
prior to exec or spawn. Returns -1 and sets errno if FD could not
|
||||
be duplicated. */
|
||||
|
||||
int
|
||||
dup_cloexec (int fd)
|
||||
int dup_cloexec(int fd)
|
||||
{
|
||||
return fcntl (fd, F_DUPFD_CLOEXEC, 0);
|
||||
return fcntl(fd, F_DUPFD_CLOEXEC, 0);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
#ifndef CLOEXEC_H
|
||||
# define CLOEXEC_H
|
||||
#define CLOEXEC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
open or pipe2 that accept flags like O_CLOEXEC to create DESC
|
||||
non-inheritable in the first place. */
|
||||
|
||||
int set_cloexec_flag (int desc, bool value);
|
||||
int set_cloexec_flag(int desc, bool value);
|
||||
|
||||
/* Duplicates a file handle FD, while marking the copy to be closed
|
||||
prior to exec or spawn. Returns -1 and sets errno if FD could not
|
||||
be duplicated. */
|
||||
|
||||
int dup_cloexec (int fd);
|
||||
int dup_cloexec(int fd);
|
||||
|
||||
#endif /* CLOEXEC_H */
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
#include "common/base64-helper.h"
|
||||
#include "log.h"
|
||||
|
||||
int saved_argc = 0;
|
||||
char **saved_argv = NULL;
|
||||
int saved_argc;
|
||||
char **saved_argv;
|
||||
|
||||
const char *_vhost_prefix(const char *name)
|
||||
{
|
||||
@@ -50,7 +50,8 @@ const char *_vhost_prefix(const char *name)
|
||||
|
||||
/* A hash of the input, to a 20-byte output. The goal is one-wayness.
|
||||
*/
|
||||
static void safe_hash(const uint8_t *data, unsigned data_size, uint8_t output[20])
|
||||
static void safe_hash(const uint8_t *data, unsigned int data_size,
|
||||
uint8_t output[20])
|
||||
{
|
||||
struct sha1_ctx ctx;
|
||||
|
||||
@@ -60,13 +61,13 @@ static void safe_hash(const uint8_t *data, unsigned data_size, uint8_t output[20
|
||||
sha1_digest(&ctx, 20, output);
|
||||
}
|
||||
|
||||
|
||||
char *calc_safe_id(const uint8_t *data, unsigned size, char *output, unsigned output_size)
|
||||
char *calc_safe_id(const uint8_t *data, unsigned int size, char *output,
|
||||
unsigned int output_size)
|
||||
{
|
||||
uint8_t safe_id[20];
|
||||
|
||||
safe_hash(data, size, safe_id);
|
||||
oc_base64_encode((char*)safe_id, 20, output, output_size);
|
||||
oc_base64_encode((char *)safe_id, 20, output, output_size);
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -74,7 +75,7 @@ char *calc_safe_id(const uint8_t *data, unsigned size, char *output, unsigned ou
|
||||
/* Note that meaning slightly changes depending on whether we are
|
||||
* referring to the cookie or the session itself.
|
||||
*/
|
||||
const char *ps_status_to_str(int status, unsigned cookie)
|
||||
const char *ps_status_to_str(int status, unsigned int cookie)
|
||||
{
|
||||
switch (status) {
|
||||
case PS_AUTH_COMPLETED:
|
||||
@@ -94,7 +95,7 @@ const char *ps_status_to_str(int status, unsigned cookie)
|
||||
}
|
||||
}
|
||||
|
||||
const char *cmd_request_to_str(unsigned _cmd)
|
||||
const char *cmd_request_to_str(unsigned int _cmd)
|
||||
{
|
||||
cmd_request_t cmd = _cmd;
|
||||
static char tmp[32];
|
||||
@@ -172,7 +173,7 @@ const char *cmd_request_to_str(unsigned _cmd)
|
||||
}
|
||||
}
|
||||
|
||||
const char *discon_reason_to_str(unsigned reason)
|
||||
const char *discon_reason_to_str(unsigned int reason)
|
||||
{
|
||||
static char tmp[32];
|
||||
|
||||
@@ -271,7 +272,7 @@ ssize_t force_read(int sockfd, void *buf, size_t len)
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t force_read_timeout(int sockfd, void *buf, size_t len, unsigned sec)
|
||||
ssize_t force_read_timeout(int sockfd, void *buf, size_t len, unsigned int sec)
|
||||
{
|
||||
int left = len;
|
||||
int ret;
|
||||
@@ -325,6 +326,7 @@ void set_non_block(int fd)
|
||||
* https://patchwork.kernel.org/project/qemu-devel/patch/20200331133536.3328-1-linus.walleij@linaro.org/
|
||||
*/
|
||||
int e = errno;
|
||||
|
||||
oc_syslog(LOG_ERR, "set_non_block: %s", strerror(e));
|
||||
}
|
||||
}
|
||||
@@ -337,11 +339,12 @@ void set_block(int fd)
|
||||
ret = fcntl(fd, F_SETFL, val & (~O_NONBLOCK));
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
|
||||
oc_syslog(LOG_ERR, "set_non_block: %s", strerror(e));
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t recv_timeout(int sockfd, void *buf, size_t len, unsigned sec)
|
||||
ssize_t recv_timeout(int sockfd, void *buf, size_t len, unsigned int sec)
|
||||
{
|
||||
int ret;
|
||||
struct pollfd pfd;
|
||||
@@ -362,8 +365,8 @@ ssize_t recv_timeout(int sockfd, void *buf, size_t len, unsigned sec)
|
||||
return recv(sockfd, buf, len, 0);
|
||||
}
|
||||
|
||||
ssize_t recvmsg_timeout(int sockfd, struct msghdr * msg, int flags,
|
||||
unsigned sec)
|
||||
ssize_t recvmsg_timeout(int sockfd, struct msghdr *msg, int flags,
|
||||
unsigned int sec)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -391,7 +394,8 @@ ssize_t recvmsg_timeout(int sockfd, struct msghdr * msg, int flags,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsigned timeout)
|
||||
int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd,
|
||||
unsigned int timeout)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
char data[5];
|
||||
@@ -414,8 +418,9 @@ int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsign
|
||||
ret = recvmsg_timeout(ifd, &hdr, 0, timeout);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
|
||||
oc_syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__, __LINE__,
|
||||
strerror(e));
|
||||
strerror(e));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -425,7 +430,7 @@ int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsign
|
||||
|
||||
if (rcmd != icmd) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: expected %d, received %d", __FILE__,
|
||||
__LINE__, (int)rcmd, (int)icmd);
|
||||
__LINE__, (int)rcmd, (int)icmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -436,7 +441,7 @@ int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsign
|
||||
ret = force_write(ofd, data, 5);
|
||||
if (ret != 5) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: cannot send headers: %s", __FILE__,
|
||||
__LINE__, strerror(errno));
|
||||
__LINE__, strerror(errno));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -449,15 +454,17 @@ int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsign
|
||||
if (ret == -1 || ret == 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
oc_syslog(LOG_ERR, "%s:%u: cannot send between descriptors: %s", __FILE__,
|
||||
__LINE__, strerror(errno));
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: cannot send between descriptors: %s",
|
||||
__FILE__, __LINE__, strerror(errno));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = force_write(ofd, buf, ret);
|
||||
if (ret == -1 || ret == 0) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: cannot send between descriptors: %s", __FILE__,
|
||||
__LINE__, strerror(errno));
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: cannot send between descriptors: %s",
|
||||
__FILE__, __LINE__, strerror(errno));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -468,9 +475,8 @@ int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsign
|
||||
}
|
||||
|
||||
/* Sends message + socketfd */
|
||||
int send_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
int socketfd, const void *msg,
|
||||
pack_size_func get_size, pack_func pack)
|
||||
int send_socket_msg(void *pool, int fd, uint8_t cmd, int socketfd,
|
||||
const void *msg, pack_size_func get_size, pack_func pack)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
struct msghdr hdr;
|
||||
@@ -506,7 +512,7 @@ int send_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
packed = talloc_size(pool, length);
|
||||
if (packed == NULL) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: memory error", __FILE__,
|
||||
__LINE__);
|
||||
__LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -516,7 +522,7 @@ int send_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
ret = pack(msg, packed);
|
||||
if (ret == 0) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: packing error", __FILE__,
|
||||
__LINE__);
|
||||
__LINE__);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -540,17 +546,19 @@ int send_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
if (ret < 0) {
|
||||
int e = errno;
|
||||
oc_syslog(LOG_ERR, "%s:%u: %s", __FILE__, __LINE__, strerror(e));
|
||||
|
||||
oc_syslog(LOG_ERR, "%s:%u: %s", __FILE__, __LINE__,
|
||||
strerror(e));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (length > 0)
|
||||
safe_memset(packed, 0, length);
|
||||
talloc_free(packed);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int recv_msg_headers(int fd, uint8_t *cmd, unsigned timeout)
|
||||
int recv_msg_headers(int fd, uint8_t *cmd, unsigned int timeout)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
char buffer[5];
|
||||
@@ -568,8 +576,9 @@ int recv_msg_headers(int fd, uint8_t *cmd, unsigned timeout)
|
||||
ret = recvmsg_timeout(fd, &hdr, 0, timeout);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
|
||||
oc_syslog(LOG_WARNING, "%s:%u: recvmsg: %s", __FILE__, __LINE__,
|
||||
strerror(e));
|
||||
strerror(e));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -612,8 +621,9 @@ int recv_msg_data(int fd, uint8_t *cmd, uint8_t *data, size_t data_size,
|
||||
ret = recvmsg_timeout(fd, &hdr, 0, MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
|
||||
oc_syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__, __LINE__,
|
||||
strerror(e));
|
||||
strerror(e));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -625,24 +635,28 @@ int recv_msg_data(int fd, uint8_t *cmd, uint8_t *data, size_t data_size,
|
||||
if (received_fd != NULL) {
|
||||
*received_fd = -1;
|
||||
|
||||
if ((cmptr = CMSG_FIRSTHDR(&hdr)) != NULL
|
||||
&& cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||
if (cmptr->cmsg_level != SOL_SOCKET
|
||||
|| cmptr->cmsg_type != SCM_RIGHTS) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: recvmsg returned invalid msg type",
|
||||
__FILE__, __LINE__);
|
||||
if ((cmptr = CMSG_FIRSTHDR(&hdr)) != NULL &&
|
||||
cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||
if (cmptr->cmsg_level != SOL_SOCKET ||
|
||||
cmptr->cmsg_type != SCM_RIGHTS) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: recvmsg returned invalid msg type",
|
||||
__FILE__, __LINE__);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (CMSG_DATA(cmptr))
|
||||
memcpy(received_fd, CMSG_DATA(cmptr), sizeof(int));
|
||||
memcpy(received_fd, CMSG_DATA(cmptr),
|
||||
sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
if (l32 > data_size) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: recv_msg_data: received more data than expected", __FILE__,
|
||||
__LINE__);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: recv_msg_data: received more data than expected",
|
||||
__FILE__, __LINE__);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -650,15 +664,16 @@ int recv_msg_data(int fd, uint8_t *cmd, uint8_t *data, size_t data_size,
|
||||
ret = force_read_timeout(fd, data, l32, MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < l32) {
|
||||
int e = errno;
|
||||
oc_syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__,
|
||||
__LINE__, strerror(e));
|
||||
|
||||
oc_syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__, __LINE__,
|
||||
strerror(e));
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = l32;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (ret < 0 && received_fd != NULL && *received_fd != -1) {
|
||||
close(*received_fd);
|
||||
*received_fd = -1;
|
||||
@@ -666,9 +681,8 @@ int recv_msg_data(int fd, uint8_t *cmd, uint8_t *data, size_t data_size,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void **msg, unpack_func unpack,
|
||||
unsigned timeout)
|
||||
int recv_socket_msg(void *pool, int fd, uint8_t cmd, int *socketfd, void **msg,
|
||||
unpack_func unpack, unsigned int timeout)
|
||||
{
|
||||
struct iovec iov[3];
|
||||
uint32_t length;
|
||||
@@ -681,6 +695,7 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
} control_un;
|
||||
struct cmsghdr *cmptr;
|
||||
int ret;
|
||||
|
||||
PROTOBUF_ALLOCATOR(pa, pool);
|
||||
|
||||
iov[0].iov_base = &rcmd;
|
||||
@@ -699,8 +714,9 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
ret = recvmsg_timeout(fd, &hdr, 0, timeout);
|
||||
if (ret == -1) {
|
||||
int e = errno;
|
||||
|
||||
oc_syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__, __LINE__,
|
||||
strerror(e));
|
||||
strerror(e));
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -710,19 +726,20 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
|
||||
if (rcmd != cmd) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: expected %d, received %d", __FILE__,
|
||||
__LINE__, (int)rcmd, (int)cmd);
|
||||
__LINE__, (int)rcmd, (int)cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
/* try to receive socket (if any) */
|
||||
if (socketfd != NULL) {
|
||||
if ((cmptr = CMSG_FIRSTHDR(&hdr)) != NULL
|
||||
&& cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||
if (cmptr->cmsg_level != SOL_SOCKET
|
||||
|| cmptr->cmsg_type != SCM_RIGHTS) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s:%u: recvmsg returned invalid msg type",
|
||||
__FILE__, __LINE__);
|
||||
if ((cmptr = CMSG_FIRSTHDR(&hdr)) != NULL &&
|
||||
cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||
if (cmptr->cmsg_level != SOL_SOCKET ||
|
||||
cmptr->cmsg_type != SCM_RIGHTS) {
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s:%u: recvmsg returned invalid msg type",
|
||||
__FILE__, __LINE__);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -745,8 +762,9 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
ret = force_read_timeout(fd, data, length, timeout);
|
||||
if (ret < length) {
|
||||
int e = errno;
|
||||
|
||||
oc_syslog(LOG_ERR, "%s:%u: recvmsg: %s", __FILE__,
|
||||
__LINE__, strerror(e));
|
||||
__LINE__, strerror(e));
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -754,7 +772,7 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
*msg = unpack(&pa, length, data);
|
||||
if (*msg == NULL) {
|
||||
oc_syslog(LOG_ERR, "%s:%u: unpacking error", __FILE__,
|
||||
__LINE__);
|
||||
__LINE__);
|
||||
ret = ERR_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -762,7 +780,7 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
talloc_free(data);
|
||||
if (ret < 0 && socketfd != NULL && *socketfd != -1) {
|
||||
close(*socketfd);
|
||||
@@ -771,7 +789,6 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void _talloc_free2(void *ctx, void *ptr)
|
||||
{
|
||||
talloc_free(ptr);
|
||||
@@ -788,8 +805,8 @@ void *_talloc_size2(void *ctx, size_t size)
|
||||
* in our_addr.
|
||||
*/
|
||||
ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr * src_addr, socklen_t * addrlen,
|
||||
struct sockaddr * our_addr, socklen_t * our_addrlen,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen,
|
||||
struct sockaddr *our_addr, socklen_t *our_addrlen,
|
||||
int def_port)
|
||||
{
|
||||
int ret;
|
||||
@@ -816,13 +833,13 @@ ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg != NULL;
|
||||
cmsg = CMSG_NXTHDR(&mh, cmsg)) {
|
||||
#if defined(IP_PKTINFO)
|
||||
if (cmsg->cmsg_level == IPPROTO_IP
|
||||
&& cmsg->cmsg_type == IP_PKTINFO) {
|
||||
if (cmsg->cmsg_level == IPPROTO_IP &&
|
||||
cmsg->cmsg_type == IP_PKTINFO) {
|
||||
struct in_pktinfo *pi = (void *)CMSG_DATA(cmsg);
|
||||
struct sockaddr_in *a = (struct sockaddr_in *)our_addr;
|
||||
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in)
|
||||
|| pi == NULL)
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in) ||
|
||||
pi == NULL)
|
||||
return -1;
|
||||
|
||||
a->sin_family = AF_INET;
|
||||
@@ -833,13 +850,13 @@ ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
break;
|
||||
}
|
||||
#elif defined(IP_RECVDSTADDR)
|
||||
if (cmsg->cmsg_level == IPPROTO_IP
|
||||
&& cmsg->cmsg_type == IP_RECVDSTADDR) {
|
||||
if (cmsg->cmsg_level == IPPROTO_IP &&
|
||||
cmsg->cmsg_type == IP_RECVDSTADDR) {
|
||||
struct in_addr *pi = (void *)CMSG_DATA(cmsg);
|
||||
struct sockaddr_in *a = (struct sockaddr_in *)our_addr;
|
||||
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in)
|
||||
|| pi == NULL)
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in) ||
|
||||
pi == NULL)
|
||||
return -1;
|
||||
|
||||
a->sin_family = AF_INET;
|
||||
@@ -851,14 +868,14 @@ ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
}
|
||||
#endif
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
if (cmsg->cmsg_level == IPPROTO_IPV6
|
||||
&& cmsg->cmsg_type == IPV6_PKTINFO) {
|
||||
if (cmsg->cmsg_level == IPPROTO_IPV6 &&
|
||||
cmsg->cmsg_type == IPV6_PKTINFO) {
|
||||
struct in6_pktinfo *pi = (void *)CMSG_DATA(cmsg);
|
||||
struct sockaddr_in6 *a =
|
||||
(struct sockaddr_in6 *)our_addr;
|
||||
(struct sockaddr_in6 *)our_addr;
|
||||
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in6)
|
||||
|| pi == NULL)
|
||||
if (*our_addrlen < sizeof(struct sockaddr_in6) ||
|
||||
pi == NULL)
|
||||
return -1;
|
||||
|
||||
a->sin6_family = AF_INET6;
|
||||
@@ -917,11 +934,12 @@ size_t oc_strlcpy(char *dst, char const *src, size_t siz)
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++) ;
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
|
||||
return (s - src - 1); /* count does not include NUL */
|
||||
return (s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef COMMON_H
|
||||
# define COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -40,15 +40,17 @@ void *_talloc_size2(void *ctx, size_t size);
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define PROTOBUF_ALLOCATOR(name, pool) \
|
||||
ProtobufCAllocator name = {.alloc = _talloc_size2, .free = _talloc_free2, .allocator_data = pool}
|
||||
#define PROTOBUF_ALLOCATOR(name, pool) \
|
||||
ProtobufCAllocator name = { .alloc = _talloc_size2, \
|
||||
.free = _talloc_free2, \
|
||||
.allocator_data = pool }
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(x,y) (((x)<(y))?(x):(y))
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(x,y) (((x)>(y))?(x):(y))
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
void set_non_block(int fd);
|
||||
@@ -56,56 +58,53 @@ void set_block(int fd);
|
||||
|
||||
ssize_t force_write(int sockfd, const void *buf, size_t len);
|
||||
ssize_t force_read(int sockfd, void *buf, size_t len);
|
||||
ssize_t force_read_timeout(int sockfd, void *buf, size_t len, unsigned sec);
|
||||
ssize_t recv_timeout(int sockfd, void *buf, size_t len, unsigned sec);
|
||||
ssize_t force_read_timeout(int sockfd, void *buf, size_t len, unsigned int sec);
|
||||
ssize_t recv_timeout(int sockfd, void *buf, size_t len, unsigned int sec);
|
||||
|
||||
typedef size_t (*pack_func)(const void*, uint8_t *);
|
||||
typedef size_t (*pack_size_func)(const void*);
|
||||
typedef size_t (*pack_func)(const void *, uint8_t *);
|
||||
typedef size_t (*pack_size_func)(const void *);
|
||||
|
||||
typedef void* (*unpack_func)(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
typedef void *(*unpack_func)(ProtobufCAllocator *allocator, size_t len,
|
||||
const uint8_t *data);
|
||||
|
||||
int send_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
int socketfd,
|
||||
const void* msg, pack_size_func get_size, pack_func pack);
|
||||
int send_socket_msg(void *pool, int fd, uint8_t cmd, int socketfd,
|
||||
const void *msg, pack_size_func get_size, pack_func pack);
|
||||
|
||||
int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd, unsigned timeout);
|
||||
int forward_msg(void *pool, int ifd, uint8_t icmd, int ofd, uint8_t ocmd,
|
||||
unsigned int timeout);
|
||||
|
||||
inline static
|
||||
int send_msg(void *pool, int fd, uint8_t cmd,
|
||||
const void *msg, pack_size_func get_size, pack_func pack)
|
||||
inline static int send_msg(void *pool, int fd, uint8_t cmd, const void *msg,
|
||||
pack_size_func get_size, pack_func pack)
|
||||
{
|
||||
return send_socket_msg(pool, fd, cmd, -1, msg, get_size, pack);
|
||||
}
|
||||
|
||||
int recv_socket_msg(void *pool, int fd, uint8_t cmd, int *socketfd, void **msg,
|
||||
unpack_func, unsigned int timeout);
|
||||
|
||||
int recv_socket_msg(void *pool, int fd, uint8_t cmd,
|
||||
int *socketfd, void** msg, unpack_func, unsigned timeout);
|
||||
|
||||
inline static int recv_msg(void *pool, int fd, uint8_t cmd,
|
||||
void **msg, unpack_func unpack, unsigned timeout)
|
||||
inline static int recv_msg(void *pool, int fd, uint8_t cmd, void **msg,
|
||||
unpack_func unpack, unsigned int timeout)
|
||||
{
|
||||
return recv_socket_msg(pool, fd, cmd, NULL, msg, unpack, timeout);
|
||||
}
|
||||
|
||||
int recv_msg_headers(int fd, uint8_t *cmd, unsigned timeout);
|
||||
int recv_msg_data(int fd, uint8_t *cmd, uint8_t *data, size_t data_size, int *received_fd);
|
||||
int recv_msg_headers(int fd, uint8_t *cmd, unsigned int timeout);
|
||||
int recv_msg_data(int fd, uint8_t *cmd, uint8_t *data, size_t data_size,
|
||||
int *received_fd);
|
||||
|
||||
const char* cmd_request_to_str(unsigned cmd);
|
||||
const char* discon_reason_to_str(unsigned reason);
|
||||
unsigned int discon_reason_to_log_level(unsigned reason);
|
||||
const char *cmd_request_to_str(unsigned int cmd);
|
||||
const char *discon_reason_to_str(unsigned int reason);
|
||||
unsigned int discon_reason_to_log_level(unsigned int reason);
|
||||
|
||||
ssize_t oc_recvfrom_at(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen,
|
||||
struct sockaddr *our_addr, socklen_t *our_addrlen,
|
||||
int def_port);
|
||||
struct sockaddr *src_addr, socklen_t *addrlen,
|
||||
struct sockaddr *our_addr, socklen_t *our_addrlen,
|
||||
int def_port);
|
||||
|
||||
inline static
|
||||
void safe_memset(void *data, int c, size_t size)
|
||||
inline static void safe_memset(void *data, int c, size_t size)
|
||||
{
|
||||
volatile unsigned volatile_zero = 0;
|
||||
volatile char *vdata = (volatile char*)data;
|
||||
volatile char *vdata = (volatile char *)data;
|
||||
|
||||
/* This is based on a nice trick for safe memset,
|
||||
* sent by David Jacobson in the openssl-dev mailing list.
|
||||
@@ -117,8 +116,7 @@ void safe_memset(void *data, int c, size_t size)
|
||||
} while (vdata[volatile_zero] != c);
|
||||
}
|
||||
|
||||
inline static
|
||||
void ms_sleep(unsigned ms)
|
||||
inline static void ms_sleep(unsigned int ms)
|
||||
{
|
||||
struct timespec tv;
|
||||
int ret;
|
||||
@@ -136,17 +134,18 @@ void ms_sleep(unsigned ms)
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
const char *ps_status_to_str(int status, unsigned cookie);
|
||||
const char *ps_status_to_str(int status, unsigned int cookie);
|
||||
|
||||
const char *_vhost_prefix(const char *name);
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t oc_strlcpy(char *dst, char const *src, size_t siz);
|
||||
# define strlcpy oc_strlcpy
|
||||
#define strlcpy oc_strlcpy
|
||||
#endif
|
||||
|
||||
#define SAFE_ID_SIZE (BASE64_ENCODE_RAW_LENGTH(20)+1)
|
||||
char *calc_safe_id(const uint8_t *data, unsigned size, char *output, unsigned output_size);
|
||||
#define SAFE_ID_SIZE (BASE64_ENCODE_RAW_LENGTH(20) + 1)
|
||||
char *calc_safe_id(const uint8_t *data, unsigned int size, char *output,
|
||||
unsigned int output_size);
|
||||
|
||||
extern int saved_argc;
|
||||
extern char **saved_argv;
|
||||
|
||||
@@ -30,13 +30,14 @@
|
||||
#include <hmac.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool hmac_init_key(size_t key_length, uint8_t * key)
|
||||
bool hmac_init_key(size_t key_length, uint8_t *key)
|
||||
{
|
||||
return gnutls_rnd(GNUTLS_RND_RANDOM, key, key_length) == 0;
|
||||
}
|
||||
|
||||
void generate_hmac(size_t key_length, const uint8_t * key, size_t component_count,
|
||||
const hmac_component_st * components, uint8_t digest[HMAC_DIGEST_SIZE])
|
||||
void generate_hmac(size_t key_length, const uint8_t *key,
|
||||
size_t component_count, const hmac_component_st *components,
|
||||
uint8_t digest[HMAC_DIGEST_SIZE])
|
||||
{
|
||||
struct hmac_sha256_ctx ctx;
|
||||
size_t i;
|
||||
@@ -44,10 +45,8 @@ void generate_hmac(size_t key_length, const uint8_t * key, size_t component_coun
|
||||
hmac_sha256_set_key(&ctx, key_length, key);
|
||||
|
||||
for (i = 0; i < component_count; i++) {
|
||||
|
||||
if (components[i].data) {
|
||||
hmac_sha256_update(&ctx,
|
||||
components[i].length,
|
||||
hmac_sha256_update(&ctx, components[i].length,
|
||||
(const uint8_t *)components[i].data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,21 +19,21 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HMAC_H
|
||||
#define HMAC_H
|
||||
#include <stdbool.h>
|
||||
|
||||
#define HMAC_DIGEST_SIZE 32
|
||||
|
||||
bool hmac_init_key(size_t key_length, uint8_t * key);
|
||||
bool hmac_init_key(size_t key_length, uint8_t *key);
|
||||
|
||||
typedef struct hmac_component_st {
|
||||
typedef struct hmac_component_st {
|
||||
size_t length;
|
||||
void * data;
|
||||
void *data;
|
||||
} hmac_component_st;
|
||||
|
||||
void generate_hmac(size_t key_length, const uint8_t * key, size_t component_count,
|
||||
const hmac_component_st * components, uint8_t digest[HMAC_DIGEST_SIZE]);
|
||||
void generate_hmac(size_t key_length, const uint8_t *key,
|
||||
size_t component_count, const hmac_component_st *components,
|
||||
uint8_t digest[HMAC_DIGEST_SIZE]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,7 +61,8 @@ static size_t snapshot_hash_filename(const char *file_name)
|
||||
|
||||
static size_t snapshot_rehash(const void *elem, void *priv)
|
||||
{
|
||||
snapshot_entry_t *entry = (snapshot_entry_t *) elem;
|
||||
snapshot_entry_t *entry = (snapshot_entry_t *)elem;
|
||||
|
||||
return snapshot_hash_filename(entry->name);
|
||||
}
|
||||
|
||||
@@ -71,6 +72,7 @@ static snapshot_entry_t *snapshot_find(struct snapshot_t *snapshot,
|
||||
struct htable_iter iter;
|
||||
size_t hash = snapshot_hash_filename(filename);
|
||||
snapshot_entry_t *entry = htable_firstval(&snapshot->ht, &iter, hash);
|
||||
|
||||
while (entry != NULL) {
|
||||
if (strcmp(entry->name, filename) == 0) {
|
||||
break;
|
||||
@@ -84,6 +86,7 @@ static int snapshot_file_name_from_fd(int fd, char *file_name,
|
||||
size_t file_name_length)
|
||||
{
|
||||
int ret = snprintf(file_name, file_name_length, "/proc/self/fd/%d", fd);
|
||||
|
||||
if (ret >= file_name_length) {
|
||||
return -1;
|
||||
} else {
|
||||
@@ -91,29 +94,28 @@ static int snapshot_file_name_from_fd(int fd, char *file_name,
|
||||
}
|
||||
}
|
||||
|
||||
static int snapshot_add_entry(snapshot_t * snapshot, const char *filename,
|
||||
static int snapshot_add_entry(snapshot_t *snapshot, const char *filename,
|
||||
int fd)
|
||||
{
|
||||
int retval = -1;
|
||||
snapshot_entry_t *entry = NULL;
|
||||
size_t file_name_length = strlen(filename) + 1;
|
||||
entry =
|
||||
(snapshot_entry_t *) talloc_zero_array(snapshot->pool, char,
|
||||
sizeof(uint32_t) +
|
||||
file_name_length);
|
||||
|
||||
entry = (snapshot_entry_t *)talloc_zero_array(
|
||||
snapshot->pool, char, sizeof(uint32_t) + file_name_length);
|
||||
if (entry == NULL)
|
||||
goto cleanup;
|
||||
|
||||
entry->fd = fd;
|
||||
strlcpy((char *)entry->name, filename, file_name_length);
|
||||
|
||||
if (!htable_add
|
||||
(&snapshot->ht, snapshot_hash_filename(entry->name), entry))
|
||||
if (!htable_add(&snapshot->ht, snapshot_hash_filename(entry->name),
|
||||
entry))
|
||||
goto cleanup;
|
||||
|
||||
entry = NULL;
|
||||
retval = 0;
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (entry)
|
||||
talloc_free(entry);
|
||||
|
||||
@@ -138,12 +140,11 @@ int snapshot_init(void *pool, struct snapshot_t **snapshot, const char *prefix)
|
||||
new_snapshot->pool = pool;
|
||||
|
||||
new_snapshot->tmp_filename_template =
|
||||
talloc_array(pool, char, tmp_filename_template_length);
|
||||
talloc_array(pool, char, tmp_filename_template_length);
|
||||
|
||||
if (snprintf
|
||||
((char *)new_snapshot->tmp_filename_template,
|
||||
tmp_filename_template_length, "%sXXXXXX",
|
||||
prefix) >= tmp_filename_template_length)
|
||||
if (snprintf((char *)new_snapshot->tmp_filename_template,
|
||||
tmp_filename_template_length, "%sXXXXXX",
|
||||
prefix) >= tmp_filename_template_length)
|
||||
goto cleanup;
|
||||
|
||||
htable_init(&new_snapshot->ht, snapshot_rehash, new_snapshot);
|
||||
@@ -151,11 +152,11 @@ int snapshot_init(void *pool, struct snapshot_t **snapshot, const char *prefix)
|
||||
|
||||
*snapshot = new_snapshot;
|
||||
new_snapshot = NULL;
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (new_snapshot != NULL) {
|
||||
if (new_snapshot->tmp_filename_template != NULL)
|
||||
talloc_free((char *)new_snapshot->
|
||||
tmp_filename_template);
|
||||
talloc_free(
|
||||
(char *)new_snapshot->tmp_filename_template);
|
||||
talloc_free(new_snapshot);
|
||||
}
|
||||
|
||||
@@ -170,6 +171,7 @@ void snapshot_terminate(struct snapshot_t *snapshot)
|
||||
{
|
||||
struct htable_iter iter;
|
||||
snapshot_entry_t *entry = htable_first(&snapshot->ht, &iter);
|
||||
|
||||
while (entry != NULL) {
|
||||
htable_delval(&snapshot->ht, &iter);
|
||||
close(entry->fd);
|
||||
@@ -203,6 +205,7 @@ int snapshot_create(struct snapshot_t *snapshot, const char *filename)
|
||||
fd_out = mkstemp(tmp_file_name);
|
||||
if (fd_out == -1) {
|
||||
int err = errno;
|
||||
|
||||
fprintf(stderr, ERRSTR "cannot create temp file '%s' : %s\n",
|
||||
tmp_file_name, strerror(err));
|
||||
goto cleanup;
|
||||
@@ -213,10 +216,12 @@ int snapshot_create(struct snapshot_t *snapshot, const char *filename)
|
||||
for (;;) {
|
||||
int byteRead = read(fd_in, buffer, sizeof(buffer));
|
||||
int bytesWritten;
|
||||
|
||||
if (byteRead == 0) {
|
||||
break;
|
||||
} else if (byteRead == -1) {
|
||||
int err = errno;
|
||||
|
||||
fprintf(stderr, ERRSTR " reading %s failed %s\n",
|
||||
filename, strerror(err));
|
||||
goto cleanup;
|
||||
@@ -224,6 +229,7 @@ int snapshot_create(struct snapshot_t *snapshot, const char *filename)
|
||||
bytesWritten = write(fd_out, buffer, byteRead);
|
||||
if (bytesWritten != byteRead) {
|
||||
int err = errno;
|
||||
|
||||
fprintf(stderr,
|
||||
ERRSTR " writing %s failed %s\n",
|
||||
tmp_file_name, strerror(err));
|
||||
@@ -250,7 +256,7 @@ int snapshot_create(struct snapshot_t *snapshot, const char *filename)
|
||||
ret = 0;
|
||||
entry = NULL;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (fd_in != -1)
|
||||
close(fd_in);
|
||||
|
||||
@@ -264,6 +270,7 @@ int snapshot_first(struct snapshot_t *snapshot, struct htable_iter *iter,
|
||||
int *fd, const char **file_name)
|
||||
{
|
||||
snapshot_entry_t *entry = htable_first(&snapshot->ht, iter);
|
||||
|
||||
if (entry == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
@@ -277,6 +284,7 @@ int snapshot_next(struct snapshot_t *snapshot, struct htable_iter *iter,
|
||||
int *fd, const char **file_name)
|
||||
{
|
||||
snapshot_entry_t *entry = htable_next(&snapshot->ht, iter);
|
||||
|
||||
if (entry == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
@@ -290,13 +298,14 @@ int snapshot_restore_entry(struct snapshot_t *snapshot, int fd,
|
||||
const char *file_name)
|
||||
{
|
||||
int ret = snapshot_add_entry(snapshot, file_name, fd);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t snapshot_entry_count(struct snapshot_t * snapshot)
|
||||
size_t snapshot_entry_count(struct snapshot_t *snapshot)
|
||||
{
|
||||
struct htable_iter iter;
|
||||
size_t count = 0;
|
||||
@@ -317,6 +326,7 @@ int snapshot_lookup_filename(struct snapshot_t *snapshot, const char *file_name,
|
||||
char fd_path[128];
|
||||
char *new_file_name = NULL;
|
||||
snapshot_entry_t *entry = snapshot_find(snapshot, file_name);
|
||||
|
||||
if (entry == NULL)
|
||||
goto cleanup;
|
||||
|
||||
@@ -332,7 +342,7 @@ int snapshot_lookup_filename(struct snapshot_t *snapshot, const char *file_name,
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (new_file_name != NULL)
|
||||
talloc_free(new_file_name);
|
||||
|
||||
|
||||
@@ -37,32 +37,23 @@
|
||||
static int send_query(int fd, int inode, int states, int show)
|
||||
{
|
||||
int err;
|
||||
struct sockaddr_nl nladdr = {
|
||||
.nl_family = AF_NETLINK
|
||||
};
|
||||
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct unix_diag_req udr;
|
||||
} req = {
|
||||
.nlh = {
|
||||
.nlmsg_len = sizeof(req),.nlmsg_type =
|
||||
SOCK_DIAG_BY_FAMILY,.nlmsg_flags =
|
||||
NLM_F_REQUEST | (inode ? 0 : NLM_F_DUMP)
|
||||
}
|
||||
,.udr = {
|
||||
.sdiag_family = AF_UNIX,.udiag_states =
|
||||
states,.udiag_show = show,.udiag_ino = inode}
|
||||
};
|
||||
struct iovec iov = {
|
||||
.iov_base = &req,
|
||||
.iov_len = sizeof(req)
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = (void *)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1
|
||||
};
|
||||
} req = { .nlh = { .nlmsg_len = sizeof(req),
|
||||
.nlmsg_type = SOCK_DIAG_BY_FAMILY,
|
||||
.nlmsg_flags = NLM_F_REQUEST |
|
||||
(inode ? 0 : NLM_F_DUMP) },
|
||||
.udr = { .sdiag_family = AF_UNIX,
|
||||
.udiag_states = states,
|
||||
.udiag_show = show,
|
||||
.udiag_ino = inode } };
|
||||
struct iovec iov = { .iov_base = &req, .iov_len = sizeof(req) };
|
||||
struct msghdr msg = { .msg_name = (void *)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1 };
|
||||
|
||||
for (;;) {
|
||||
if (sendmsg(fd, &msg, 0) < 0) {
|
||||
@@ -78,7 +69,7 @@ static int send_query(int fd, int inode, int states, int show)
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*process_response)(const struct unix_diag_msg * diag,
|
||||
typedef int (*process_response)(const struct unix_diag_msg *diag,
|
||||
unsigned int len, void *context);
|
||||
|
||||
struct match_name_context {
|
||||
@@ -95,12 +86,12 @@ static int match_name(const struct unix_diag_msg *diag, unsigned int len,
|
||||
struct rtattr *attr;
|
||||
unsigned int rta_len = len - NLMSG_LENGTH(sizeof(*diag));
|
||||
size_t path_len = 0;
|
||||
char path[sizeof(((struct sockaddr_un *) 0)->sun_path) + 1];
|
||||
char path[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
|
||||
struct unix_diag_rqlen rqlen;
|
||||
int rqlen_valid = 0;
|
||||
|
||||
for (attr = (struct rtattr *)(diag + 1);
|
||||
RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) {
|
||||
for (attr = (struct rtattr *)(diag + 1); RTA_OK(attr, rta_len);
|
||||
attr = RTA_NEXT(attr, rta_len)) {
|
||||
switch (attr->rta_type) {
|
||||
case UNIX_DIAG_NAME:
|
||||
if (!path_len) {
|
||||
@@ -142,22 +133,15 @@ static int receive_responses(int fd, process_response process, void *context)
|
||||
{
|
||||
int err;
|
||||
long buf[8192 / sizeof(long)];
|
||||
struct sockaddr_nl nladdr = {
|
||||
.nl_family = AF_NETLINK
|
||||
};
|
||||
struct iovec iov = {
|
||||
.iov_base = buf,
|
||||
.iov_len = sizeof(buf)
|
||||
};
|
||||
struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK };
|
||||
struct iovec iov = { .iov_base = buf, .iov_len = sizeof(buf) };
|
||||
int flags = 0;
|
||||
|
||||
for (;;) {
|
||||
struct msghdr msg = {
|
||||
.msg_name = (void *)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1
|
||||
};
|
||||
struct msghdr msg = { .msg_name = (void *)&nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1 };
|
||||
|
||||
ssize_t ret = recvmsg(fd, &msg, flags);
|
||||
|
||||
@@ -191,12 +175,14 @@ static int receive_responses(int fd, process_response process, void *context)
|
||||
const struct nlmsgerr *err = NLMSG_DATA(h);
|
||||
|
||||
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"nlmsg_type NLMSG_ERROR has short nlmsg_len %d",
|
||||
h->nlmsg_len);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"nlmsg_type NLMSG_ERROR has short nlmsg_len %d",
|
||||
h->nlmsg_len);
|
||||
} else {
|
||||
oc_syslog(LOG_ERR, "NLM query failed %s",
|
||||
strerror(-err->error));
|
||||
oc_syslog(LOG_ERR,
|
||||
"NLM query failed %s",
|
||||
strerror(-err->error));
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -204,22 +190,23 @@ static int receive_responses(int fd, process_response process, void *context)
|
||||
|
||||
if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
|
||||
oc_syslog(LOG_ERR, "unexpected nlmsg_type %u\n",
|
||||
(unsigned)h->nlmsg_type);
|
||||
(unsigned int)h->nlmsg_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
diag = (const struct unix_diag_msg *)NLMSG_DATA(h);
|
||||
|
||||
if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*diag))) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"nlmsg_type SOCK_DIAG_BY_FAMILY has short nlmsg_len %d",
|
||||
h->nlmsg_len);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"nlmsg_type SOCK_DIAG_BY_FAMILY has short nlmsg_len %d",
|
||||
h->nlmsg_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (diag->udiag_family != AF_UNIX) {
|
||||
oc_syslog(LOG_ERR, "unexpected family %u\n",
|
||||
diag->udiag_family);
|
||||
diag->udiag_family);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -235,10 +222,7 @@ int sockdiag_query_unix_domain_socket_queue_length(const char *socket_name,
|
||||
{
|
||||
int err;
|
||||
int ret = -1;
|
||||
struct match_name_context ctx = {
|
||||
.name = socket_name,
|
||||
.inode = 0
|
||||
};
|
||||
struct match_name_context ctx = { .name = socket_name, .inode = 0 };
|
||||
|
||||
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
|
||||
|
||||
@@ -248,8 +232,8 @@ int sockdiag_query_unix_domain_socket_queue_length(const char *socket_name,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (send_query
|
||||
(fd, 0, 1 << TCP_LISTEN, UDIAG_SHOW_NAME | UDIAG_SHOW_RQLEN))
|
||||
if (send_query(fd, 0, 1 << TCP_LISTEN,
|
||||
UDIAG_SHOW_NAME | UDIAG_SHOW_RQLEN))
|
||||
goto cleanup;
|
||||
|
||||
if (receive_responses(fd, match_name, &ctx))
|
||||
@@ -260,7 +244,7 @@ int sockdiag_query_unix_domain_socket_queue_length(const char *socket_name,
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
int sockdiag_query_unix_domain_socket_queue_length(const char * socket_name, int * sock_rqueue, int * sock_wqueue);
|
||||
int sockdiag_query_unix_domain_socket_queue_length(const char *socket_name,
|
||||
int *sock_rqueue,
|
||||
int *sock_wqueue);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <system.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __linux__
|
||||
# include <sys/prctl.h>
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -47,8 +47,9 @@ void pr_set_undumpable(const char *mod)
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_DUMPABLE, 0) == -1) {
|
||||
int e = errno;
|
||||
oc_syslog(LOG_ERR, "%s: prctl(PR_SET_DUMPABLE) failed %s",
|
||||
mod, strerror(e));
|
||||
|
||||
oc_syslog(LOG_ERR, "%s: prctl(PR_SET_DUMPABLE) failed %s", mod,
|
||||
strerror(e));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -60,17 +61,18 @@ SIGHANDLER_T ocsignal(int signum, SIGHANDLER_T handler)
|
||||
memset(&new_action, 0, sizeof(new_action));
|
||||
|
||||
new_action.sa_handler = handler;
|
||||
sigemptyset (&new_action.sa_mask);
|
||||
sigemptyset(&new_action.sa_mask);
|
||||
new_action.sa_flags = 0;
|
||||
|
||||
sigaction (signum, &new_action, &old_action);
|
||||
sigaction(signum, &new_action, &old_action);
|
||||
return old_action.sa_handler;
|
||||
}
|
||||
|
||||
/* Checks whether the peer in a socket has the expected @uid and @gid.
|
||||
* Returns zero on success.
|
||||
*/
|
||||
int check_upeer_id(const char *mod, int debug, int cfd, uid_t uid, uid_t gid, uid_t *ruid, pid_t *pid)
|
||||
int check_upeer_id(const char *mod, int debug, int cfd, uid_t uid, uid_t gid,
|
||||
uid_t *ruid, pid_t *pid)
|
||||
{
|
||||
int e, ret;
|
||||
#if defined(SO_PEERCRED) && defined(HAVE_STRUCT_UCRED)
|
||||
@@ -85,15 +87,15 @@ int check_upeer_id(const char *mod, int debug, int cfd, uid_t uid, uid_t gid, ui
|
||||
ret = getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len);
|
||||
if (ret == -1) {
|
||||
e = errno;
|
||||
oc_syslog(LOG_ERR, "%s: getsockopt SO_PEERCRED error: %s",
|
||||
mod, strerror(e));
|
||||
oc_syslog(LOG_ERR, "%s: getsockopt SO_PEERCRED error: %s", mod,
|
||||
strerror(e));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (debug >= OCLOG_DEBUG)
|
||||
oc_syslog(LOG_DEBUG,
|
||||
"%s: received request from pid %u and uid %u",
|
||||
mod, (unsigned)cr.pid, (unsigned)cr.uid);
|
||||
"%s: received request from pid %u and uid %u", mod,
|
||||
(unsigned int)cr.pid, (unsigned int)cr.uid);
|
||||
|
||||
if (ruid)
|
||||
*ruid = cr.uid;
|
||||
@@ -102,10 +104,11 @@ int check_upeer_id(const char *mod, int debug, int cfd, uid_t uid, uid_t gid, ui
|
||||
*pid = cr.pid;
|
||||
|
||||
if (cr.uid != 0 && (cr.uid != uid || cr.gid != gid)) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s: received unauthorized request from pid %u and uid %u",
|
||||
mod, (unsigned)cr.pid, (unsigned)cr.uid);
|
||||
return -1;
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s: received unauthorized request from pid %u and uid %u",
|
||||
mod, (unsigned int)cr.pid, (unsigned int)cr.uid);
|
||||
return -1;
|
||||
}
|
||||
#elif defined(HAVE_GETPEEREID)
|
||||
uid_t euid;
|
||||
@@ -115,8 +118,8 @@ int check_upeer_id(const char *mod, int debug, int cfd, uid_t uid, uid_t gid, ui
|
||||
|
||||
if (ret == -1) {
|
||||
e = errno;
|
||||
oc_syslog(LOG_DEBUG, "%s: getpeereid error: %s",
|
||||
mod, strerror(e));
|
||||
oc_syslog(LOG_DEBUG, "%s: getpeereid error: %s", mod,
|
||||
strerror(e));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -128,14 +131,15 @@ int check_upeer_id(const char *mod, int debug, int cfd, uid_t uid, uid_t gid, ui
|
||||
|
||||
if (debug >= OCLOG_DEBUG)
|
||||
oc_syslog(LOG_DEBUG,
|
||||
"%s: received request from a processes with uid %u",
|
||||
mod, (unsigned)euid);
|
||||
"%s: received request from a processes with uid %u",
|
||||
mod, (unsigned int)euid);
|
||||
|
||||
if (euid != 0 && (euid != uid || egid != gid)) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"%s: received unauthorized request from a process with uid %u",
|
||||
mod, (unsigned)euid);
|
||||
return -1;
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"%s: received unauthorized request from a process with uid %u",
|
||||
mod, (unsigned int)euid);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
#error "Unsupported UNIX variant"
|
||||
|
||||
@@ -19,30 +19,29 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef DIE_H
|
||||
# define DIE_H
|
||||
#define DIE_H
|
||||
|
||||
# include <config.h>
|
||||
# include <signal.h>
|
||||
# include <unistd.h>
|
||||
#include <config.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SIGHANDLER_T
|
||||
# define SIGHANDLER_T sighandler_t
|
||||
#define SIGHANDLER_T sighandler_t
|
||||
#elif HAVE_SIG_T
|
||||
# define SIGHANDLER_T sig_t
|
||||
#define SIGHANDLER_T sig_t
|
||||
#elif HAVE___SIGHANDLER_T
|
||||
# define SIGHANDLER_T __sighandler_t
|
||||
#define SIGHANDLER_T __sighandler_t
|
||||
#else
|
||||
typedef void (*sighandler_t)(int);
|
||||
# define SIGHANDLER_T sighandler_t
|
||||
#define SIGHANDLER_T sighandler_t
|
||||
#endif
|
||||
|
||||
void pr_set_undumpable(const char* mod);
|
||||
void pr_set_undumpable(const char *mod);
|
||||
void kill_on_parent_kill(int sig);
|
||||
|
||||
SIGHANDLER_T ocsignal(int signum, SIGHANDLER_T handler);
|
||||
|
||||
int check_upeer_id(const char *mod, int debug, int cfg, uid_t uid, uid_t gid, uid_t *ruid, pid_t *pid);
|
||||
|
||||
|
||||
int check_upeer_id(const char *mod, int debug, int cfg, uid_t uid, uid_t gid,
|
||||
uid_t *ruid, pid_t *pid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,8 @@ static char *find_space(char *str)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void parse_kkdcp_string(char *str, int *socktype, char **_port, char **_server, char **_path, char **_realm)
|
||||
void parse_kkdcp_string(char *str, int *socktype, char **_port, char **_server,
|
||||
char **_path, char **_realm)
|
||||
{
|
||||
char *path, *server, *port, *realm, *p;
|
||||
|
||||
@@ -73,7 +74,7 @@ void parse_kkdcp_string(char *str, int *socktype, char **_port, char **_server,
|
||||
*socktype = SOCK_STREAM;
|
||||
} else {
|
||||
fprintf(stderr, "cannot handle protocol %s\n", server);
|
||||
exit(EXIT_FAILURE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
server += 4;
|
||||
|
||||
@@ -86,7 +87,7 @@ void parse_kkdcp_string(char *str, int *socktype, char **_port, char **_server,
|
||||
*p = 0;
|
||||
p = strchr(server, '[');
|
||||
if (p)
|
||||
server = p+1;
|
||||
server = p + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,13 @@
|
||||
|
||||
#include <vpn.h>
|
||||
|
||||
static int append_port(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, int port, fw_proto_t proto, unsigned negate)
|
||||
static int append_port(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports,
|
||||
int port, fw_proto_t proto, unsigned int negate)
|
||||
{
|
||||
FwPortSt *current;
|
||||
|
||||
*fw_ports = talloc_realloc(pool, *fw_ports, FwPortSt*, (*n_fw_ports)+1);
|
||||
*fw_ports =
|
||||
talloc_realloc(pool, *fw_ports, FwPortSt *, (*n_fw_ports) + 1);
|
||||
if (*fw_ports == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -56,10 +58,11 @@ static int append_port(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, int
|
||||
/* Parse strings of the format tcp(443), udp(111), and fill in
|
||||
* allowed_tcp_ports and allowed_udp_ports.
|
||||
*/
|
||||
int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const char *str)
|
||||
int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports,
|
||||
const char *str)
|
||||
{
|
||||
const char *p, *p2;
|
||||
unsigned finish = 0;
|
||||
unsigned int finish = 0;
|
||||
int port, ret;
|
||||
fw_proto_t proto;
|
||||
int negate = 0, bracket_start = 0;
|
||||
@@ -82,13 +85,14 @@ int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const
|
||||
}
|
||||
|
||||
if (bracket_start == 0) {
|
||||
oc_syslog(LOG_ERR, "no bracket following negation at %d '%s'", (int)(ptrdiff_t)(p-str), str);
|
||||
oc_syslog(LOG_ERR,
|
||||
"no bracket following negation at %d '%s'",
|
||||
(int)(ptrdiff_t)(p - str), str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
|
||||
@@ -111,7 +115,10 @@ int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const
|
||||
proto = PROTO_ESP;
|
||||
p += 3;
|
||||
} else {
|
||||
oc_syslog(LOG_ERR, "unknown protocol on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p-str), str);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"unknown protocol on restrict-user-to-ports at %d '%s'",
|
||||
(int)(ptrdiff_t)(p - str), str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -119,14 +126,18 @@ int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const
|
||||
p++;
|
||||
|
||||
if (*p != '(') {
|
||||
oc_syslog(LOG_ERR, "expected parenthesis on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p-str), str);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"expected parenthesis on restrict-user-to-ports at %d '%s'",
|
||||
(int)(ptrdiff_t)(p - str), str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
p++;
|
||||
port = atoi(p);
|
||||
|
||||
ret = append_port(pool, fw_ports, n_fw_ports, port, proto, negate);
|
||||
ret = append_port(pool, fw_ports, n_fw_ports, port, proto,
|
||||
negate);
|
||||
if (ret < 0) {
|
||||
oc_syslog(LOG_ERR, "memory error");
|
||||
return -1;
|
||||
@@ -134,7 +145,10 @@ int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const
|
||||
|
||||
p2 = strchr(p, ')');
|
||||
if (p2 == NULL) {
|
||||
oc_syslog(LOG_ERR, "expected closing parenthesis on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p-str), str);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"expected closing parenthesis on restrict-user-to-ports at %d '%s'",
|
||||
(int)(ptrdiff_t)(p - str), str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -145,10 +159,13 @@ int cfg_parse_ports(void *pool, FwPortSt ***fw_ports, size_t *n_fw_ports, const
|
||||
if (*p2 == 0 || (negate != 0 && *p2 == ')')) {
|
||||
finish = 1;
|
||||
} else if (*p2 != ',') {
|
||||
oc_syslog(LOG_ERR, "expected comma or end of line on restrict-user-to-ports at %d '%s'", (int)(ptrdiff_t)(p2-str), str);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"expected comma or end of line on restrict-user-to-ports at %d '%s'",
|
||||
(int)(ptrdiff_t)(p2 - str), str);
|
||||
return -1;
|
||||
}
|
||||
p=p2;
|
||||
p = p2;
|
||||
p++;
|
||||
} while (finish == 0);
|
||||
|
||||
|
||||
1412
src/config.c
1412
src/config.c
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,6 @@
|
||||
#define LOG_TRANSFER_DEBUG 2049
|
||||
#define LOG_SENSITIVE 2050
|
||||
|
||||
|
||||
/* User Disconnect reasons (must be > 0) */
|
||||
#define REASON_ANY 1
|
||||
#define REASON_USER_DISCONNECT 2
|
||||
@@ -46,12 +45,12 @@
|
||||
|
||||
/* Debug definitions for logger */
|
||||
#define OCLOG_BASIC 1
|
||||
#define OCLOG_INFO 2
|
||||
#define OCLOG_INFO 2
|
||||
#define OCLOG_DEBUG 3
|
||||
#define OCLOG_HTTP 4
|
||||
#define OCLOG_HTTP 4
|
||||
#define OCLOG_TRANSFERRED 5
|
||||
#define OCLOG_SENSITIVE 8
|
||||
#define OCLOG_TLS 9
|
||||
#define OCLOG_TLS 9
|
||||
|
||||
/* Authentication states */
|
||||
enum {
|
||||
@@ -90,7 +89,7 @@ typedef enum {
|
||||
CMD_SEC_CLI_STATS,
|
||||
|
||||
/* from main to sec-mod and vice versa */
|
||||
MIN_SECM_CMD=239,
|
||||
MIN_SECM_CMD = 239,
|
||||
CMD_SECM_SESSION_OPEN, /* sync: reply is CMD_SECM_SESSION_REPLY */
|
||||
CMD_SECM_SESSION_CLOSE, /* sync: reply is CMD_SECM_CLI_STATS */
|
||||
CMD_SECM_SESSION_REPLY,
|
||||
|
||||
@@ -28,49 +28,43 @@
|
||||
|
||||
/* emulate gnulib's gettime using gettimeofday to avoid linking to
|
||||
* librt */
|
||||
inline static void
|
||||
gettime (struct timespec *t)
|
||||
inline static void gettime(struct timespec *t)
|
||||
{
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME_COARSE)
|
||||
clock_gettime (CLOCK_REALTIME_COARSE, t);
|
||||
clock_gettime(CLOCK_REALTIME_COARSE, t);
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
||||
clock_gettime (CLOCK_REALTIME, t);
|
||||
clock_gettime(CLOCK_REALTIME, t);
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, NULL);
|
||||
t->tv_sec = tv.tv_sec;
|
||||
t->tv_nsec = tv.tv_usec * 1000;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
t->tv_sec = tv.tv_sec;
|
||||
t->tv_nsec = tv.tv_usec * 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static void
|
||||
gettime_realtime (struct timespec *t)
|
||||
inline static void gettime_realtime(struct timespec *t)
|
||||
{
|
||||
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
||||
clock_gettime (CLOCK_REALTIME, t);
|
||||
clock_gettime(CLOCK_REALTIME, t);
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, NULL);
|
||||
t->tv_sec = tv.tv_sec;
|
||||
t->tv_nsec = tv.tv_usec * 1000;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
t->tv_sec = tv.tv_sec;
|
||||
t->tv_nsec = tv.tv_usec * 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static
|
||||
unsigned int
|
||||
timespec_sub_ms (struct timespec *a, struct timespec *b)
|
||||
inline static unsigned int timespec_sub_ms(struct timespec *a,
|
||||
struct timespec *b)
|
||||
{
|
||||
return (a->tv_sec * 1000 + a->tv_nsec / (1000 * 1000) -
|
||||
(b->tv_sec * 1000 + b->tv_nsec / (1000 * 1000)));
|
||||
return (a->tv_sec * 1000 + a->tv_nsec / (1000 * 1000) -
|
||||
(b->tv_sec * 1000 + b->tv_nsec / (1000 * 1000)));
|
||||
}
|
||||
|
||||
|
||||
inline static
|
||||
uint64_t
|
||||
timespec_sub_us (struct timespec *a, struct timespec *b)
|
||||
inline static uint64_t timespec_sub_us(struct timespec *a, struct timespec *b)
|
||||
{
|
||||
return (a->tv_sec * 1000000ULL + a->tv_nsec / (1000) -
|
||||
(b->tv_sec * 1000000ULL + b->tv_nsec / (1000)));
|
||||
return (a->tv_sec * 1000000ULL + a->tv_nsec / (1000) -
|
||||
(b->tv_sec * 1000000ULL + b->tv_nsec / (1000)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
43
src/html.c
43
src/html.c
@@ -29,18 +29,19 @@
|
||||
#include "html.h"
|
||||
#include "log.h"
|
||||
|
||||
char *unescape_html(void *pool, const char *html, unsigned len, unsigned *out_len)
|
||||
char *unescape_html(void *pool, const char *html, unsigned int len,
|
||||
unsigned int *out_len)
|
||||
{
|
||||
char *msg;
|
||||
int pos;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
msg = talloc_size(pool, len + 1);
|
||||
if (msg == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = pos = 0; i < len;) {
|
||||
if (len-pos < 1) {
|
||||
if (len - pos < 1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -68,28 +69,31 @@ char *unescape_html(void *pool, const char *html, unsigned len, unsigned *out_le
|
||||
char *endptr = NULL;
|
||||
long val;
|
||||
|
||||
if (p[2]=='x') {
|
||||
if (p[2] == 'x') {
|
||||
p += 3;
|
||||
val = strtol(p, &endptr, 16);
|
||||
} else {
|
||||
p += 2;
|
||||
val = strtol(p, &endptr, 10);
|
||||
}
|
||||
if (endptr == NULL || *endptr != ';' || val > WCHAR_MAX) {
|
||||
if (endptr == NULL || *endptr != ';' ||
|
||||
val > WCHAR_MAX) {
|
||||
/* skip */
|
||||
msg[pos++] = html[i++];
|
||||
} else {
|
||||
char tmpmb[MB_CUR_MAX];
|
||||
wchar_t ch = val;
|
||||
mbstate_t ps;
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
|
||||
i += (ptrdiff_t)(1+endptr-(&html[i]));
|
||||
i += (ptrdiff_t)(1 + endptr -
|
||||
(&html[i]));
|
||||
val = wcrtomb(tmpmb, ch, &ps);
|
||||
|
||||
if (val == -1)
|
||||
goto fail;
|
||||
if (len-pos > val)
|
||||
if (len - pos > val)
|
||||
memcpy(&msg[pos], tmpmb, val);
|
||||
else
|
||||
goto fail;
|
||||
@@ -106,16 +110,17 @@ char *unescape_html(void *pool, const char *html, unsigned len, unsigned *out_le
|
||||
*out_len = pos;
|
||||
|
||||
return msg;
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *unescape_url(void *pool, const char *url, unsigned len, unsigned *out_len)
|
||||
char *unescape_url(void *pool, const char *url, unsigned int len,
|
||||
unsigned int *out_len)
|
||||
{
|
||||
char *msg;
|
||||
int pos;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
msg = talloc_size(pool, len + 1);
|
||||
if (msg == NULL)
|
||||
@@ -132,7 +137,8 @@ char *unescape_url(void *pool, const char *url, unsigned len, unsigned *out_len)
|
||||
|
||||
if (sscanf(b, "%02x", &u) <= 0) {
|
||||
talloc_free(msg);
|
||||
oc_syslog(LOG_ERR, "%s: error parsing URL: %s", __func__, url);
|
||||
oc_syslog(LOG_ERR, "%s: error parsing URL: %s",
|
||||
__func__, url);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -152,25 +158,28 @@ char *unescape_url(void *pool, const char *url, unsigned len, unsigned *out_len)
|
||||
return msg;
|
||||
}
|
||||
|
||||
char *escape_url(void *pool, const char *url, unsigned len, unsigned *out_len)
|
||||
char *escape_url(void *pool, const char *url, unsigned int len,
|
||||
unsigned int *out_len)
|
||||
{
|
||||
char *msg;
|
||||
int pos;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
msg = talloc_size(pool, 3*len + 1);
|
||||
msg = talloc_size(pool, 3 * len + 1);
|
||||
if (msg == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = pos = 0; i < len;) {
|
||||
if (isalnum(url[i]) || url[i]=='-' || url[i]=='_' || url[i]=='.' || url[i]=='~') {
|
||||
if (isalnum(url[i]) || url[i] == '-' || url[i] == '_' ||
|
||||
url[i] == '.' || url[i] == '~') {
|
||||
msg[pos++] = url[i++];
|
||||
} else if (url[i] == ' ') {
|
||||
msg[pos++] = '+';
|
||||
i++;
|
||||
} else {
|
||||
snprintf(&msg[pos], 4, "%%%02X", (unsigned)url[i++]);
|
||||
pos+=3;
|
||||
snprintf(&msg[pos], 4, "%%%02X",
|
||||
(unsigned int)url[i++]);
|
||||
pos += 3;
|
||||
}
|
||||
}
|
||||
msg[pos] = 0;
|
||||
|
||||
11
src/html.h
11
src/html.h
@@ -19,10 +19,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_HTML_H
|
||||
# define OC_HTML_H
|
||||
#define OC_HTML_H
|
||||
|
||||
char* unescape_html(void *pool, const char *html, unsigned len, unsigned *out_len);
|
||||
char *unescape_url(void *pool, const char *url, unsigned len, unsigned *out_len);
|
||||
char *escape_url(void *pool, const char *url, unsigned len, unsigned *out_len);
|
||||
char *unescape_html(void *pool, const char *html, unsigned int len,
|
||||
unsigned int *out_len);
|
||||
char *unescape_url(void *pool, const char *url, unsigned int len,
|
||||
unsigned int *out_len);
|
||||
char *escape_url(void *pool, const char *url, unsigned int len,
|
||||
unsigned int *out_len);
|
||||
|
||||
#endif
|
||||
|
||||
169
src/icmp-ping.c
169
src/icmp-ping.c
@@ -74,7 +74,7 @@
|
||||
#include <main.h>
|
||||
#include <net/if.h>
|
||||
#ifdef HAVE_NETINET_IN_SYSTM_H
|
||||
# include <netinet/in_systm.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#endif
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
@@ -89,11 +89,11 @@
|
||||
#include <poll.h>
|
||||
|
||||
#ifndef ICMP_DEST_UNREACH
|
||||
# ifdef ICMP_UNREACH
|
||||
# define ICMP_DEST_UNREACH ICMP_UNREACH
|
||||
# else
|
||||
# define ICMP_DEST_UNREACH 3
|
||||
# endif
|
||||
#ifdef ICMP_UNREACH
|
||||
#define ICMP_DEST_UNREACH ICMP_UNREACH
|
||||
#else
|
||||
#define ICMP_DEST_UNREACH 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* I see RENUMBERED constants in bits/in.h - !!?
|
||||
@@ -110,7 +110,7 @@ enum {
|
||||
MAXPACKET = 65468,
|
||||
MAX_DUP_CHK = (8 * 128),
|
||||
MAXWAIT = 10,
|
||||
PINGINTERVAL = 1, /* 1 second */
|
||||
PINGINTERVAL = 1, /* 1 second */
|
||||
};
|
||||
|
||||
/* common routines */
|
||||
@@ -128,7 +128,7 @@ static int in_cksum(unsigned short *buf, int sz)
|
||||
}
|
||||
|
||||
if (nleft == 1) {
|
||||
*(unsigned char *) (&ans) = *(unsigned char *) w;
|
||||
*(unsigned char *)(&ans) = *(unsigned char *)w;
|
||||
sum += ans;
|
||||
}
|
||||
|
||||
@@ -148,29 +148,26 @@ inline static int retry(int e)
|
||||
|
||||
#define PING_TIMEOUT 3
|
||||
|
||||
static
|
||||
ssize_t recvfrom_timeout(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t * addrlen)
|
||||
static ssize_t recvfrom_timeout(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen)
|
||||
{
|
||||
int ret;
|
||||
struct pollfd pfd;
|
||||
struct pollfd pfd;
|
||||
|
||||
pfd.fd = sockfd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
pfd.fd = sockfd;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
ret = poll(&pfd, 1, 250);
|
||||
ret = poll(&pfd, 1, 250);
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
else if (ret > 0)
|
||||
return recvfrom(sockfd, buf, len, 0, src_addr, addrlen);
|
||||
else
|
||||
return -1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1)
|
||||
int icmp_ping4(main_server_st *s, struct sockaddr_in *addr1)
|
||||
{
|
||||
struct icmp *pkt;
|
||||
int pingsock, c, e;
|
||||
@@ -178,14 +175,15 @@ int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1)
|
||||
char buf1[64];
|
||||
time_t now;
|
||||
uint16_t id1;
|
||||
unsigned gotreply = 0, unreachable = 0;
|
||||
unsigned int gotreply = 0, unreachable = 0;
|
||||
|
||||
if (GETCONFIG(s)->ping_leases == 0)
|
||||
return 0;
|
||||
|
||||
if ((e=gnutls_rnd(GNUTLS_RND_NONCE, &id1, sizeof(id1))) < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error in the random generator: %s", gnutls_strerror(e));
|
||||
e = gnutls_rnd(GNUTLS_RND_NONCE, &id1, sizeof(id1));
|
||||
if (e < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "error in the random generator: %s",
|
||||
gnutls_strerror(e));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -197,47 +195,51 @@ int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkt = (struct icmp *) packet1;
|
||||
pkt = (struct icmp *)packet1;
|
||||
memset(pkt, 0, sizeof(packet1));
|
||||
pkt->icmp_type = ICMP_ECHO;
|
||||
pkt->icmp_id = id1;
|
||||
pkt->icmp_cksum =
|
||||
in_cksum((unsigned short *) pkt, sizeof(packet1));
|
||||
pkt->icmp_cksum = in_cksum((unsigned short *)pkt, sizeof(packet1));
|
||||
|
||||
while (sendto(pingsock, packet1, DEFDATALEN + ICMP_MINLEN, 0,
|
||||
(struct sockaddr *) addr1,
|
||||
sizeof(*addr1) == -1) && retry(errno));
|
||||
(struct sockaddr *)addr1, sizeof(*addr1) == -1) &&
|
||||
retry(errno))
|
||||
;
|
||||
/* listen for replies */
|
||||
|
||||
now = time(NULL);
|
||||
while (time(NULL) - now < PING_TIMEOUT
|
||||
&& (unreachable + gotreply) < 2) {
|
||||
while (time(NULL) - now < PING_TIMEOUT &&
|
||||
(unreachable + gotreply) < 2) {
|
||||
struct sockaddr_in from;
|
||||
socklen_t fromlen = sizeof(from);
|
||||
|
||||
c = recvfrom_timeout(pingsock, packet1, sizeof(packet1), 0,
|
||||
(struct sockaddr *) &from, &fromlen);
|
||||
(struct sockaddr *)&from, &fromlen);
|
||||
|
||||
if (c < 0) {
|
||||
continue;
|
||||
} else if (c >= 76 && fromlen == sizeof(struct sockaddr_in)) { /* icmp6_hdr */
|
||||
if (memcmp
|
||||
(SA_IN_P(&from), SA_IN_P(addr1),
|
||||
SA_IN_SIZE(sizeof(*addr1))) == 0) {
|
||||
|
||||
} else if (c >= 76 &&
|
||||
fromlen ==
|
||||
sizeof(struct sockaddr_in)) { /* icmp6_hdr */
|
||||
if (memcmp(SA_IN_P(&from), SA_IN_P(addr1),
|
||||
SA_IN_SIZE(sizeof(*addr1))) == 0) {
|
||||
#ifdef HAVE_STRUCT_IPHDR_IHL
|
||||
struct iphdr *iphdr =
|
||||
(struct iphdr *) packet1;
|
||||
pkt = (struct icmp *) (packet1 + (iphdr->ihl << 2)); /* skip ip hdr */
|
||||
struct iphdr *iphdr = (struct iphdr *)packet1;
|
||||
pkt = (struct icmp *)(packet1 +
|
||||
(iphdr->ihl
|
||||
<< 2)); /* skip ip hdr */
|
||||
#else
|
||||
pkt = (struct icmp *) (packet1 + ((packet1[0] & 0x0f) << 2)); /* skip ip hdr */
|
||||
pkt = (struct icmp *)(packet1 +
|
||||
((packet1[0] & 0x0f)
|
||||
<< 2)); /* skip ip hdr */
|
||||
#endif
|
||||
if (pkt->icmp_id == id1) {
|
||||
if (pkt->icmp_type == ICMP_ECHOREPLY)
|
||||
gotreply++;
|
||||
else if (pkt->icmp_type == ICMP_DEST_UNREACH)
|
||||
else if (pkt->icmp_type ==
|
||||
ICMP_DEST_UNREACH)
|
||||
unreachable++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,24 +247,19 @@ int icmp_ping4(main_server_st * s, struct sockaddr_in *addr1)
|
||||
close(pingsock);
|
||||
|
||||
if (gotreply > 0) {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"pinged %s and is in use",
|
||||
human_addr((void *) addr1,
|
||||
sizeof(struct sockaddr_in), buf1,
|
||||
sizeof(buf1)));
|
||||
mslog(s, NULL, LOG_INFO, "pinged %s and is in use",
|
||||
human_addr((void *)addr1, sizeof(struct sockaddr_in),
|
||||
buf1, sizeof(buf1)));
|
||||
return gotreply;
|
||||
} else {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"pinged %s and is not in use",
|
||||
human_addr((void *) addr1,
|
||||
sizeof(struct sockaddr_in), buf1,
|
||||
sizeof(buf1)));
|
||||
mslog(s, NULL, LOG_INFO, "pinged %s and is not in use",
|
||||
human_addr((void *)addr1, sizeof(struct sockaddr_in),
|
||||
buf1, sizeof(buf1)));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int icmp_ping6(main_server_st * s,
|
||||
struct sockaddr_in6 *addr1)
|
||||
int icmp_ping6(main_server_st *s, struct sockaddr_in6 *addr1)
|
||||
{
|
||||
struct icmp6_hdr *pkt;
|
||||
char buf1[64];
|
||||
@@ -272,15 +269,16 @@ int icmp_ping6(main_server_st * s,
|
||||
#endif
|
||||
char packet1[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
|
||||
uint16_t id1;
|
||||
unsigned gotreply = 0, unreachable = 0;
|
||||
unsigned int gotreply = 0, unreachable = 0;
|
||||
time_t now;
|
||||
|
||||
if (GETCONFIG(s)->ping_leases == 0)
|
||||
return 0;
|
||||
|
||||
if ((e=gnutls_rnd(GNUTLS_RND_NONCE, &id1, sizeof(id1))) < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error in the random generator: %s", gnutls_strerror(e));
|
||||
e = gnutls_rnd(GNUTLS_RND_NONCE, &id1, sizeof(id1));
|
||||
if (e < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "error in the random generator: %s",
|
||||
gnutls_strerror(e));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -292,43 +290,42 @@ int icmp_ping6(main_server_st * s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkt = (struct icmp6_hdr *) packet1;
|
||||
pkt = (struct icmp6_hdr *)packet1;
|
||||
memset(pkt, 0, sizeof(packet1));
|
||||
pkt->icmp6_type = ICMP6_ECHO_REQUEST;
|
||||
pkt->icmp6_id = id1;
|
||||
|
||||
#if defined(SOL_RAW) && defined(IPV6_CHECKSUM)
|
||||
sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
|
||||
setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM,
|
||||
&sockopt, sizeof(sockopt));
|
||||
setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
|
||||
#endif
|
||||
while (sendto(pingsock, packet1,
|
||||
DEFDATALEN + sizeof(struct icmp6_hdr), 0,
|
||||
(struct sockaddr *) addr1,
|
||||
sizeof(*addr1) == -1) && retry(errno));
|
||||
while (sendto(pingsock, packet1, DEFDATALEN + sizeof(struct icmp6_hdr),
|
||||
0, (struct sockaddr *)addr1, sizeof(*addr1) == -1) &&
|
||||
retry(errno))
|
||||
;
|
||||
|
||||
/* listen for replies */
|
||||
now = time(NULL);
|
||||
while (time(NULL) - now < PING_TIMEOUT
|
||||
&& (unreachable + gotreply) < 2) {
|
||||
while (time(NULL) - now < PING_TIMEOUT &&
|
||||
(unreachable + gotreply) < 2) {
|
||||
struct sockaddr_in6 from;
|
||||
socklen_t fromlen = sizeof(from);
|
||||
c = recvfrom_timeout(pingsock, packet1,
|
||||
sizeof(packet1), 0,
|
||||
(struct sockaddr *)
|
||||
&from, &fromlen);
|
||||
|
||||
c = recvfrom_timeout(pingsock, packet1, sizeof(packet1), 0,
|
||||
(struct sockaddr *)&from, &fromlen);
|
||||
if (c < 0) {
|
||||
continue;
|
||||
} else if (c >= 8 && fromlen == sizeof(struct sockaddr_in6)) { /* icmp6_hdr */
|
||||
if (memcmp
|
||||
(SA_IN6_P(&from), SA_IN6_P(addr1),
|
||||
SA_IN_SIZE(sizeof(*addr1))) == 0) {
|
||||
|
||||
pkt = (struct icmp6_hdr *) packet1;
|
||||
} else if (c >= 8 &&
|
||||
fromlen ==
|
||||
sizeof(struct sockaddr_in6)) { /* icmp6_hdr */
|
||||
if (memcmp(SA_IN6_P(&from), SA_IN6_P(addr1),
|
||||
SA_IN_SIZE(sizeof(*addr1))) == 0) {
|
||||
pkt = (struct icmp6_hdr *)packet1;
|
||||
if (pkt->icmp6_id == id1) {
|
||||
if (pkt->icmp6_type == ICMP6_ECHO_REPLY)
|
||||
gotreply++;
|
||||
else if (pkt->icmp6_type == ICMP6_DST_UNREACH)
|
||||
else if (pkt->icmp6_type ==
|
||||
ICMP6_DST_UNREACH)
|
||||
unreachable++;
|
||||
}
|
||||
}
|
||||
@@ -338,18 +335,14 @@ int icmp_ping6(main_server_st * s,
|
||||
close(pingsock);
|
||||
|
||||
if (gotreply > 0) {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"pinged %s and is in use",
|
||||
human_addr((void *) addr1,
|
||||
sizeof(struct sockaddr_in6), buf1,
|
||||
sizeof(buf1)));
|
||||
mslog(s, NULL, LOG_INFO, "pinged %s and is in use",
|
||||
human_addr((void *)addr1, sizeof(struct sockaddr_in6),
|
||||
buf1, sizeof(buf1)));
|
||||
return gotreply;
|
||||
} else {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"pinged %s and is not in use",
|
||||
human_addr((void *) addr1,
|
||||
sizeof(struct sockaddr_in6), buf1,
|
||||
sizeof(buf1)));
|
||||
mslog(s, NULL, LOG_INFO, "pinged %s and is not in use",
|
||||
human_addr((void *)addr1, sizeof(struct sockaddr_in6),
|
||||
buf1, sizeof(buf1)));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_ICMP_PING_H
|
||||
# define OC_ICMP_PING_H
|
||||
#define OC_ICMP_PING_H
|
||||
|
||||
#include <main.h>
|
||||
|
||||
/* returns the number of positive replies received or
|
||||
* 0 if no host with this IP exists. */
|
||||
int icmp_ping4(main_server_st* s, struct sockaddr_in* addr1);
|
||||
int icmp_ping6(main_server_st* s, struct sockaddr_in6* addr1);
|
||||
int icmp_ping4(main_server_st *s, struct sockaddr_in *addr1);
|
||||
int icmp_ping6(main_server_st *s, struct sockaddr_in6 *addr1);
|
||||
|
||||
#endif
|
||||
|
||||
318
src/ip-lease.c
318
src/ip-lease.c
@@ -27,8 +27,8 @@
|
||||
#include <icmp-ping.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
static void ip_from_seed(uint8_t *seed, unsigned seed_size,
|
||||
void *ip, size_t ip_size)
|
||||
static void ip_from_seed(uint8_t *seed, unsigned int seed_size, void *ip,
|
||||
size_t ip_size)
|
||||
{
|
||||
uint8_t digest[20];
|
||||
int ret;
|
||||
@@ -45,13 +45,12 @@ static void ip_from_seed(uint8_t *seed, unsigned seed_size,
|
||||
}
|
||||
|
||||
memcpy(ip, digest, ip_size);
|
||||
|
||||
}
|
||||
|
||||
void ip_lease_deinit(struct ip_lease_db_st* db)
|
||||
void ip_lease_deinit(struct ip_lease_db_st *db)
|
||||
{
|
||||
struct ip_lease_st * cache;
|
||||
struct htable_iter iter;
|
||||
struct ip_lease_st *cache;
|
||||
struct htable_iter iter;
|
||||
|
||||
cache = htable_first(&db->ht, &iter);
|
||||
while (cache != NULL) {
|
||||
@@ -64,44 +63,46 @@ struct htable_iter iter;
|
||||
htable_clear(&db->ht);
|
||||
}
|
||||
|
||||
static size_t rehash(const void* _e, void* unused)
|
||||
static size_t rehash(const void *_e, void *unused)
|
||||
{
|
||||
const struct ip_lease_st * e = _e;
|
||||
const struct ip_lease_st *e = _e;
|
||||
|
||||
return hash_any(SA_IN_P_GENERIC(&e->sig, e->sig_len), SA_IN_SIZE(e->sig_len), 0);
|
||||
return hash_any(SA_IN_P_GENERIC(&e->sig, e->sig_len),
|
||||
SA_IN_SIZE(e->sig_len), 0);
|
||||
}
|
||||
|
||||
void ip_lease_init(struct ip_lease_db_st* db)
|
||||
void ip_lease_init(struct ip_lease_db_st *db)
|
||||
{
|
||||
htable_init(&db->ht, rehash, NULL);
|
||||
}
|
||||
|
||||
static bool ip_lease_cmp(const void* _c1, void* _c2)
|
||||
static bool ip_lease_cmp(const void *_c1, void *_c2)
|
||||
{
|
||||
const struct ip_lease_st* c1 = _c1;
|
||||
struct ip_lease_st* c2 = _c2;
|
||||
const struct ip_lease_st *c1 = _c1;
|
||||
struct ip_lease_st *c2 = _c2;
|
||||
|
||||
if (c1->sig_len == c2->sig_len &&
|
||||
ip_cmp(&c1->sig, &c2->sig) == 0)
|
||||
if (c1->sig_len == c2->sig_len && ip_cmp(&c1->sig, &c2->sig) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ip_lease_exists(main_server_st* s, struct sockaddr_storage* ip, size_t sockaddrlen)
|
||||
static int ip_lease_exists(main_server_st *s, struct sockaddr_storage *ip,
|
||||
size_t sockaddrlen)
|
||||
{
|
||||
struct ip_lease_st t;
|
||||
struct ip_lease_st t;
|
||||
|
||||
t.sig_len = sockaddrlen;
|
||||
memcpy(&t.sig, ip, sizeof(*ip));
|
||||
|
||||
if (htable_get(&s->ip_leases.ht, rehash(&t, NULL), ip_lease_cmp, &t) != 0)
|
||||
if (htable_get(&s->ip_leases.ht, rehash(&t, NULL), ip_lease_cmp, &t) !=
|
||||
0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void steal_ip_leases(struct proc_st* proc, struct proc_st *thief)
|
||||
void steal_ip_leases(struct proc_st *proc, struct proc_st *thief)
|
||||
{
|
||||
/* here we reset the old tun device, and assign the old addresses
|
||||
* to a new device. We cannot reuse the old device because the
|
||||
@@ -120,9 +121,12 @@ void steal_ip_leases(struct proc_st* proc, struct proc_st *thief)
|
||||
if (proc->ipv4 != NULL) {
|
||||
proc->ipv4->rip_len = thief->ipv4->rip_len;
|
||||
proc->ipv4->lip_len = thief->ipv4->lip_len;
|
||||
memcpy(&proc->ipv4->rip, &thief->ipv4->rip, thief->ipv4->rip_len);
|
||||
memcpy(&proc->ipv4->lip, &thief->ipv4->lip, thief->ipv4->lip_len);
|
||||
memcpy(&proc->ipv4->sig, &thief->ipv4->sig, thief->ipv4->sig_len);
|
||||
memcpy(&proc->ipv4->rip, &thief->ipv4->rip,
|
||||
thief->ipv4->rip_len);
|
||||
memcpy(&proc->ipv4->lip, &thief->ipv4->lip,
|
||||
thief->ipv4->lip_len);
|
||||
memcpy(&proc->ipv4->sig, &thief->ipv4->sig,
|
||||
thief->ipv4->sig_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,14 +137,19 @@ void steal_ip_leases(struct proc_st* proc, struct proc_st *thief)
|
||||
proc->ipv6->prefix = thief->ipv6->prefix;
|
||||
proc->ipv6->rip_len = thief->ipv6->rip_len;
|
||||
proc->ipv6->lip_len = thief->ipv6->lip_len;
|
||||
memcpy(&proc->ipv6->rip, &thief->ipv6->rip, thief->ipv6->rip_len);
|
||||
memcpy(&proc->ipv6->lip, &thief->ipv6->lip, thief->ipv6->lip_len);
|
||||
memcpy(&proc->ipv6->sig, &thief->ipv6->sig, thief->ipv6->sig_len);
|
||||
memcpy(&proc->ipv6->rip, &thief->ipv6->rip,
|
||||
thief->ipv6->rip_len);
|
||||
memcpy(&proc->ipv6->lip, &thief->ipv6->lip,
|
||||
thief->ipv6->lip_len);
|
||||
memcpy(&proc->ipv6->sig, &thief->ipv6->sig,
|
||||
thief->ipv6->sig_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int is_ipv6_ok(main_server_st *s, struct sockaddr_storage *ip, struct sockaddr_storage *tun, struct sockaddr_storage *subnet)
|
||||
static int is_ipv6_ok(main_server_st *s, struct sockaddr_storage *ip,
|
||||
struct sockaddr_storage *tun,
|
||||
struct sockaddr_storage *subnet)
|
||||
{
|
||||
/* check that IP & mask don't match tun IP */
|
||||
if (ip_cmp(subnet, tun) == 0) {
|
||||
@@ -155,19 +164,20 @@ static int is_ipv6_ok(main_server_st *s, struct sockaddr_storage *ip, struct soc
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int is_ipv4_ok(main_server_st *s, struct sockaddr_storage *ip, struct sockaddr_storage *net, struct sockaddr_storage *mask)
|
||||
static int is_ipv4_ok(main_server_st *s, struct sockaddr_storage *ip,
|
||||
struct sockaddr_storage *net,
|
||||
struct sockaddr_storage *mask)
|
||||
{
|
||||
struct sockaddr_storage broadcast;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
memcpy(&broadcast, net, sizeof(broadcast));
|
||||
for (i=0;i<sizeof(struct in_addr);i++) {
|
||||
for (i = 0; i < sizeof(struct in_addr); i++) {
|
||||
SA_IN_U8_P(&broadcast)[i] |= ~(SA_IN_U8_P(mask)[i]);
|
||||
}
|
||||
|
||||
if (ip_lease_exists(s, ip, sizeof(struct sockaddr_in)) != 0 ||
|
||||
ip_cmp(ip, net) == 0 ||
|
||||
ip_cmp(ip, &broadcast) == 0) {
|
||||
ip_cmp(ip, net) == 0 || ip_cmp(ip, &broadcast) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -176,13 +186,11 @@ static int is_ipv4_ok(main_server_st *s, struct sockaddr_storage *ip, struct soc
|
||||
#define MAX_IP_TRIES 16
|
||||
#define FIXED_IPS 5
|
||||
|
||||
static
|
||||
int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
static int get_ipv4_lease(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
|
||||
struct sockaddr_storage tmp, mask, network, rnd;
|
||||
unsigned i;
|
||||
unsigned max_loops = MAX_IP_TRIES;
|
||||
unsigned int i;
|
||||
unsigned int max_loops = MAX_IP_TRIES;
|
||||
int ret;
|
||||
const char *c_network, *c_netmask;
|
||||
char buf[64];
|
||||
@@ -195,7 +203,8 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
c_netmask = proc->config->ipv4_netmask;
|
||||
} else {
|
||||
c_network = proc->vhost->perm_config.config->network.ipv4;
|
||||
c_netmask = proc->vhost->perm_config.config->network.ipv4_netmask;
|
||||
c_netmask =
|
||||
proc->vhost->perm_config.config->network.ipv4_netmask;
|
||||
}
|
||||
|
||||
if (c_network == NULL || c_netmask == NULL) {
|
||||
@@ -203,32 +212,31 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret =
|
||||
inet_pton(AF_INET, c_network, SA_IN_P(&network));
|
||||
ret = inet_pton(AF_INET, c_network, SA_IN_P(&network));
|
||||
if (ret != 1) {
|
||||
mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret =
|
||||
inet_pton(AF_INET, c_netmask, SA_IN_P(&mask));
|
||||
ret = inet_pton(AF_INET, c_netmask, SA_IN_P(&mask));
|
||||
if (ret != 1) {
|
||||
mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* mask the network (just in case it is wrong) */
|
||||
for (i=0;i<sizeof(struct in_addr);i++)
|
||||
for (i = 0; i < sizeof(struct in_addr); i++)
|
||||
SA_IN_U8_P(&network)[i] &= (SA_IN_U8_P(&mask)[i]);
|
||||
((struct sockaddr_in*)&network)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)&network)->sin_port = 0;
|
||||
((struct sockaddr_in *)&network)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)&network)->sin_port = 0;
|
||||
|
||||
if (proc->config->explicit_ipv4) {
|
||||
ret =
|
||||
inet_pton(AF_INET, proc->config->explicit_ipv4, SA_IN_P(&tmp));
|
||||
ret = inet_pton(AF_INET, proc->config->explicit_ipv4,
|
||||
SA_IN_P(&tmp));
|
||||
|
||||
if (ret != 1) {
|
||||
mslog(s, NULL, LOG_ERR, "error reading explicit IP: %s", proc->config->explicit_ipv4);
|
||||
mslog(s, NULL, LOG_ERR, "error reading explicit IP: %s",
|
||||
proc->config->explicit_ipv4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -236,16 +244,19 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
if (proc->ipv4 == NULL)
|
||||
return ERR_MEM;
|
||||
|
||||
((struct sockaddr_in*)&tmp)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)&tmp)->sin_port = 0;
|
||||
((struct sockaddr_in *)&tmp)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)&tmp)->sin_port = 0;
|
||||
memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in));
|
||||
proc->ipv4->rip_len = sizeof(struct sockaddr_in);
|
||||
|
||||
memcpy(&proc->ipv4->sig, &tmp, sizeof(struct sockaddr_in));
|
||||
|
||||
if (is_ipv4_ok(s, &proc->ipv4->rip, &network, &mask) == 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot assign explicit IP %s; it is in use or invalid",
|
||||
human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf)));
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot assign explicit IP %s; it is in use or invalid",
|
||||
human_addr((void *)&tmp,
|
||||
sizeof(struct sockaddr_in), buf,
|
||||
sizeof(buf)));
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
@@ -256,7 +267,9 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
SA_IN_U8_P(&proc->ipv4->lip)[3] |= 1;
|
||||
|
||||
if (ip_cmp(&proc->ipv4->lip, &proc->ipv4->rip) == 0) {
|
||||
mslog(s, NULL, LOG_ERR, "cannot assign explicit IP %s; network: %s", proc->config->explicit_ipv4, c_network);
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"cannot assign explicit IP %s; network: %s",
|
||||
proc->config->explicit_ipv4, c_network);
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
@@ -271,49 +284,59 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
proc->ipv4->db = &s->ip_leases;
|
||||
|
||||
memcpy(&tmp, &network, sizeof(tmp));
|
||||
((struct sockaddr_in*)&tmp)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)&tmp)->sin_port = 0;
|
||||
((struct sockaddr_in *)&tmp)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)&tmp)->sin_port = 0;
|
||||
|
||||
memset(&rnd, 0, sizeof(rnd));
|
||||
((struct sockaddr_in*)&rnd)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)&rnd)->sin_port = 0;
|
||||
((struct sockaddr_in *)&rnd)->sin_family = AF_INET;
|
||||
((struct sockaddr_in *)&rnd)->sin_port = 0;
|
||||
|
||||
do {
|
||||
if (max_loops == 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not figure out a valid IPv4 IP");
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not figure out a valid IPv4 IP");
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
if (max_loops == MAX_IP_TRIES) {
|
||||
memcpy(SA_IN_U8_P(&rnd), proc->ipv4_seed, 4);
|
||||
} else {
|
||||
if (max_loops < MAX_IP_TRIES-FIXED_IPS) {
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, SA_IN_U8_P(&rnd), sizeof(struct in_addr));
|
||||
if (max_loops < MAX_IP_TRIES - FIXED_IPS) {
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE,
|
||||
SA_IN_U8_P(&rnd),
|
||||
sizeof(struct in_addr));
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "error in the random generator: %s", gnutls_strerror(ret));
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error in the random generator: %s",
|
||||
gnutls_strerror(ret));
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
ip_from_seed(SA_IN_U8_P(&rnd), sizeof(struct in_addr),
|
||||
SA_IN_U8_P(&rnd), sizeof(struct in_addr));
|
||||
ip_from_seed(SA_IN_U8_P(&rnd),
|
||||
sizeof(struct in_addr),
|
||||
SA_IN_U8_P(&rnd),
|
||||
sizeof(struct in_addr));
|
||||
}
|
||||
}
|
||||
max_loops--;
|
||||
|
||||
/* Mask the random number with the netmask */
|
||||
for (i=0;i<sizeof(struct in_addr);i++) {
|
||||
for (i = 0; i < sizeof(struct in_addr); i++) {
|
||||
SA_IN_U8_P(&rnd)[i] &= ~(SA_IN_U8_P(&mask)[i]);
|
||||
}
|
||||
|
||||
/* Now add the IP to the masked random number */
|
||||
for (i=0;i<sizeof(struct in_addr);i++)
|
||||
for (i = 0; i < sizeof(struct in_addr); i++)
|
||||
SA_IN_U8_P(&rnd)[i] |= (SA_IN_U8_P(&network)[i]);
|
||||
|
||||
/* check if it exists in the hash table */
|
||||
if (is_ipv4_ok(s, &rnd, &network, &mask) == 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s; it is in use or invalid",
|
||||
human_addr((void*)&rnd, sizeof(struct sockaddr_in), buf, sizeof(buf)));
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot assign remote IP %s; it is in use or invalid",
|
||||
human_addr((void *)&rnd,
|
||||
sizeof(struct sockaddr_in), buf,
|
||||
sizeof(buf)));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -327,34 +350,35 @@ int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
|
||||
proc->ipv4->lip_len = sizeof(struct sockaddr_in);
|
||||
SA_IN_U8_P(&proc->ipv4->lip)[3] |= 1;
|
||||
|
||||
if (memcmp(SA_IN_U8_P(&proc->ipv4->lip), SA_IN_U8_P(&proc->ipv4->rip), sizeof(struct in_addr)) == 0) {
|
||||
if (memcmp(SA_IN_U8_P(&proc->ipv4->lip),
|
||||
SA_IN_U8_P(&proc->ipv4->rip),
|
||||
sizeof(struct in_addr)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mslog(s, proc, LOG_DEBUG, "selected IP: %s",
|
||||
human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf)));
|
||||
human_addr((void *)&proc->ipv4->rip, proc->ipv4->rip_len,
|
||||
buf, sizeof(buf)));
|
||||
|
||||
if (icmp_ping4(s, (void*)&proc->ipv4->rip) == 0)
|
||||
if (icmp_ping4(s, (void *)&proc->ipv4->rip) == 0)
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(proc->ipv4);
|
||||
proc->ipv4 = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
static int get_ipv6_lease(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
|
||||
struct sockaddr_storage tmp, mask, network, rnd, subnet_mask;
|
||||
unsigned i, max_loops = MAX_IP_TRIES;
|
||||
const char* c_network = NULL;
|
||||
unsigned prefix, subnet_prefix ;
|
||||
unsigned int i, max_loops = MAX_IP_TRIES;
|
||||
const char *c_network = NULL;
|
||||
unsigned int prefix, subnet_prefix;
|
||||
int ret;
|
||||
char buf[64];
|
||||
|
||||
@@ -365,7 +389,8 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
} else {
|
||||
c_network = proc->vhost->perm_config.config->network.ipv6;
|
||||
prefix = proc->vhost->perm_config.config->network.ipv6_prefix;
|
||||
subnet_prefix = proc->vhost->perm_config.config->network.ipv6_subnet_prefix;
|
||||
subnet_prefix = proc->vhost->perm_config.config->network
|
||||
.ipv6_subnet_prefix;
|
||||
}
|
||||
|
||||
if (c_network == NULL || prefix == 0 || subnet_prefix == 0) {
|
||||
@@ -380,21 +405,21 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
|
||||
ret = ipv6_prefix_to_mask(SA_IN6_P(&subnet_mask), subnet_prefix);
|
||||
if (ret == 0) {
|
||||
mslog(s, NULL, LOG_ERR, "error reading prefix: %u", subnet_prefix);
|
||||
mslog(s, NULL, LOG_ERR, "error reading prefix: %u",
|
||||
subnet_prefix);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret =
|
||||
inet_pton(AF_INET6, c_network, SA_IN6_P(&network));
|
||||
ret = inet_pton(AF_INET6, c_network, SA_IN6_P(&network));
|
||||
if (ret != 1) {
|
||||
mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* mask the network */
|
||||
((struct sockaddr_in6*)&network)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6*)&network)->sin6_port = 0;
|
||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
||||
((struct sockaddr_in6 *)&network)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)&network)->sin6_port = 0;
|
||||
for (i = 0; i < sizeof(struct in6_addr); i++)
|
||||
SA_IN6_U8_P(&network)[i] &= (SA_IN6_U8_P(&mask)[i]);
|
||||
|
||||
proc->ipv6 = talloc_zero(proc, struct ip_lease_st);
|
||||
@@ -409,26 +434,34 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
|
||||
if (proc->config->explicit_ipv6) {
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
ret =
|
||||
inet_pton(AF_INET6, proc->config->explicit_ipv6, SA_IN6_P(&tmp));
|
||||
ret = inet_pton(AF_INET6, proc->config->explicit_ipv6,
|
||||
SA_IN6_P(&tmp));
|
||||
|
||||
if (ret != 1) {
|
||||
mslog(s, NULL, LOG_ERR, "error reading explicit IP %s", proc->config->explicit_ipv6);
|
||||
mslog(s, NULL, LOG_ERR, "error reading explicit IP %s",
|
||||
proc->config->explicit_ipv6);
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
((struct sockaddr_in6*)&tmp)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)&tmp)->sin6_family = AF_INET6;
|
||||
memcpy(&proc->ipv6->rip, &tmp, sizeof(struct sockaddr_in6));
|
||||
proc->ipv6->rip_len = sizeof(struct sockaddr_in6);
|
||||
|
||||
/* create our sig */
|
||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
||||
SA_IN6_U8_P(&proc->ipv6->sig)[i] = SA_IN6_U8_P(&proc->ipv6->rip)[i] & SA_IN6_U8_P(&subnet_mask)[i];
|
||||
for (i = 0; i < sizeof(struct in6_addr); i++) {
|
||||
uint8_t *p = SA_IN6_U8_P(&proc->ipv6->sig);
|
||||
p[i] = (SA_IN6_U8_P(&proc->ipv6->rip)[i]) &
|
||||
SA_IN6_U8_P(&subnet_mask)[i];
|
||||
}
|
||||
|
||||
if (is_ipv6_ok(s, &tmp, &proc->ipv6->lip, &proc->ipv6->sig) == 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot assign explicit IP %s; it is in use or invalid",
|
||||
human_addr((void*)&tmp, sizeof(struct sockaddr_in6), buf, sizeof(buf)));
|
||||
if (is_ipv6_ok(s, &tmp, &proc->ipv6->lip, &proc->ipv6->sig) ==
|
||||
0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot assign explicit IP %s; it is in use or invalid",
|
||||
human_addr((void *)&tmp,
|
||||
sizeof(struct sockaddr_in6), buf,
|
||||
sizeof(buf)));
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
@@ -440,56 +473,70 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
proc->ipv6->db = &s->ip_leases;
|
||||
|
||||
memcpy(&tmp, &network, sizeof(tmp));
|
||||
((struct sockaddr_in6*)&tmp)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6*)&tmp)->sin6_port = 0;
|
||||
((struct sockaddr_in6 *)&tmp)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)&tmp)->sin6_port = 0;
|
||||
|
||||
do {
|
||||
if (max_loops == 0) {
|
||||
mslog(s, NULL, LOG_ERR, "could not figure out a valid IPv6 IP");
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"could not figure out a valid IPv6 IP");
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memset(&rnd, 0, sizeof(rnd));
|
||||
((struct sockaddr_in6*)&rnd)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)&rnd)->sin6_family = AF_INET6;
|
||||
|
||||
if (max_loops == MAX_IP_TRIES) {
|
||||
ip_from_seed(proc->ipv4_seed, 4,
|
||||
SA_IN6_U8_P(&rnd), sizeof(struct in6_addr));
|
||||
ip_from_seed(proc->ipv4_seed, 4, SA_IN6_U8_P(&rnd),
|
||||
sizeof(struct in6_addr));
|
||||
} else {
|
||||
if (max_loops < MAX_IP_TRIES-FIXED_IPS) {
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, SA_IN_U8_P(&rnd), sizeof(struct in6_addr));
|
||||
if (max_loops < MAX_IP_TRIES - FIXED_IPS) {
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE,
|
||||
SA_IN_U8_P(&rnd),
|
||||
sizeof(struct in6_addr));
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "error in the random generator: %s", gnutls_strerror(ret));
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error in the random generator: %s",
|
||||
gnutls_strerror(ret));
|
||||
ret = ERR_NO_IP;
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
ip_from_seed(SA_IN6_U8_P(&rnd), sizeof(struct in6_addr),
|
||||
SA_IN6_U8_P(&rnd), sizeof(struct in6_addr));
|
||||
ip_from_seed(SA_IN6_U8_P(&rnd),
|
||||
sizeof(struct in6_addr),
|
||||
SA_IN6_U8_P(&rnd),
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
}
|
||||
max_loops--;
|
||||
|
||||
/* Mask the random number with the netmask */
|
||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
||||
for (i = 0; i < sizeof(struct in6_addr); i++)
|
||||
SA_IN6_U8_P(&rnd)[i] &= ~(SA_IN6_U8_P(&mask)[i]);
|
||||
|
||||
/* Now add the network to the masked random number */
|
||||
for (i=0;i<sizeof(struct in6_addr);i++)
|
||||
for (i = 0; i < sizeof(struct in6_addr); i++)
|
||||
SA_IN6_U8_P(&rnd)[i] |= (SA_IN6_U8_P(&network)[i]);
|
||||
|
||||
/* make the sig of our subnet */
|
||||
((struct sockaddr_in6*)&proc->ipv6->sig)->sin6_family = AF_INET6;
|
||||
((struct sockaddr_in6*)&proc->ipv6->sig)->sin6_port = 0;
|
||||
for (i=0;i<sizeof(struct in6_addr);i++) {
|
||||
SA_IN6_U8_P(&proc->ipv6->sig)[i] = SA_IN6_U8_P(&rnd)[i] & SA_IN6_U8_P(&subnet_mask)[i];
|
||||
((struct sockaddr_in6 *)&proc->ipv6->sig)->sin6_family =
|
||||
AF_INET6;
|
||||
((struct sockaddr_in6 *)&proc->ipv6->sig)->sin6_port = 0;
|
||||
for (i = 0; i < sizeof(struct in6_addr); i++) {
|
||||
SA_IN6_U8_P(&proc->ipv6->sig)
|
||||
[i] = SA_IN6_U8_P(&rnd)[i] &
|
||||
SA_IN6_U8_P(&subnet_mask)[i];
|
||||
}
|
||||
|
||||
/* check if it exists in the hash table */
|
||||
if (is_ipv6_ok(s, &rnd, &proc->ipv6->lip, &proc->ipv6->sig) == 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot assign IP %s; it is in use or invalid",
|
||||
human_addr((void*)&rnd, sizeof(struct sockaddr_in6), buf, sizeof(buf)));
|
||||
if (is_ipv6_ok(s, &rnd, &proc->ipv6->lip, &proc->ipv6->sig) ==
|
||||
0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot assign IP %s; it is in use or invalid",
|
||||
human_addr((void *)&rnd,
|
||||
sizeof(struct sockaddr_in6), buf,
|
||||
sizeof(buf)));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -497,26 +544,26 @@ int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
|
||||
memcpy(&proc->ipv6->rip, &rnd, proc->ipv6->rip_len);
|
||||
|
||||
mslog(s, proc, LOG_DEBUG, "selected IP: %s",
|
||||
human_addr((void*)&proc->ipv6->rip, proc->ipv6->rip_len, buf, sizeof(buf)));
|
||||
human_addr((void *)&proc->ipv6->rip, proc->ipv6->rip_len,
|
||||
buf, sizeof(buf)));
|
||||
|
||||
if (proc->ipv6->prefix != 128 || icmp_ping6(s, (void*)&proc->ipv6->rip) == 0)
|
||||
if (proc->ipv6->prefix != 128 ||
|
||||
icmp_ping6(s, (void *)&proc->ipv6->rip) == 0)
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
finish:
|
||||
finish:
|
||||
proc->ipv6->prefix = subnet_prefix;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(proc->ipv6);
|
||||
proc->ipv6 = NULL;
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
int unref_ip_lease(struct ip_lease_st *lease)
|
||||
static int unref_ip_lease(struct ip_lease_st *lease)
|
||||
{
|
||||
if (lease->db) {
|
||||
htable_del(&lease->db->ht, rehash(lease, NULL), lease);
|
||||
@@ -527,8 +574,8 @@ int unref_ip_lease(struct ip_lease_st *lease)
|
||||
|
||||
int get_ip_leases(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
int ret;
|
||||
char buf[128];
|
||||
int ret;
|
||||
char buf[128];
|
||||
|
||||
if (proc->ipv4 == NULL) {
|
||||
ret = get_ipv4_lease(s, proc);
|
||||
@@ -536,8 +583,11 @@ char buf[128];
|
||||
return ret;
|
||||
|
||||
if (proc->ipv4 && proc->ipv4->db) {
|
||||
if (htable_add(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4) == 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table");
|
||||
if (htable_add(&s->ip_leases.ht,
|
||||
rehash(proc->ipv4, NULL),
|
||||
proc->ipv4) == 0) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not add IPv4 lease to hash table");
|
||||
return -1;
|
||||
}
|
||||
talloc_set_destructor(proc->ipv4, unref_ip_lease);
|
||||
@@ -550,8 +600,11 @@ char buf[128];
|
||||
return ret;
|
||||
|
||||
if (proc->ipv6 && proc->ipv6->db) {
|
||||
if (htable_add(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6) == 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table");
|
||||
if (htable_add(&s->ip_leases.ht,
|
||||
rehash(proc->ipv6, NULL),
|
||||
proc->ipv6) == 0) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not add IPv6 lease to hash table");
|
||||
return -1;
|
||||
}
|
||||
talloc_set_destructor(proc->ipv6, unref_ip_lease);
|
||||
@@ -559,23 +612,26 @@ char buf[128];
|
||||
}
|
||||
|
||||
if (proc->ipv4 == 0 && proc->ipv6 == 0) {
|
||||
mslog(s, proc, LOG_ERR, "no IPv4 or IPv6 addresses are configured. Cannot obtain lease");
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"no IPv4 or IPv6 addresses are configured. Cannot obtain lease");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (proc->ipv4)
|
||||
mslog(s, proc, LOG_DEBUG, "assigned IPv4: %s",
|
||||
human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf)));
|
||||
human_addr((void *)&proc->ipv4->rip, proc->ipv4->rip_len,
|
||||
buf, sizeof(buf)));
|
||||
|
||||
if (proc->ipv6)
|
||||
mslog(s, proc, LOG_DEBUG, "assigned IPv6: %s/%u",
|
||||
human_addr((void*)&proc->ipv6->rip, proc->ipv6->rip_len, buf, sizeof(buf)),
|
||||
proc->ipv6->prefix);
|
||||
human_addr((void *)&proc->ipv6->rip, proc->ipv6->rip_len,
|
||||
buf, sizeof(buf)),
|
||||
proc->ipv6->prefix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void remove_ip_leases(main_server_st* s, struct proc_st* proc)
|
||||
void remove_ip_leases(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
if (proc->ipv4) {
|
||||
talloc_free(proc->ipv4);
|
||||
@@ -587,7 +643,7 @@ void remove_ip_leases(main_server_st* s, struct proc_st* proc)
|
||||
}
|
||||
}
|
||||
|
||||
void remove_ip_lease(main_server_st* s, struct ip_lease_st * lease)
|
||||
void remove_ip_lease(main_server_st *s, struct ip_lease_st *lease)
|
||||
{
|
||||
talloc_free(lease);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_IP_LEASE_H
|
||||
# define OC_IP_LEASE_H
|
||||
#define OC_IP_LEASE_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <string.h>
|
||||
@@ -28,28 +28,28 @@
|
||||
#include <main.h>
|
||||
|
||||
struct ip_lease_st {
|
||||
/* In IPv4 this is the same as rip, in IPv6
|
||||
* that's the network address */
|
||||
struct sockaddr_storage sig;
|
||||
/* In IPv4 this is the same as rip, in IPv6
|
||||
* that's the network address */
|
||||
struct sockaddr_storage sig;
|
||||
#define sig_len rip_len
|
||||
|
||||
struct sockaddr_storage rip;
|
||||
socklen_t rip_len;
|
||||
struct sockaddr_storage rip;
|
||||
socklen_t rip_len;
|
||||
|
||||
struct sockaddr_storage lip;
|
||||
socklen_t lip_len;
|
||||
unsigned prefix; /* in ipv6 */
|
||||
struct sockaddr_storage lip;
|
||||
socklen_t lip_len;
|
||||
unsigned int prefix; /* in ipv6 */
|
||||
|
||||
struct ip_lease_db_st* db;
|
||||
struct ip_lease_db_st *db;
|
||||
};
|
||||
|
||||
void ip_lease_deinit(struct ip_lease_db_st* db);
|
||||
void ip_lease_init(struct ip_lease_db_st* db);
|
||||
void ip_lease_deinit(struct ip_lease_db_st *db);
|
||||
void ip_lease_init(struct ip_lease_db_st *db);
|
||||
|
||||
void steal_ip_leases(struct proc_st* proc, struct proc_st *thief);
|
||||
void steal_ip_leases(struct proc_st *proc, struct proc_st *thief);
|
||||
|
||||
int get_ip_leases(struct main_server_st* s, struct proc_st* proc);
|
||||
void remove_ip_leases(struct main_server_st* s, struct proc_st* proc);
|
||||
void remove_ip_lease(main_server_st* s, struct ip_lease_st * lease);
|
||||
int get_ip_leases(struct main_server_st *s, struct proc_st *proc);
|
||||
void remove_ip_leases(struct main_server_st *s, struct proc_st *proc);
|
||||
void remove_ip_lease(main_server_st *s, struct ip_lease_st *lease);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,16 +35,17 @@
|
||||
|
||||
int ip_cmp(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2)
|
||||
{
|
||||
if (((struct sockaddr*)s1)->sa_family == AF_INET) {
|
||||
if (((struct sockaddr *)s1)->sa_family == AF_INET) {
|
||||
return memcmp(SA_IN_P(s1), SA_IN_P(s2), sizeof(struct in_addr));
|
||||
} else { /* inet6 */
|
||||
return memcmp(SA_IN6_P(s1), SA_IN6_P(s2), sizeof(struct in6_addr));
|
||||
return memcmp(SA_IN6_P(s1), SA_IN6_P(s2),
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
}
|
||||
|
||||
/* returns an allocated string with the mask to apply for the prefix
|
||||
*/
|
||||
char* ipv4_prefix_to_strmask(void *pool, unsigned prefix)
|
||||
char *ipv4_prefix_to_strmask(void *pool, unsigned int prefix)
|
||||
{
|
||||
struct in_addr in;
|
||||
char str[MAX_IP_STR];
|
||||
@@ -59,7 +60,7 @@ char* ipv4_prefix_to_strmask(void *pool, unsigned prefix)
|
||||
return talloc_strdup(pool, str);
|
||||
}
|
||||
|
||||
unsigned ipv6_prefix_to_mask(struct in6_addr *in6, unsigned prefix)
|
||||
unsigned int ipv6_prefix_to_mask(struct in6_addr *in6, unsigned int prefix)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@@ -71,7 +72,7 @@ unsigned ipv6_prefix_to_mask(struct in6_addr *in6, unsigned prefix)
|
||||
if (i >= 8) {
|
||||
in6->s6_addr[j] = 0xff;
|
||||
} else {
|
||||
in6->s6_addr[j] = (unsigned long)(0xffU << ( 8 - i ));
|
||||
in6->s6_addr[j] = (unsigned long)(0xffU << (8 - i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +88,7 @@ unsigned ipv6_prefix_to_mask(struct in6_addr *in6, unsigned prefix)
|
||||
int ip_route_sanity_check(void *pool, char **_route)
|
||||
{
|
||||
char *p;
|
||||
unsigned prefix;
|
||||
unsigned int prefix;
|
||||
char *route = *_route, *n;
|
||||
char *slash_ptr, *pstr;
|
||||
|
||||
@@ -98,7 +99,10 @@ int ip_route_sanity_check(void *pool, char **_route)
|
||||
|
||||
p = strchr(p, '/');
|
||||
if (p == NULL) {
|
||||
oc_syslog(LOG_ERR, "route '%s' in wrong format, use xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx\n", route);
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"route '%s' in wrong format, use xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx\n",
|
||||
route);
|
||||
return -1;
|
||||
}
|
||||
slash_ptr = p;
|
||||
@@ -113,7 +117,8 @@ int ip_route_sanity_check(void *pool, char **_route)
|
||||
|
||||
pstr = ipv4_prefix_to_strmask(pool, prefix);
|
||||
if (pstr == NULL) {
|
||||
oc_syslog(LOG_ERR, "cannot figure format of route '%s'\n", route);
|
||||
oc_syslog(LOG_ERR, "cannot figure format of route '%s'\n",
|
||||
route);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -131,8 +136,7 @@ int ip_route_sanity_check(void *pool, char **_route)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int bit_count(uint32_t i)
|
||||
static int bit_count(uint32_t i)
|
||||
{
|
||||
int c = 0;
|
||||
unsigned int seen_one = 0;
|
||||
@@ -157,8 +161,7 @@ static int mask2prefix(struct in_addr mask)
|
||||
return bit_count(ntohl(mask.s_addr));
|
||||
}
|
||||
|
||||
static
|
||||
int ipv4_mask_to_int(const char *prefix)
|
||||
static int ipv4_mask_to_int(const char *prefix)
|
||||
{
|
||||
int ret;
|
||||
struct in_addr in;
|
||||
@@ -188,7 +191,7 @@ char *ipv4_route_to_cidr(void *pool, const char *route)
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
len = (ptrdiff_t)(p-route);
|
||||
len = (ptrdiff_t)(p - route);
|
||||
p++;
|
||||
|
||||
/* if we are in CIDR format exit */
|
||||
@@ -202,14 +205,14 @@ char *ipv4_route_to_cidr(void *pool, const char *route)
|
||||
return talloc_asprintf(pool, "%.*s/%d", len, route, prefix);
|
||||
}
|
||||
|
||||
char *human_addr2(const struct sockaddr *sa, socklen_t salen,
|
||||
void *_buf, size_t buflen, unsigned full)
|
||||
char *human_addr2(const struct sockaddr *sa, socklen_t salen, void *_buf,
|
||||
size_t buflen, unsigned int full)
|
||||
{
|
||||
char *save_buf = _buf;
|
||||
char *buf = _buf;
|
||||
size_t l;
|
||||
const char *ret;
|
||||
unsigned port;
|
||||
unsigned int port;
|
||||
|
||||
if (!buf || !buflen)
|
||||
return NULL;
|
||||
@@ -219,20 +222,26 @@ char *human_addr2(const struct sockaddr *sa, socklen_t salen,
|
||||
}
|
||||
|
||||
if (salen == sizeof(struct sockaddr_in6)) {
|
||||
port = (unsigned)ntohs(((struct sockaddr_in6*)sa)->sin6_port);
|
||||
port = (unsigned int)ntohs(
|
||||
((struct sockaddr_in6 *)sa)->sin6_port);
|
||||
|
||||
if (full != 0 && port != 0) {
|
||||
assert(buflen > 0); /* already checked, but to avoid regression */
|
||||
assert(buflen >
|
||||
0); /* already checked, but to avoid regression */
|
||||
*buf = '[';
|
||||
buf++;
|
||||
buflen--;
|
||||
}
|
||||
|
||||
ret = inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, buf, buflen);
|
||||
ret = inet_ntop(AF_INET6,
|
||||
&((struct sockaddr_in6 *)sa)->sin6_addr, buf,
|
||||
buflen);
|
||||
} else {
|
||||
port = (unsigned)ntohs(((struct sockaddr_in*)sa)->sin_port);
|
||||
port = (unsigned int)ntohs(
|
||||
((struct sockaddr_in *)sa)->sin_port);
|
||||
|
||||
ret = inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, buf, buflen);
|
||||
ret = inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr,
|
||||
buf, buflen);
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
@@ -272,7 +281,7 @@ void set_mtu_disc(int fd, int family, int val)
|
||||
y = val;
|
||||
#if defined(IPV6_DONTFRAG)
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG,
|
||||
(const void *) &y, sizeof(y)) < 0)
|
||||
(const void *)&y, sizeof(y)) < 0)
|
||||
oc_syslog(LOG_INFO, "setsockopt(IPV6_DF) failed");
|
||||
#elif defined(IPV6_MTU_DISCOVER)
|
||||
if (val)
|
||||
@@ -280,14 +289,15 @@ void set_mtu_disc(int fd, int family, int val)
|
||||
else
|
||||
y = IP_PMTUDISC_DONT;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
|
||||
(const void *) &y, sizeof(y)) < 0)
|
||||
oc_syslog(LOG_INFO, "setsockopt(IPV6_MTU_DISCOVER) failed");
|
||||
(const void *)&y, sizeof(y)) < 0)
|
||||
oc_syslog(LOG_INFO,
|
||||
"setsockopt(IPV6_MTU_DISCOVER) failed");
|
||||
#endif
|
||||
} else {
|
||||
y = val;
|
||||
#if defined(IP_DONTFRAG)
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_DONTFRAG,
|
||||
(const void *) &y, sizeof(y)) < 0)
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_DONTFRAG, (const void *)&y,
|
||||
sizeof(y)) < 0)
|
||||
oc_syslog(LOG_INFO, "setsockopt(IP_DF) failed");
|
||||
#elif defined(IP_MTU_DISCOVER)
|
||||
if (val)
|
||||
@@ -295,8 +305,9 @@ void set_mtu_disc(int fd, int family, int val)
|
||||
else
|
||||
y = IP_PMTUDISC_DONT;
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER,
|
||||
(const void *) &y, sizeof(y)) < 0)
|
||||
oc_syslog(LOG_INFO, "setsockopt(IP_MTU_DISCOVER) failed");
|
||||
(const void *)&y, sizeof(y)) < 0)
|
||||
oc_syslog(LOG_INFO,
|
||||
"setsockopt(IP_MTU_DISCOVER) failed");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_IP_UTIL_H
|
||||
# define OC_IP_UTIL_H
|
||||
#define OC_IP_UTIL_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -28,15 +28,16 @@
|
||||
// Lower MTU bound is the value defined in RFC 791
|
||||
#define RFC_791_MTU (68)
|
||||
// Upper bound is the maximum DTLS frame size
|
||||
#define MAX_DTLS_MTU (1<<14)
|
||||
#define MAX_DTLS_MTU (1 << 14)
|
||||
|
||||
void set_mtu_disc(int fd, int family, int val);
|
||||
int ip_route_sanity_check(void *pool, char **_route);
|
||||
|
||||
int ip_cmp(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2);
|
||||
char* ipv4_prefix_to_strmask(void *pool, unsigned prefix);
|
||||
unsigned ipv6_prefix_to_mask(struct in6_addr *in6, unsigned prefix);
|
||||
inline static int valid_ipv6_prefix(unsigned prefix)
|
||||
int ip_cmp(const struct sockaddr_storage *s1,
|
||||
const struct sockaddr_storage *s2);
|
||||
char *ipv4_prefix_to_strmask(void *pool, unsigned int prefix);
|
||||
unsigned int ipv6_prefix_to_mask(struct in6_addr *in6, unsigned int prefix);
|
||||
inline static int valid_ipv6_prefix(unsigned int prefix)
|
||||
{
|
||||
if (prefix > 10 && prefix <= 128)
|
||||
return 1;
|
||||
@@ -48,19 +49,24 @@ char *ipv4_route_to_cidr(void *pool, const char *route);
|
||||
|
||||
/* Helper casts */
|
||||
#define SA_IN_P(p) (&((struct sockaddr_in *)(p))->sin_addr)
|
||||
#define SA_IN_U8_P(p) ((uint8_t*)(&((struct sockaddr_in *)(p))->sin_addr))
|
||||
#define SA_IN_U8_P(p) ((uint8_t *)(&((struct sockaddr_in *)(p))->sin_addr))
|
||||
#define SA_IN6_P(p) (&((struct sockaddr_in6 *)(p))->sin6_addr)
|
||||
#define SA_IN6_U8_P(p) ((uint8_t*)(&((struct sockaddr_in6 *)(p))->sin6_addr))
|
||||
#define SA_IN6_U8_P(p) ((uint8_t *)(&((struct sockaddr_in6 *)(p))->sin6_addr))
|
||||
|
||||
#define SA_IN_PORT(p) (((struct sockaddr_in *)(p))->sin_port)
|
||||
#define SA_IN6_PORT(p) (((struct sockaddr_in6 *)(p))->sin6_port)
|
||||
|
||||
#define SA_IN_P_GENERIC(addr, size) ((size==sizeof(struct sockaddr_in))?SA_IN_U8_P(addr):SA_IN6_U8_P(addr))
|
||||
#define SA_IN_P_TYPE(addr, type) ((type==AF_INET)?SA_IN_U8_P(addr):SA_IN6_U8_P(addr))
|
||||
#define SA_IN_SIZE(size) ((size==sizeof(struct sockaddr_in))?sizeof(struct in_addr):sizeof(struct in6_addr))
|
||||
#define SA_IN_P_GENERIC(addr, size) \
|
||||
((size == sizeof(struct sockaddr_in)) ? SA_IN_U8_P(addr) : \
|
||||
SA_IN6_U8_P(addr))
|
||||
#define SA_IN_P_TYPE(addr, type) \
|
||||
((type == AF_INET) ? SA_IN_U8_P(addr) : SA_IN6_U8_P(addr))
|
||||
#define SA_IN_SIZE(size) \
|
||||
((size == sizeof(struct sockaddr_in)) ? sizeof(struct in_addr) : \
|
||||
sizeof(struct in6_addr))
|
||||
|
||||
char *human_addr2(const struct sockaddr *sa, socklen_t salen,
|
||||
void *buf, size_t buflen, unsigned full);
|
||||
char *human_addr2(const struct sockaddr *sa, socklen_t salen, void *buf,
|
||||
size_t buflen, unsigned int full);
|
||||
|
||||
#define human_addr(x, y, z, w) human_addr2(x, y, z, w, 1)
|
||||
|
||||
|
||||
@@ -35,17 +35,15 @@ void set_worker_fd_limits(struct worker_st *ws)
|
||||
ret = getrlimit(RLIMIT_NOFILE, &def_set);
|
||||
if (ret < 0) {
|
||||
int e = errno;
|
||||
oclog(ws, LOG_ERR,
|
||||
"error in getrlimit: %s\n", strerror(e));
|
||||
|
||||
oclog(ws, LOG_ERR, "error in getrlimit: %s\n", strerror(e));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = setrlimit(RLIMIT_NOFILE, &def_set);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_INFO,
|
||||
"cannot update file limit(%u): %s\n",
|
||||
(unsigned)def_set.rlim_cur,
|
||||
strerror(errno));
|
||||
oclog(ws, LOG_INFO, "cannot update file limit(%u): %s\n",
|
||||
(unsigned int)def_set.rlim_cur, strerror(errno));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -98,7 +96,6 @@ void drop_privileges(struct worker_st *ws, main_server_st *s)
|
||||
oclog(ws, LOG_ERR, "cannot set uid to %d: %s\n",
|
||||
(int)GETPCONFIG(s)->uid, strerror(e));
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#ifndef OC_ISOLATE_H
|
||||
# define OC_ISOLATE_H
|
||||
#define OC_ISOLATE_H
|
||||
|
||||
void set_worker_fd_limits(struct worker_st *);
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <libtasn1.h>
|
||||
|
||||
const asn1_static_node kkdcp_asn1_tab[] = {
|
||||
{ "KKDCP", 536872976, NULL },
|
||||
{ NULL, 1073741836, NULL },
|
||||
{ "KDC-PROXY-MESSAGE", 536870917, NULL },
|
||||
{ "kerb-message", 1610620935, NULL },
|
||||
{ NULL, 2056, "0"},
|
||||
{ "target-domain", 1610637339, NULL },
|
||||
{ NULL, 2056, "1"},
|
||||
{ "dclocator-hint", 536895491, NULL },
|
||||
{ NULL, 2056, "2"},
|
||||
{ NULL, 0, NULL }
|
||||
{ "KKDCP", 536872976, NULL },
|
||||
{ NULL, 1073741836, NULL },
|
||||
{ "KDC-PROXY-MESSAGE", 536870917, NULL },
|
||||
{ "kerb-message", 1610620935, NULL },
|
||||
{ NULL, 2056, "0" },
|
||||
{ "target-domain", 1610637339, NULL },
|
||||
{ NULL, 2056, "1" },
|
||||
{ "dclocator-hint", 536895491, NULL },
|
||||
{ NULL, 2056, "2" },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
/* This global variable is used by oc_syslog() */
|
||||
int global_log_prio = DEFAULT_LOG_LEVEL;
|
||||
|
||||
void __attribute__ ((format(printf, 2, 3)))
|
||||
oc_syslog(int priority, const char *fmt, ...)
|
||||
void __attribute__((format(printf, 2, 3))) oc_syslog(int priority,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
char buf[512];
|
||||
va_list args;
|
||||
|
||||
119
src/log.h
119
src/log.h
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_LOG_H
|
||||
# define OC_LOG_H
|
||||
#define OC_LOG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -31,9 +31,9 @@ extern int global_log_prio;
|
||||
|
||||
/* For logging in the main process or sec-mod use the following:
|
||||
* mslog(const struct main_server_st * s, const struct proc_st* proc,
|
||||
* int priority, const char *fmt, ...);
|
||||
* int priority, const char *fmt, ...);
|
||||
* seclog(const struct sec_mod_st* sec, int priority, const char *fmt, ...);
|
||||
* int priority, const char *fmt, ...);
|
||||
* int priority, const char *fmt, ...);
|
||||
*
|
||||
* For logging in the worker process:
|
||||
* oclog(const struct worker_st * server, int priority, const char *fmt, ...);
|
||||
@@ -47,28 +47,32 @@ extern int global_log_prio;
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define _oc_syslog(prio, fmt, ...) do { \
|
||||
if (syslog_open) { \
|
||||
syslog(prio, fmt, ## __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, fmt "\n", ## __VA_ARGS__); \
|
||||
}} while(0)
|
||||
#define _oc_syslog(prio, fmt, ...) \
|
||||
do { \
|
||||
if (syslog_open) { \
|
||||
syslog(prio, fmt, ##__VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, fmt "\n", ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define _oc_syslog(prio, ...) do { \
|
||||
if (syslog_open) { \
|
||||
syslog(prio, __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fputc('\n', stderr); \
|
||||
}} while(0)
|
||||
#define _oc_syslog(prio, ...) \
|
||||
do { \
|
||||
if (syslog_open) { \
|
||||
syslog(prio, __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fputc('\n', stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef UNDER_TEST
|
||||
/* for testing */
|
||||
# define mslog(...)
|
||||
# define oclog(...)
|
||||
# define seclog(...)
|
||||
# define oc_syslog _oc_syslog
|
||||
#define mslog(...)
|
||||
#define oclog(...)
|
||||
#define seclog(...)
|
||||
#define oc_syslog _oc_syslog
|
||||
|
||||
#else
|
||||
|
||||
@@ -77,54 +81,56 @@ struct worker_st;
|
||||
struct proc_st;
|
||||
struct sec_mod_st;
|
||||
|
||||
void
|
||||
__attribute__ ((format(printf, 4, 5)))
|
||||
_mslog(const struct main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *fmt, ...);
|
||||
void __attribute__((format(printf, 4, 5)))
|
||||
_mslog(const struct main_server_st *s, const struct proc_st *proc, int priority,
|
||||
const char *fmt, ...);
|
||||
|
||||
void __attribute__ ((format(printf, 3, 4)))
|
||||
_oclog(const struct worker_st * server, int priority, const char *fmt, ...);
|
||||
void __attribute__((format(printf, 3, 4)))
|
||||
_oclog(const struct worker_st *server, int priority, const char *fmt, ...);
|
||||
|
||||
void __attribute__ ((format(printf, 3, 4)))
|
||||
_seclog(const struct sec_mod_st* sec, int priority, const char *fmt, ...);
|
||||
void __attribute__((format(printf, 3, 4)))
|
||||
_seclog(const struct sec_mod_st *sec, int priority, const char *fmt, ...);
|
||||
|
||||
void __attribute__ ((format(printf, 2, 3)))
|
||||
oc_syslog(int priority, const char *fmt, ...);
|
||||
void __attribute__((format(printf, 2, 3))) oc_syslog(int priority,
|
||||
const char *fmt, ...);
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define mslog(s, proc, prio, fmt, ...) \
|
||||
(prio == LOG_ERR) ? _mslog(s, proc, prio, "%s:%d: " fmt, __FILE__, \
|
||||
__LINE__, ##__VA_ARGS__) : \
|
||||
_mslog(s, proc, prio, fmt, ##__VA_ARGS__)
|
||||
|
||||
# ifdef __GNUC__
|
||||
# define mslog(s, proc, prio, fmt, ...) \
|
||||
(prio==LOG_ERR)?_mslog(s, proc, prio, "%s:%d: "fmt, __FILE__, __LINE__, ##__VA_ARGS__): \
|
||||
_mslog(s, proc, prio, fmt, ##__VA_ARGS__)
|
||||
#define oclog(server, prio, fmt, ...) \
|
||||
(prio == LOG_ERR) ? _oclog(server, prio, "%s:%d: " fmt, __FILE__, \
|
||||
__LINE__, ##__VA_ARGS__) : \
|
||||
_oclog(server, prio, fmt, ##__VA_ARGS__)
|
||||
|
||||
# define oclog(server, prio, fmt, ...) \
|
||||
(prio==LOG_ERR)?_oclog(server, prio, "%s:%d: "fmt, __FILE__, __LINE__, ##__VA_ARGS__): \
|
||||
_oclog(server, prio, fmt, ##__VA_ARGS__)
|
||||
#define seclog(sec, prio, fmt, ...) \
|
||||
(prio == LOG_ERR) ? _seclog(sec, prio, "%s:%d: " fmt, __FILE__, \
|
||||
__LINE__, ##__VA_ARGS__) : \
|
||||
_seclog(sec, prio, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define mslog _mslog
|
||||
#define seclog _seclog
|
||||
#define oclog _oclog
|
||||
#endif
|
||||
|
||||
# define seclog(sec, prio, fmt, ...) \
|
||||
(prio==LOG_ERR)?_seclog(sec, prio, "%s:%d: "fmt, __FILE__, __LINE__, ##__VA_ARGS__): \
|
||||
_seclog(sec, prio, fmt, ##__VA_ARGS__)
|
||||
# else
|
||||
# define mslog _mslog
|
||||
# define seclog _seclog
|
||||
# define oclog _oclog
|
||||
# endif
|
||||
void mslog_hex(const struct main_server_st *s, const struct proc_st *proc,
|
||||
int priority, const char *prefix, uint8_t *bin,
|
||||
unsigned int bin_size, unsigned int b64);
|
||||
|
||||
void mslog_hex(const struct main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *prefix, uint8_t* bin, unsigned bin_size, unsigned b64);
|
||||
void oclog_hex(const struct worker_st *ws, int priority, const char *prefix,
|
||||
uint8_t *bin, unsigned int bin_size, unsigned int b64);
|
||||
|
||||
void oclog_hex(const struct worker_st* ws, int priority,
|
||||
const char *prefix, uint8_t* bin, unsigned bin_size, unsigned b64);
|
||||
|
||||
void seclog_hex(const struct sec_mod_st* sec, int priority,
|
||||
const char *prefix, uint8_t* bin, unsigned bin_size, unsigned b64);
|
||||
void seclog_hex(const struct sec_mod_st *sec, int priority, const char *prefix,
|
||||
uint8_t *bin, unsigned int bin_size, unsigned int b64);
|
||||
|
||||
#endif
|
||||
|
||||
/* Returns zero when the given priority is not sufficient
|
||||
* for logging. Updates the priority with */
|
||||
inline static
|
||||
unsigned log_check_priority(int oc_priority, int log_prio, int *syslog_prio)
|
||||
inline static unsigned int log_check_priority(int oc_priority, int log_prio,
|
||||
int *syslog_prio)
|
||||
{
|
||||
switch (oc_priority) {
|
||||
case LOG_ERR:
|
||||
@@ -157,7 +163,6 @@ unsigned log_check_priority(int oc_priority, int log_prio, int *syslog_prio)
|
||||
if (log_prio < OCLOG_TRANSFERRED)
|
||||
return 0;
|
||||
|
||||
|
||||
if (syslog_prio)
|
||||
*syslog_prio = LOG_DEBUG;
|
||||
break;
|
||||
@@ -173,9 +178,9 @@ unsigned log_check_priority(int oc_priority, int log_prio, int *syslog_prio)
|
||||
|
||||
if (syslog_prio)
|
||||
*syslog_prio = LOG_DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* OC_LOG_H */
|
||||
|
||||
122
src/lzs.c
122
src/lzs.c
@@ -23,9 +23,9 @@
|
||||
|
||||
#include "lzs.h"
|
||||
|
||||
#define GET_BITS(bits) \
|
||||
do { \
|
||||
/* Strictly speaking, this check ought to be on \
|
||||
#define GET_BITS(bits) \
|
||||
do { \
|
||||
/* Strictly speaking, this check ought to be on \
|
||||
* (srclen < 1 + (bits_left < bits)). However, when bits == 9 \
|
||||
* the (bits_left < bits) comparison is always true so it \
|
||||
* always comes out as (srclen < 2). \
|
||||
@@ -33,40 +33,43 @@ do { \
|
||||
* reading part of a match encoding. And in that case, there \
|
||||
* damn well ought to be an end marker (7 more bits) after \
|
||||
* what we're reading now, so it's perfectly OK to use \
|
||||
* (srclen < 2) in that case too. And a *lot* cheaper. */ \
|
||||
if (srclen < 2) \
|
||||
return -EINVAL; \
|
||||
/* Explicit comparison with 8 to optimise it into a tautology \
|
||||
* (srclen < 2) in that case too. And a *lot* cheaper. */ \
|
||||
if (srclen < 2) \
|
||||
return -EINVAL; \
|
||||
/* Explicit comparison with 8 to optimise it into a tautology \
|
||||
* in the bits == 9 case, because the compiler doesn't
|
||||
* know that bits_left can never be larger than 8. */ \
|
||||
if (bits >= 8 || bits >= bits_left) { \
|
||||
/* We need *all* the bits that are left in the current \
|
||||
* byte. Take them and bump the input pointer. */ \
|
||||
data = (src[0] << (bits - bits_left)) & ((1 << bits) - 1); \
|
||||
src++; \
|
||||
srclen--; \
|
||||
bits_left += 8 - bits; \
|
||||
if (bits > 8 || bits_left < 8) { \
|
||||
/* We need bits from the next byte too... */ \
|
||||
data |= src[0] >> bits_left; \
|
||||
/* ...if we used *all* of them then (which can \
|
||||
* know that bits_left can never be larger than 8. */ \
|
||||
if (bits >= 8 || bits >= bits_left) { \
|
||||
/* We need *all* the bits that are left in the current \
|
||||
* byte. Take them and bump the input pointer. */ \
|
||||
data = (src[0] << (bits - bits_left)) & \
|
||||
((1 << bits) - 1); \
|
||||
src++; \
|
||||
srclen--; \
|
||||
bits_left += 8 - bits; \
|
||||
if (bits > 8 || bits_left < 8) { \
|
||||
/* We need bits from the next byte too... */ \
|
||||
data |= src[0] >> bits_left; \
|
||||
/* ...if we used *all* of them then (which can \
|
||||
* only happen if bits > 8), then bump the \
|
||||
* input pointer again so we never leave \
|
||||
* bits_left == 0. */ \
|
||||
if (bits > 8 && !bits_left) { \
|
||||
bits_left = 8; \
|
||||
src++; \
|
||||
srclen--; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
/* We need fewer bits than are left in the current byte */ \
|
||||
data = (src[0] >> (bits_left - bits)) & ((1ULL << bits) - 1); \
|
||||
bits_left -= bits; \
|
||||
} \
|
||||
} while (0)
|
||||
* bits_left == 0. */ \
|
||||
if (bits > 8 && !bits_left) { \
|
||||
bits_left = 8; \
|
||||
src++; \
|
||||
srclen--; \
|
||||
} \
|
||||
} \
|
||||
} else { \
|
||||
/* We need fewer bits than are left in the current byte */ \
|
||||
data = (src[0] >> (bits_left - bits)) & \
|
||||
((1ULL << bits) - 1); \
|
||||
bits_left -= bits; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int lzs_decompress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen)
|
||||
int lzs_decompress(unsigned char *dst, int dstlen, const unsigned char *src,
|
||||
int srclen)
|
||||
{
|
||||
int outlen = 0;
|
||||
int bits_left = 8; /* Bits left in the current byte at *src */
|
||||
@@ -140,24 +143,24 @@ int lzs_decompress(unsigned char *dst, int dstlen, const unsigned char *src, int
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#define PUT_BITS(nr, bits) \
|
||||
do { \
|
||||
outbits <<= (nr); \
|
||||
outbits |= (bits); \
|
||||
nr_outbits += (nr); \
|
||||
if ((nr) > 8) { \
|
||||
nr_outbits -= 8; \
|
||||
if (outpos == dstlen) \
|
||||
return -EFBIG; \
|
||||
dst[outpos++] = outbits >> nr_outbits; \
|
||||
} \
|
||||
if (nr_outbits >= 8) { \
|
||||
nr_outbits -= 8; \
|
||||
if (outpos == dstlen) \
|
||||
return -EFBIG; \
|
||||
dst[outpos++] = outbits >> nr_outbits; \
|
||||
} \
|
||||
} while (0)
|
||||
#define PUT_BITS(nr, bits) \
|
||||
do { \
|
||||
outbits <<= (nr); \
|
||||
outbits |= (bits); \
|
||||
nr_outbits += (nr); \
|
||||
if ((nr) > 8) { \
|
||||
nr_outbits -= 8; \
|
||||
if (outpos == dstlen) \
|
||||
return -EFBIG; \
|
||||
dst[outpos++] = outbits >> nr_outbits; \
|
||||
} \
|
||||
if (nr_outbits >= 8) { \
|
||||
nr_outbits -= 8; \
|
||||
if (outpos == dstlen) \
|
||||
return -EFBIG; \
|
||||
dst[outpos++] = outbits >> nr_outbits; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct oc_packed_uint16_t {
|
||||
uint16_t d;
|
||||
@@ -167,7 +170,8 @@ struct oc_packed_uint16_t {
|
||||
* Much of the compression algorithm used here is based very loosely on ideas
|
||||
* from isdn_lzscomp.c by Andre Beck: http://micky.ibh.de/~beck/stuff/lzs4i4l/
|
||||
*/
|
||||
int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen)
|
||||
int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src,
|
||||
int srclen)
|
||||
{
|
||||
int length, offset;
|
||||
int inpos = 0, outpos = 0;
|
||||
@@ -203,7 +207,7 @@ int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int s
|
||||
* offset will yield the previous offset at which the same data hash
|
||||
* value was found.
|
||||
*/
|
||||
#define MAX_HISTORY (1<<11) /* Highest offset LZS can represent is 11 bits */
|
||||
#define MAX_HISTORY (1 << 11) /* Highest offset LZS can represent is 11 bits */
|
||||
uint16_t hash_chain[MAX_HISTORY];
|
||||
|
||||
/* Just in case anyone tries to use this in a more general-purpose
|
||||
@@ -234,10 +238,10 @@ int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int s
|
||||
|
||||
for (; hofs != INVALID_OFS && hofs + MAX_HISTORY > inpos;
|
||||
hofs = hash_chain[hofs & (MAX_HISTORY - 1)]) {
|
||||
|
||||
/* We only get here if longest_match_len is >= 2. We need to find
|
||||
a match of longest_match_len + 1 for it to be interesting. */
|
||||
if (!memcmp(src + hofs + 2, src + inpos + 2, longest_match_len - 1)) {
|
||||
if (!memcmp(src + hofs + 2, src + inpos + 2,
|
||||
longest_match_len - 1)) {
|
||||
longest_match_ofs = hofs;
|
||||
|
||||
do {
|
||||
@@ -248,7 +252,8 @@ int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int s
|
||||
if (longest_match_len + inpos == srclen)
|
||||
goto got_match;
|
||||
|
||||
} while (src[longest_match_len + inpos] == src[longest_match_len + hofs]);
|
||||
} while (src[longest_match_len + inpos] ==
|
||||
src[longest_match_len + hofs]);
|
||||
}
|
||||
|
||||
/* Typical compressor tuning would have a break out of the loop
|
||||
@@ -261,7 +266,7 @@ int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int s
|
||||
something. Anyway, we currently don't give up until we run out
|
||||
of reachable history — maximal compression. */
|
||||
}
|
||||
got_match:
|
||||
got_match:
|
||||
/* Output offset, as 7-bit or 11-bit as appropriate */
|
||||
offset = inpos - longest_match_ofs;
|
||||
length = longest_match_len;
|
||||
@@ -298,7 +303,8 @@ int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int s
|
||||
inpos++;
|
||||
while (--longest_match_len) {
|
||||
hash = HASH(src + inpos);
|
||||
hash_chain[inpos & (MAX_HISTORY - 1)] = hash_table[hash];
|
||||
hash_chain[inpos & (MAX_HISTORY - 1)] =
|
||||
hash_table[hash];
|
||||
hash_table[hash] = inpos++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
*/
|
||||
|
||||
#ifndef OC_LZS_H
|
||||
# define OC_LZS_H
|
||||
#define OC_LZS_H
|
||||
|
||||
int lzs_decompress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen);
|
||||
int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src, int srclen);
|
||||
int lzs_decompress(unsigned char *dst, int dstlen, const unsigned char *src,
|
||||
int srclen);
|
||||
int lzs_compress(unsigned char *dst, int dstlen, const unsigned char *src,
|
||||
int srclen);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include <common.h>
|
||||
|
||||
/* Puts the provided PIN into the config's cgroup */
|
||||
void put_into_cgroup(main_server_st * s, const char *_cgroup, pid_t pid)
|
||||
void put_into_cgroup(main_server_st *s, const char *_cgroup, pid_t pid)
|
||||
{
|
||||
#ifdef __linux__
|
||||
char *name, *p, *savep;
|
||||
@@ -72,8 +72,8 @@ void put_into_cgroup(main_server_st * s, const char *_cgroup, pid_t pid)
|
||||
p = strtok_r(cgroup, ",", &savep);
|
||||
while (p != NULL) {
|
||||
mslog(s, NULL, LOG_DEBUG,
|
||||
"putting process %u to cgroup '%s:%s'", (unsigned)pid, p,
|
||||
name);
|
||||
"putting process %u to cgroup '%s:%s'", (unsigned int)pid,
|
||||
p, name);
|
||||
|
||||
snprintf(file, sizeof(file), "/sys/fs/cgroup/%s/%s/tasks", p,
|
||||
name);
|
||||
@@ -84,7 +84,7 @@ void put_into_cgroup(main_server_st * s, const char *_cgroup, pid_t pid)
|
||||
return;
|
||||
}
|
||||
|
||||
if (fprintf(fd, "%u", (unsigned)pid) <= 0) {
|
||||
if (fprintf(fd, "%u", (unsigned int)pid) <= 0) {
|
||||
mslog(s, NULL, LOG_ERR, "could not write to: %s", file);
|
||||
}
|
||||
fclose(fd);
|
||||
@@ -99,8 +99,7 @@ void put_into_cgroup(main_server_st * s, const char *_cgroup, pid_t pid)
|
||||
#endif
|
||||
}
|
||||
|
||||
int send_cookie_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
AUTHREP r)
|
||||
int send_cookie_auth_reply(main_server_st *s, struct proc_st *proc, AUTHREP r)
|
||||
{
|
||||
AuthCookieReplyMsg msg = AUTH_COOKIE_REPLY_MSG__INIT;
|
||||
int ret;
|
||||
@@ -126,36 +125,43 @@ int send_cookie_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
msg.group_name = proc->groupname;
|
||||
|
||||
if (proc->ipv4 && proc->ipv4->rip_len > 0) {
|
||||
msg.ipv4 = human_addr2((struct sockaddr*)&proc->ipv4->rip, proc->ipv4->rip_len,
|
||||
ipv4, sizeof(ipv4), 0);
|
||||
msg.ipv4_local = human_addr2((struct sockaddr*)&proc->ipv4->lip, proc->ipv4->lip_len,
|
||||
ipv4_local, sizeof(ipv4_local), 0);
|
||||
msg.ipv4 = human_addr2(
|
||||
(struct sockaddr *)&proc->ipv4->rip,
|
||||
proc->ipv4->rip_len, ipv4, sizeof(ipv4), 0);
|
||||
msg.ipv4_local =
|
||||
human_addr2((struct sockaddr *)&proc->ipv4->lip,
|
||||
proc->ipv4->lip_len, ipv4_local,
|
||||
sizeof(ipv4_local), 0);
|
||||
}
|
||||
|
||||
if (proc->ipv6 && proc->ipv6->rip_len > 0) {
|
||||
msg.ipv6 = human_addr2((struct sockaddr*)&proc->ipv6->rip, proc->ipv6->rip_len,
|
||||
ipv6, sizeof(ipv6), 0);
|
||||
msg.ipv6_local = human_addr2((struct sockaddr*)&proc->ipv6->lip, proc->ipv6->lip_len,
|
||||
ipv6_local, sizeof(ipv6_local), 0);
|
||||
msg.ipv6 = human_addr2(
|
||||
(struct sockaddr *)&proc->ipv6->rip,
|
||||
proc->ipv6->rip_len, ipv6, sizeof(ipv6), 0);
|
||||
msg.ipv6_local =
|
||||
human_addr2((struct sockaddr *)&proc->ipv6->lip,
|
||||
proc->ipv6->lip_len, ipv6_local,
|
||||
sizeof(ipv6_local), 0);
|
||||
}
|
||||
|
||||
msg.config = proc->config;
|
||||
|
||||
ret = send_socket_msg_to_worker(s, proc, AUTH_COOKIE_REP, proc->tun_lease.fd,
|
||||
&msg,
|
||||
(pack_size_func)auth_cookie_reply_msg__get_packed_size,
|
||||
(pack_func)auth_cookie_reply_msg__pack);
|
||||
ret = send_socket_msg_to_worker(
|
||||
s, proc, AUTH_COOKIE_REP, proc->tun_lease.fd, &msg,
|
||||
(pack_size_func)auth_cookie_reply_msg__get_packed_size,
|
||||
(pack_func)auth_cookie_reply_msg__pack);
|
||||
} else {
|
||||
msg.reply = AUTH__REP__FAILED;
|
||||
|
||||
ret = send_msg_to_worker(s, proc, AUTH_COOKIE_REP,
|
||||
&msg,
|
||||
(pack_size_func)auth_cookie_reply_msg__get_packed_size,
|
||||
(pack_func)auth_cookie_reply_msg__pack);
|
||||
ret = send_msg_to_worker(
|
||||
s, proc, AUTH_COOKIE_REP, &msg,
|
||||
(pack_size_func)auth_cookie_reply_msg__get_packed_size,
|
||||
(pack_func)auth_cookie_reply_msg__pack);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
int e = errno;
|
||||
|
||||
mslog(s, proc, LOG_ERR, "send_msg: %s", strerror(e));
|
||||
return ret;
|
||||
}
|
||||
@@ -163,10 +169,11 @@ int send_cookie_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_auth_cookie_req(sec_mod_instance_st * sec_mod_instance, struct proc_st* proc,
|
||||
const AuthCookieRequestMsg * req)
|
||||
int handle_auth_cookie_req(sec_mod_instance_st *sec_mod_instance,
|
||||
struct proc_st *proc,
|
||||
const AuthCookieRequestMsg *req)
|
||||
{
|
||||
main_server_st * s = sec_mod_instance->server;
|
||||
main_server_st *s = sec_mod_instance->server;
|
||||
int ret;
|
||||
struct proc_st *old_proc;
|
||||
|
||||
@@ -175,7 +182,8 @@ int handle_auth_cookie_req(sec_mod_instance_st * sec_mod_instance, struct proc_s
|
||||
|
||||
/* generate a new DTLS session ID for each connection, to allow
|
||||
* openconnect of distinguishing when the DTLS key has switched. */
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, proc->dtls_session_id, sizeof(proc->dtls_session_id));
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, proc->dtls_session_id,
|
||||
sizeof(proc->dtls_session_id));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
proc->dtls_session_id_size = sizeof(proc->dtls_session_id);
|
||||
@@ -184,13 +192,15 @@ int handle_auth_cookie_req(sec_mod_instance_st * sec_mod_instance, struct proc_s
|
||||
old_proc = proc_search_sid(s, req->cookie.data);
|
||||
if (old_proc != NULL) {
|
||||
if (old_proc->invalidated != 0) {
|
||||
mslog(s, proc, LOG_ERR, "the reused session has been invalidated");
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"the reused session has been invalidated");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* loads sup config and basic proc info (e.g., username) */
|
||||
ret = session_open(sec_mod_instance, proc, req->cookie.data, req->cookie.len);
|
||||
ret = session_open(sec_mod_instance, proc, req->cookie.data,
|
||||
req->cookie.len);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_INFO, "could not open session");
|
||||
return -1;
|
||||
@@ -204,12 +214,14 @@ int handle_auth_cookie_req(sec_mod_instance_st * sec_mod_instance, struct proc_s
|
||||
/* disconnect and reuse previous session's IPs*/
|
||||
if (old_proc != NULL) {
|
||||
if (strcmp(proc->username, old_proc->username) != 0) {
|
||||
mslog(s, old_proc, LOG_ERR, "the user of the new session doesn't match the old (new: %s)",
|
||||
mslog(s, old_proc, LOG_ERR,
|
||||
"the user of the new session doesn't match the old (new: %s)",
|
||||
proc->username);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mslog(s, old_proc, LOG_INFO, "disconnecting previous user session due to session reuse");
|
||||
mslog(s, old_proc, LOG_INFO,
|
||||
"disconnecting previous user session due to session reuse");
|
||||
|
||||
/* steal its leases */
|
||||
steal_ip_leases(old_proc, proc);
|
||||
@@ -248,20 +260,22 @@ int handle_auth_cookie_req(sec_mod_instance_st * sec_mod_instance, struct proc_s
|
||||
* used had been reused before, and then disconnect the old session
|
||||
* (cookies are unique).
|
||||
*/
|
||||
int check_multiple_users(main_server_st *s, struct proc_st* proc)
|
||||
int check_multiple_users(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
struct proc_st *ctmp = NULL, *cpos;
|
||||
unsigned int entries = 1; /* that one */
|
||||
unsigned max;
|
||||
unsigned int max;
|
||||
|
||||
max = proc->config->max_same_clients;
|
||||
|
||||
if (max == 0)
|
||||
return 0;
|
||||
|
||||
list_for_each_safe(&s->proc_list.head, ctmp, cpos, list) {
|
||||
list_for_each_safe(&s->proc_list.head, ctmp, cpos, list)
|
||||
{
|
||||
if (ctmp != proc && ctmp->pid != -1) {
|
||||
if (!ctmp->pid_killed && strcmp(proc->username, ctmp->username) == 0) {
|
||||
if (!ctmp->pid_killed &&
|
||||
strcmp(proc->username, ctmp->username) == 0) {
|
||||
entries++;
|
||||
|
||||
if (entries > max)
|
||||
|
||||
154
src/main-ban.c
154
src/main-ban.c
@@ -45,11 +45,13 @@
|
||||
#include <ifaddrs.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
static bool if_address_test_local(main_server_st * s, struct sockaddr_storage *addr);
|
||||
static bool if_address_test_local(main_server_st *s,
|
||||
struct sockaddr_storage *addr);
|
||||
|
||||
static size_t rehash(const void *_e, void *unused)
|
||||
{
|
||||
ban_entry_st *e = (void*)_e;
|
||||
ban_entry_st *e = (void *)_e;
|
||||
|
||||
return hash_any(e->ip.ip, e->ip.size, 0);
|
||||
}
|
||||
|
||||
@@ -61,15 +63,16 @@ static bool ban_entry_cmp(const void *_c1, void *_c2)
|
||||
const struct ban_entry_st *c1 = _c1;
|
||||
struct ban_entry_st *c2 = _c2;
|
||||
|
||||
if (c1->ip.size == c2->ip.size && memcmp(c1->ip.ip, c2->ip.ip, c1->ip.size) == 0)
|
||||
if (c1->ip.size == c2->ip.size &&
|
||||
memcmp(c1->ip.ip, c2->ip.ip, c1->ip.size) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *main_ban_db_init(main_server_st *s)
|
||||
{
|
||||
struct htable *db = talloc(s, struct htable);
|
||||
|
||||
if (db == NULL) {
|
||||
oc_syslog(LOG_ERR, "error initializing ban DB\n");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -93,13 +96,13 @@ void main_ban_db_deinit(main_server_st *s)
|
||||
|
||||
#define IS_BANNED(main, entry) (entry->score >= GETCONFIG(main)->max_ban_score)
|
||||
|
||||
unsigned main_ban_db_elems(main_server_st *s)
|
||||
unsigned int main_ban_db_elems(main_server_st *s)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
ban_entry_st *t;
|
||||
struct htable_iter iter;
|
||||
time_t now = time(NULL);
|
||||
unsigned banned = 0;
|
||||
unsigned int banned = 0;
|
||||
|
||||
if (db == NULL || GETCONFIG(s)->max_ban_score == 0)
|
||||
return 0;
|
||||
@@ -122,8 +125,8 @@ static void massage_ipv6_address(ban_entry_st *t)
|
||||
}
|
||||
|
||||
/* returns -1 if the user is already banned, and zero otherwise */
|
||||
static
|
||||
int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_size, unsigned score)
|
||||
static int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip,
|
||||
unsigned int ip_size, unsigned int score)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
struct ban_entry_st *e;
|
||||
@@ -133,9 +136,10 @@ int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_s
|
||||
int ret = 0;
|
||||
char str_ip[MAX_IP_STR];
|
||||
const char *p_str_ip = NULL;
|
||||
unsigned print_msg;
|
||||
unsigned int print_msg;
|
||||
|
||||
if (db == NULL || GETCONFIG(s)->max_ban_score == 0 || ip == NULL || (ip_size != 4 && ip_size != 16))
|
||||
if (db == NULL || GETCONFIG(s)->max_ban_score == 0 || ip == NULL ||
|
||||
(ip_size != 4 && ip_size != 16))
|
||||
return 0;
|
||||
|
||||
memcpy(t.ip.ip, ip, ip_size);
|
||||
@@ -156,7 +160,7 @@ int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_s
|
||||
|
||||
if (htable_add(db, rehash(e, NULL), e) == 0) {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"could not add ban entry to hash table");
|
||||
"could not add ban entry to hash table");
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
@@ -176,7 +180,8 @@ int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_s
|
||||
print_msg = 0;
|
||||
|
||||
/* prevent overflow */
|
||||
e->score = (e->score + score) > e->score ? (e->score + score) : (e->score);
|
||||
e->score = (e->score + score) > e->score ? (e->score + score) :
|
||||
(e->score);
|
||||
|
||||
if (ip_size == 4)
|
||||
p_str_ip = inet_ntop(AF_INET, ip, str_ip, sizeof(str_ip));
|
||||
@@ -187,32 +192,41 @@ int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_s
|
||||
if (print_msg && p_str_ip) {
|
||||
char date[256];
|
||||
struct tm tm;
|
||||
if ((localtime_r(&e->expires, &tm) == NULL) || (strftime(date, sizeof(date), "%a %b %e %H:%M:%S %Y", &tm) == 0)) {
|
||||
|
||||
if ((localtime_r(&e->expires, &tm) == NULL) ||
|
||||
(strftime(date, sizeof(date),
|
||||
"%a %b %e %H:%M:%S %Y", &tm) == 0)) {
|
||||
date[0] = 0;
|
||||
}
|
||||
mslog(s, NULL, LOG_INFO, "added IP '%s' (with score %d) to ban list, will be reset at: %s", str_ip, e->score, date);
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"added IP '%s' (with score %d) to ban list, will be reset at: %s",
|
||||
str_ip, e->score, date);
|
||||
}
|
||||
ret = -1;
|
||||
} else {
|
||||
if (p_str_ip) {
|
||||
mslog(s, NULL, LOG_DEBUG, "added %d points (total %d) for IP '%s' to ban list", score, e->score, str_ip);
|
||||
mslog(s, NULL, LOG_DEBUG,
|
||||
"added %d points (total %d) for IP '%s' to ban list",
|
||||
score, e->score, str_ip);
|
||||
}
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(e);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int add_str_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
int add_str_ip_to_ban_list(main_server_st *s, const char *ip,
|
||||
unsigned int score)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
ban_entry_st t;
|
||||
int ret = 0;
|
||||
|
||||
if (db == NULL || GETCONFIG(s)->max_ban_score == 0 || ip == NULL || ip[0] == 0)
|
||||
if (db == NULL || GETCONFIG(s)->max_ban_score == 0 || ip == NULL ||
|
||||
ip[0] == 0)
|
||||
return 0;
|
||||
|
||||
if (strchr(ip, ':') != 0) {
|
||||
@@ -223,8 +237,7 @@ int add_str_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
t.ip.size = 4;
|
||||
}
|
||||
if (ret != 1) {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"could not read IP: %s", ip);
|
||||
mslog(s, NULL, LOG_INFO, "could not read IP: %s", ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,7 +245,8 @@ int add_str_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
}
|
||||
|
||||
/* returns non-zero if there is an IP removed */
|
||||
int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip, unsigned size)
|
||||
int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip,
|
||||
unsigned int size)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
struct ban_entry_st *e;
|
||||
@@ -243,9 +257,9 @@ int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip, unsigned size)
|
||||
return 0;
|
||||
|
||||
if (size == 4 || size == 16) {
|
||||
if (inet_ntop(size==16?AF_INET6:AF_INET, ip, txt_ip, sizeof(txt_ip)) != NULL) {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"unbanning IP '%s'", txt_ip);
|
||||
if (inet_ntop(size == 16 ? AF_INET6 : AF_INET, ip, txt_ip,
|
||||
sizeof(txt_ip)) != NULL) {
|
||||
mslog(s, NULL, LOG_INFO, "unbanning IP '%s'", txt_ip);
|
||||
}
|
||||
|
||||
t.ip.size = size;
|
||||
@@ -265,12 +279,13 @@ int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip, unsigned size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned check_if_banned(main_server_st *s, struct sockaddr_storage *addr, socklen_t addr_size)
|
||||
unsigned int check_if_banned(main_server_st *s, struct sockaddr_storage *addr,
|
||||
socklen_t addr_size)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
time_t now;
|
||||
ban_entry_st t, *e;
|
||||
unsigned in_size;
|
||||
unsigned int in_size;
|
||||
char txt[MAX_IP_STR];
|
||||
|
||||
if (db == NULL || GETCONFIG(s)->max_ban_score == 0)
|
||||
@@ -279,24 +294,30 @@ unsigned check_if_banned(main_server_st *s, struct sockaddr_storage *addr, sockl
|
||||
(void)(txt);
|
||||
|
||||
if (if_address_test_local(s, addr)) {
|
||||
mslog(s, NULL, LOG_DEBUG, "Not applying ban to local IP: %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), 0));
|
||||
mslog(s, NULL, LOG_DEBUG, "Not applying ban to local IP: %s",
|
||||
human_addr2((struct sockaddr *)addr, addr_size, txt,
|
||||
sizeof(txt), 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
in_size = SA_IN_SIZE(addr_size);
|
||||
if (in_size != 4 && in_size != 16) {
|
||||
mslog(s, NULL, LOG_ERR, "unknown address type for %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), 0));
|
||||
mslog(s, NULL, LOG_ERR, "unknown address type for %s",
|
||||
human_addr2((struct sockaddr *)addr, addr_size, txt,
|
||||
sizeof(txt), 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(t.ip.ip, SA_IN_P_GENERIC(addr, addr_size), SA_IN_SIZE(addr_size));
|
||||
memcpy(t.ip.ip, SA_IN_P_GENERIC(addr, addr_size),
|
||||
SA_IN_SIZE(addr_size));
|
||||
t.ip.size = SA_IN_SIZE(addr_size);
|
||||
|
||||
/* In IPv6 treat a /64 as a single address */
|
||||
massage_ipv6_address(&t);
|
||||
|
||||
/* add its current connection points */
|
||||
add_ip_to_ban_list(s, t.ip.ip, t.ip.size, GETCONFIG(s)->ban_points_connect);
|
||||
add_ip_to_ban_list(s, t.ip.ip, t.ip.size,
|
||||
GETCONFIG(s)->ban_points_connect);
|
||||
|
||||
now = time(NULL);
|
||||
e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
|
||||
@@ -305,7 +326,10 @@ unsigned check_if_banned(main_server_st *s, struct sockaddr_storage *addr, sockl
|
||||
return 0;
|
||||
|
||||
if (e->score >= GETCONFIG(s)->max_ban_score) {
|
||||
mslog(s, NULL, LOG_INFO, "rejected connection from banned IP: %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), 0));
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"rejected connection from banned IP: %s",
|
||||
human_addr2((struct sockaddr *)addr, addr_size,
|
||||
txt, sizeof(txt), 0));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -324,27 +348,30 @@ void cleanup_banned_entries(main_server_st *s)
|
||||
|
||||
t = htable_first(db, &iter);
|
||||
while (t != NULL) {
|
||||
if (now >= t->expires && now > t->last_reset + GETCONFIG(s)->ban_reset_time) {
|
||||
if (now >= t->expires &&
|
||||
now > t->last_reset + GETCONFIG(s)->ban_reset_time) {
|
||||
htable_delval(db, &iter);
|
||||
talloc_free(t);
|
||||
}
|
||||
t = htable_next(db, &iter);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int if_address_init(main_server_st *s)
|
||||
{
|
||||
struct ifaddrs * ifaddr = NULL, *ifa;
|
||||
if_address_st * local_if_addresses = NULL;
|
||||
struct ifaddrs *ifaddr = NULL, *ifa;
|
||||
if_address_st *local_if_addresses = NULL;
|
||||
int retval = 0;
|
||||
unsigned count = 0;
|
||||
unsigned int count = 0;
|
||||
|
||||
s->if_addresses_count = 0;
|
||||
s->if_addresses = NULL;
|
||||
|
||||
if (getifaddrs(&ifaddr) < 0) {
|
||||
int err = errno;
|
||||
oc_syslog(LOG_ERR, "Failed to read local if address list: %s", strerror(err));
|
||||
|
||||
oc_syslog(LOG_ERR, "Failed to read local if address list: %s",
|
||||
strerror(err));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -352,7 +379,7 @@ int if_address_init(main_server_st *s)
|
||||
if (ifa->ifa_addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
count ++;
|
||||
count++;
|
||||
}
|
||||
|
||||
local_if_addresses = talloc_array(s, if_address_st, count);
|
||||
@@ -365,13 +392,16 @@ int if_address_init(main_server_st *s)
|
||||
|
||||
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
||||
sa_family_t family;
|
||||
|
||||
if (ifa->ifa_addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
family = ifa->ifa_addr->sa_family;
|
||||
if (family == AF_INET || family == AF_INET6) {
|
||||
memcpy(&local_if_addresses[count].if_addr, ifa->ifa_addr, sizeof(struct sockaddr));
|
||||
memcpy(&local_if_addresses[count].if_netmask, ifa->ifa_netmask, sizeof(struct sockaddr));
|
||||
memcpy(&local_if_addresses[count].if_addr,
|
||||
ifa->ifa_addr, sizeof(struct sockaddr));
|
||||
memcpy(&local_if_addresses[count].if_netmask,
|
||||
ifa->ifa_netmask, sizeof(struct sockaddr));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -392,45 +422,61 @@ cleanup:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool test_local_ipv4(struct sockaddr_in * remote, struct sockaddr_in * local, struct sockaddr_in * network)
|
||||
static bool test_local_ipv4(struct sockaddr_in *remote,
|
||||
struct sockaddr_in *local,
|
||||
struct sockaddr_in *network)
|
||||
{
|
||||
uint32_t l = local->sin_addr.s_addr & network->sin_addr.s_addr;
|
||||
uint32_t r = remote->sin_addr.s_addr & network->sin_addr.s_addr;
|
||||
|
||||
if (l != r)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_local_ipv6(struct sockaddr_in6 * remote, struct sockaddr_in6 * local, struct sockaddr_in6 * network)
|
||||
static bool test_local_ipv6(struct sockaddr_in6 *remote,
|
||||
struct sockaddr_in6 *local,
|
||||
struct sockaddr_in6 *network)
|
||||
{
|
||||
unsigned index = 0;
|
||||
unsigned int index = 0;
|
||||
|
||||
for (index = 0; index < 4; index++) {
|
||||
uint32_t l = local->sin6_addr.s6_addr32[index] &
|
||||
network->sin6_addr.s6_addr32[index];
|
||||
uint32_t r = remote->sin6_addr.s6_addr32[index] &
|
||||
network->sin6_addr.s6_addr32[index];
|
||||
|
||||
for (index = 0; index < 4; index ++) {
|
||||
uint32_t l = local->sin6_addr.s6_addr32[index] & network->sin6_addr.s6_addr32[index];
|
||||
uint32_t r = remote->sin6_addr.s6_addr32[index] & network->sin6_addr.s6_addr32[index];
|
||||
if (l != r)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool if_address_test_local(main_server_st * s, struct sockaddr_storage *addr)
|
||||
static bool if_address_test_local(main_server_st *s,
|
||||
struct sockaddr_storage *addr)
|
||||
{
|
||||
unsigned index;
|
||||
for (index = 0; index < s->if_addresses_count; index ++)
|
||||
{
|
||||
if_address_st * ifa = &s->if_addresses[index];
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0; index < s->if_addresses_count; index++) {
|
||||
if_address_st *ifa = &s->if_addresses[index];
|
||||
|
||||
if (ifa->if_addr.sa_family != addr->ss_family)
|
||||
continue;
|
||||
|
||||
switch (addr->ss_family) {
|
||||
case AF_INET:
|
||||
if (test_local_ipv4((struct sockaddr_in *)addr, (struct sockaddr_in *)&ifa->if_addr, (struct sockaddr_in *)&ifa->if_netmask))
|
||||
if (test_local_ipv4(
|
||||
(struct sockaddr_in *)addr,
|
||||
(struct sockaddr_in *)&ifa->if_addr,
|
||||
(struct sockaddr_in *)&ifa->if_netmask))
|
||||
return true;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (test_local_ipv6((struct sockaddr_in6 *)addr, (struct sockaddr_in6 *)&ifa->if_addr, (struct sockaddr_in6 *)&ifa->if_netmask))
|
||||
if (test_local_ipv6(
|
||||
(struct sockaddr_in6 *)addr,
|
||||
(struct sockaddr_in6 *)&ifa->if_addr,
|
||||
(struct sockaddr_in6 *)&ifa->if_netmask))
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
@@ -440,7 +486,7 @@ static bool if_address_test_local(main_server_st * s, struct sockaddr_storage *a
|
||||
return false;
|
||||
}
|
||||
|
||||
void if_address_cleanup(main_server_st * s)
|
||||
void if_address_cleanup(main_server_st *s)
|
||||
{
|
||||
if (s->if_addresses)
|
||||
talloc_free(s->if_addresses);
|
||||
|
||||
@@ -19,32 +19,35 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_MAIN_BAN_H
|
||||
# define OC_MAIN_BAN_H
|
||||
#define OC_MAIN_BAN_H
|
||||
|
||||
# include "main.h"
|
||||
#include "main.h"
|
||||
|
||||
typedef struct inaddr_st {
|
||||
uint8_t ip[16];
|
||||
unsigned size; /* 4 or 16 */
|
||||
unsigned int size; /* 4 or 16 */
|
||||
} inaddr_st;
|
||||
|
||||
typedef struct ban_entry_st {
|
||||
inaddr_st ip;
|
||||
unsigned score;
|
||||
unsigned int score;
|
||||
|
||||
time_t last_reset; /* the time its score counting started */
|
||||
time_t expires; /* the time after the client is allowed to login */
|
||||
} ban_entry_st;
|
||||
|
||||
void cleanup_banned_entries(main_server_st *s);
|
||||
unsigned check_if_banned(main_server_st *s, struct sockaddr_storage *addr, socklen_t addr_size);
|
||||
int add_str_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score);
|
||||
int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip, unsigned size);
|
||||
unsigned main_ban_db_elems(main_server_st *s);
|
||||
unsigned int check_if_banned(main_server_st *s, struct sockaddr_storage *addr,
|
||||
socklen_t addr_size);
|
||||
int add_str_ip_to_ban_list(main_server_st *s, const char *ip,
|
||||
unsigned int score);
|
||||
int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip,
|
||||
unsigned int size);
|
||||
unsigned int main_ban_db_elems(main_server_st *s);
|
||||
void main_ban_db_deinit(main_server_st *s);
|
||||
void *main_ban_db_init(main_server_st *s);
|
||||
|
||||
int if_address_init(main_server_st *s);
|
||||
void if_address_cleanup(main_server_st * s);
|
||||
void if_address_cleanup(main_server_st *s);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,46 +45,44 @@ typedef struct method_ctx {
|
||||
void *pool;
|
||||
} method_ctx;
|
||||
|
||||
static void method_top(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_status(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_disconnect_user_name(method_ctx *ctx, int cfd,
|
||||
uint8_t * msg, unsigned msg_size);
|
||||
static void method_disconnect_user_id(method_ctx *ctx, int cfd,
|
||||
uint8_t * msg, unsigned msg_size);
|
||||
static void method_unban_ip(method_ctx *ctx, int cfd,
|
||||
uint8_t * msg, unsigned msg_size);
|
||||
static void method_stop(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_reload(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_user_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_id_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_list_banned(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_top(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_status(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_list_users(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_disconnect_user_name(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_disconnect_user_id(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_unban_ip(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_stop(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_reload(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_user_info(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_id_info(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_list_banned(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
|
||||
typedef void (*method_func) (method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
typedef void (*method_func)(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size);
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
unsigned cmd;
|
||||
unsigned int cmd;
|
||||
method_func func;
|
||||
unsigned indefinite; /* session remains open */
|
||||
unsigned int indefinite; /* session remains open */
|
||||
} ctl_method_st;
|
||||
|
||||
#define ENTRY(cmd, func) \
|
||||
{#cmd, cmd, func, 0}
|
||||
#define ENTRY(cmd, func) { #cmd, cmd, func, 0 }
|
||||
|
||||
#define ENTRY_INDEF(cmd, func) \
|
||||
{#cmd, cmd, func, 1}
|
||||
#define ENTRY_INDEF(cmd, func) { #cmd, cmd, func, 1 }
|
||||
|
||||
static const ctl_method_st methods[] = {
|
||||
ENTRY_INDEF(CTL_CMD_TOP, method_top),
|
||||
@@ -99,10 +97,10 @@ static const ctl_method_st methods[] = {
|
||||
ENTRY(CTL_CMD_UNBAN_IP, method_unban_ip),
|
||||
ENTRY(CTL_CMD_DISCONNECT_NAME, method_disconnect_user_name),
|
||||
ENTRY(CTL_CMD_DISCONNECT_ID, method_disconnect_user_id),
|
||||
{NULL, 0, NULL}
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
void ctl_handler_deinit(main_server_st * s)
|
||||
void ctl_handler_deinit(main_server_st *s)
|
||||
{
|
||||
if (GETCONFIG(s)->use_occtl == 0)
|
||||
return;
|
||||
@@ -116,21 +114,24 @@ void ctl_handler_deinit(main_server_st * s)
|
||||
|
||||
/* Initializes unix socket and stores the fd.
|
||||
*/
|
||||
int ctl_handler_init(main_server_st * s)
|
||||
int ctl_handler_init(main_server_st *s)
|
||||
{
|
||||
int ret;
|
||||
struct sockaddr_un sa;
|
||||
int sd, e;
|
||||
|
||||
if (GETCONFIG(s)->use_occtl == 0 || GETPCONFIG(s)->occtl_socket_file == NULL) {
|
||||
if (GETCONFIG(s)->use_occtl == 0 ||
|
||||
GETPCONFIG(s)->occtl_socket_file == NULL) {
|
||||
mslog(s, NULL, LOG_INFO, "not using control unix socket");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mslog(s, NULL, LOG_DEBUG, "initializing control unix socket: %s", GETPCONFIG(s)->occtl_socket_file);
|
||||
mslog(s, NULL, LOG_DEBUG, "initializing control unix socket: %s",
|
||||
GETPCONFIG(s)->occtl_socket_file);
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sun_family = AF_UNIX;
|
||||
strlcpy(sa.sun_path, GETPCONFIG(s)->occtl_socket_file, sizeof(sa.sun_path));
|
||||
strlcpy(sa.sun_path, GETPCONFIG(s)->occtl_socket_file,
|
||||
sizeof(sa.sun_path));
|
||||
ret = remove(GETPCONFIG(s)->occtl_socket_file);
|
||||
if (ret != 0) {
|
||||
e = errno;
|
||||
@@ -156,7 +157,8 @@ int ctl_handler_init(main_server_st * s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = chown(GETPCONFIG(s)->occtl_socket_file, GETPCONFIG(s)->uid, GETPCONFIG(s)->gid);
|
||||
ret = chown(GETPCONFIG(s)->occtl_socket_file, GETPCONFIG(s)->uid,
|
||||
GETPCONFIG(s)->gid);
|
||||
if (ret == -1) {
|
||||
e = errno;
|
||||
mslog(s, NULL, LOG_ERR, "could not chown socket '%s': %s",
|
||||
@@ -176,18 +178,20 @@ int ctl_handler_init(main_server_st * s)
|
||||
return sd;
|
||||
}
|
||||
|
||||
static void method_status(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_status(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
StatusRep rep = STATUS_REP__INIT;
|
||||
int ret;
|
||||
unsigned int i;
|
||||
uint32_t * sec_mod_pids;
|
||||
uint32_t *sec_mod_pids;
|
||||
|
||||
sec_mod_pids = talloc_array(ctx->pool, uint32_t, ctx->s->sec_mod_instance_count);
|
||||
sec_mod_pids = talloc_array(ctx->pool, uint32_t,
|
||||
ctx->s->sec_mod_instance_count);
|
||||
if (sec_mod_pids) {
|
||||
for (i = 0; i < ctx->s->sec_mod_instance_count; i ++) {
|
||||
sec_mod_pids[i] = ctx->s->sec_mod_instances[i].sec_mod_pid;
|
||||
for (i = 0; i < ctx->s->sec_mod_instance_count; i++) {
|
||||
sec_mod_pids[i] =
|
||||
ctx->s->sec_mod_instances[i].sec_mod_pid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,10 +209,14 @@ static void method_status(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
rep.stored_tls_sessions = 0;
|
||||
rep.max_auth_time = 0;
|
||||
rep.avg_auth_time = 0;
|
||||
for (i = 0; i < ctx->s->sec_mod_instance_count; i ++) {
|
||||
rep.secmod_client_entries += ctx->s->sec_mod_instances[i].secmod_client_entries;
|
||||
rep.stored_tls_sessions += ctx->s->sec_mod_instances[i].tlsdb_entries;
|
||||
rep.max_auth_time = MAX(rep.max_auth_time, ctx->s->sec_mod_instances[i].max_auth_time);
|
||||
for (i = 0; i < ctx->s->sec_mod_instance_count; i++) {
|
||||
rep.secmod_client_entries +=
|
||||
ctx->s->sec_mod_instances[i].secmod_client_entries;
|
||||
rep.stored_tls_sessions +=
|
||||
ctx->s->sec_mod_instances[i].tlsdb_entries;
|
||||
rep.max_auth_time =
|
||||
MAX(rep.max_auth_time,
|
||||
ctx->s->sec_mod_instances[i].max_auth_time);
|
||||
rep.avg_auth_time = ctx->s->sec_mod_instances[i].avg_auth_time;
|
||||
}
|
||||
if (ctx->s->sec_mod_instance_count != 0) {
|
||||
@@ -232,65 +240,66 @@ static void method_status(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
rep.total_auth_failures = ctx->s->stats.total_auth_failures;
|
||||
rep.total_sessions_closed = ctx->s->stats.total_sessions_closed;
|
||||
#if defined(CAPTURE_LATENCY_SUPPORT)
|
||||
rep.latency_median_total = ctx->s->stats.current_latency_stats.median_total;
|
||||
rep.latency_median_total =
|
||||
ctx->s->stats.current_latency_stats.median_total;
|
||||
rep.has_latency_median_total = true;
|
||||
rep.latency_rms_total = ctx->s->stats.current_latency_stats.rms_total;
|
||||
rep.has_latency_rms_total = true;
|
||||
rep.latency_sample_count = ctx->s->stats.current_latency_stats.sample_count;
|
||||
rep.latency_sample_count =
|
||||
ctx->s->stats.current_latency_stats.sample_count;
|
||||
rep.has_latency_sample_count = true;
|
||||
#endif
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_STATUS_REP, &rep,
|
||||
(pack_size_func) status_rep__get_packed_size,
|
||||
(pack_func) status_rep__pack);
|
||||
(pack_size_func)status_rep__get_packed_size,
|
||||
(pack_func)status_rep__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
}
|
||||
}
|
||||
|
||||
static void method_reload(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_reload(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
BoolMsg rep = BOOL_MSG__INIT;
|
||||
int ret;
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: reload");
|
||||
|
||||
ev_feed_signal_event (main_loop, SIGHUP);
|
||||
ev_feed_signal_event(main_loop, SIGHUP);
|
||||
|
||||
rep.status = 1;
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_RELOAD_REP, &rep,
|
||||
(pack_size_func) bool_msg__get_packed_size,
|
||||
(pack_func) bool_msg__pack);
|
||||
(pack_size_func)bool_msg__get_packed_size,
|
||||
(pack_func)bool_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
}
|
||||
}
|
||||
|
||||
static void method_stop(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_stop(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
BoolMsg rep = BOOL_MSG__INIT;
|
||||
int ret;
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: stop");
|
||||
|
||||
ev_feed_signal_event (main_loop, SIGTERM);
|
||||
ev_feed_signal_event(main_loop, SIGTERM);
|
||||
|
||||
rep.status = 1;
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_STOP_REP, &rep,
|
||||
(pack_size_func) bool_msg__get_packed_size,
|
||||
(pack_func) bool_msg__pack);
|
||||
(pack_size_func)bool_msg__get_packed_size,
|
||||
(pack_func)bool_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
}
|
||||
}
|
||||
|
||||
#define IPBUF_SIZE 64
|
||||
static int append_user_info(method_ctx *ctx,
|
||||
UserListRep * list,
|
||||
static int append_user_info(method_ctx *ctx, UserListRep *list,
|
||||
struct proc_st *ctmp)
|
||||
{
|
||||
uint32_t tmp;
|
||||
@@ -299,8 +308,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
UserInfoRep *rep;
|
||||
char *safe_id;
|
||||
|
||||
list->user =
|
||||
talloc_realloc(ctx->pool, list->user, UserInfoRep *, (1 + list->n_user));
|
||||
list->user = talloc_realloc(ctx->pool, list->user, UserInfoRep *,
|
||||
(1 + list->n_user));
|
||||
if (list->user == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -327,9 +336,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
if (ipbuf == NULL)
|
||||
return -1;
|
||||
|
||||
strtmp =
|
||||
human_addr2((struct sockaddr *)&ctmp->remote_addr,
|
||||
ctmp->remote_addr_len, ipbuf, IPBUF_SIZE, 0);
|
||||
strtmp = human_addr2((struct sockaddr *)&ctmp->remote_addr,
|
||||
ctmp->remote_addr_len, ipbuf, IPBUF_SIZE, 0);
|
||||
if (strtmp == NULL)
|
||||
strtmp = "";
|
||||
rep->ip = strtmp;
|
||||
@@ -338,9 +346,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
if (ipbuf == NULL)
|
||||
return -1;
|
||||
|
||||
strtmp =
|
||||
human_addr2((struct sockaddr *)&ctmp->our_addr,
|
||||
ctmp->our_addr_len, ipbuf, IPBUF_SIZE, 0);
|
||||
strtmp = human_addr2((struct sockaddr *)&ctmp->our_addr,
|
||||
ctmp->our_addr_len, ipbuf, IPBUF_SIZE, 0);
|
||||
if (strtmp == NULL)
|
||||
strtmp = "";
|
||||
rep->local_dev_ip = strtmp;
|
||||
@@ -353,9 +360,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
|
||||
strtmp = NULL;
|
||||
if (ctmp->ipv4 != NULL)
|
||||
strtmp =
|
||||
human_addr2((struct sockaddr *)&ctmp->ipv4->rip,
|
||||
ctmp->ipv4->rip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
strtmp = human_addr2((struct sockaddr *)&ctmp->ipv4->rip,
|
||||
ctmp->ipv4->rip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
if (strtmp == NULL)
|
||||
strtmp = "";
|
||||
rep->local_ip = strtmp;
|
||||
@@ -366,9 +372,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
|
||||
strtmp = NULL;
|
||||
if (ctmp->ipv4 != NULL)
|
||||
strtmp =
|
||||
human_addr2((struct sockaddr *)&ctmp->ipv4->lip,
|
||||
ctmp->ipv4->lip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
strtmp = human_addr2((struct sockaddr *)&ctmp->ipv4->lip,
|
||||
ctmp->ipv4->lip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
if (strtmp == NULL)
|
||||
strtmp = "";
|
||||
rep->remote_ip = strtmp;
|
||||
@@ -381,9 +386,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
|
||||
strtmp = NULL;
|
||||
if (ctmp->ipv6 != NULL)
|
||||
strtmp =
|
||||
human_addr2((struct sockaddr *)&ctmp->ipv6->rip,
|
||||
ctmp->ipv6->rip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
strtmp = human_addr2((struct sockaddr *)&ctmp->ipv6->rip,
|
||||
ctmp->ipv6->rip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
if (strtmp == NULL)
|
||||
strtmp = "";
|
||||
rep->local_ip6 = strtmp;
|
||||
@@ -394,9 +398,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
|
||||
strtmp = NULL;
|
||||
if (ctmp->ipv6 != NULL)
|
||||
strtmp =
|
||||
human_addr2((struct sockaddr *)&ctmp->ipv6->lip,
|
||||
ctmp->ipv6->lip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
strtmp = human_addr2((struct sockaddr *)&ctmp->ipv6->lip,
|
||||
ctmp->ipv6->lip_len, ipbuf, IPBUF_SIZE, 0);
|
||||
if (strtmp == NULL)
|
||||
strtmp = "";
|
||||
rep->remote_ip6 = strtmp;
|
||||
@@ -411,7 +414,7 @@ static int append_user_info(method_ctx *ctx,
|
||||
rep->dtls_ciphersuite = ctmp->dtls_ciphersuite;
|
||||
|
||||
calc_safe_id(ctmp->sid, sizeof(ctmp->sid), safe_id, SAFE_ID_SIZE);
|
||||
rep->safe_id.data = (unsigned char*)safe_id;
|
||||
rep->safe_id.data = (unsigned char *)safe_id;
|
||||
rep->safe_id.len = SAFE_ID_SIZE;
|
||||
|
||||
rep->cstp_compr = ctmp->cstp_compr;
|
||||
@@ -438,8 +441,10 @@ static int append_user_info(method_ctx *ctx,
|
||||
|
||||
rep->keepalive = ctmp->config->keepalive;
|
||||
if (ctmp->vhost) {
|
||||
rep->domains = ctmp->vhost->perm_config.config->split_dns;
|
||||
rep->n_domains = ctmp->vhost->perm_config.config->split_dns_size;
|
||||
rep->domains =
|
||||
ctmp->vhost->perm_config.config->split_dns;
|
||||
rep->n_domains =
|
||||
ctmp->vhost->perm_config.config->split_dns_size;
|
||||
}
|
||||
|
||||
rep->dns = ctmp->config->dns;
|
||||
@@ -464,8 +469,8 @@ static int append_user_info(method_ctx *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_list_users(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
UserListRep rep = USER_LIST_REP__INIT;
|
||||
struct proc_st *ctmp = NULL;
|
||||
@@ -473,7 +478,8 @@ static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: list-users");
|
||||
|
||||
list_for_each(&ctx->s->proc_list.head, ctmp, list) {
|
||||
list_for_each(&ctx->s->proc_list.head, ctmp, list)
|
||||
{
|
||||
ret = append_user_info(ctx, &rep, ctmp);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
@@ -483,15 +489,15 @@ static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
}
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_LIST_REP, &rep,
|
||||
(pack_size_func) user_list_rep__get_packed_size,
|
||||
(pack_func) user_list_rep__pack);
|
||||
(pack_size_func)user_list_rep__get_packed_size,
|
||||
(pack_func)user_list_rep__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
}
|
||||
}
|
||||
|
||||
static void method_top(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_top(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
/* we send the initial user list, and the we send a TOP reply message
|
||||
* once a user connects/disconnects. */
|
||||
@@ -505,15 +511,14 @@ static void method_top(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
method_list_users(ctx, cfd, msg, msg_size);
|
||||
}
|
||||
|
||||
static int append_ban_info(method_ctx *ctx,
|
||||
BanListRep *list,
|
||||
static int append_ban_info(method_ctx *ctx, BanListRep *list,
|
||||
struct ban_entry_st *e)
|
||||
{
|
||||
BanInfoRep *rep;
|
||||
main_server_st *s = ctx->s;
|
||||
|
||||
list->info =
|
||||
talloc_realloc(ctx->pool, list->info, BanInfoRep *, (1 + list->n_info));
|
||||
list->info = talloc_realloc(ctx->pool, list->info, BanInfoRep *,
|
||||
(1 + list->n_info));
|
||||
if (list->info == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -528,7 +533,8 @@ static int append_ban_info(method_ctx *ctx,
|
||||
rep->ip.len = e->ip.size;
|
||||
rep->score = e->score;
|
||||
|
||||
if (GETCONFIG(s)->max_ban_score > 0 && e->score >= GETCONFIG(s)->max_ban_score) {
|
||||
if (GETCONFIG(s)->max_ban_score > 0 &&
|
||||
e->score >= GETCONFIG(s)->max_ban_score) {
|
||||
rep->expires = e->expires;
|
||||
rep->has_expires = 1;
|
||||
}
|
||||
@@ -536,8 +542,8 @@ static int append_ban_info(method_ctx *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void method_list_banned(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_list_banned(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
BanListRep rep = BAN_LIST_REP__INIT;
|
||||
struct ban_entry_st *e = NULL;
|
||||
@@ -559,19 +565,21 @@ static void method_list_banned(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
}
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_LIST_BANNED_REP, &rep,
|
||||
(pack_size_func) ban_list_rep__get_packed_size,
|
||||
(pack_func) ban_list_rep__pack);
|
||||
(pack_size_func)ban_list_rep__get_packed_size,
|
||||
(pack_func)ban_list_rep__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ban list reply");
|
||||
}
|
||||
}
|
||||
|
||||
static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
SecmListCookiesReplyMsg reply = SECM_LIST_COOKIES_REPLY_MSG__INIT;
|
||||
SecmListCookiesReplyMsg ** sub_replies = NULL;
|
||||
CookieIntMsg ** cookies = NULL;
|
||||
SecmListCookiesReplyMsg **sub_replies = NULL;
|
||||
|
||||
CookieIntMsg **cookies = NULL;
|
||||
|
||||
PROTOBUF_ALLOCATOR(pa, ctx->pool);
|
||||
|
||||
size_t total_cookies = 0;
|
||||
@@ -582,23 +590,31 @@ static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: list-cookies");
|
||||
|
||||
sub_replies = talloc_zero_array(ctx->pool, SecmListCookiesReplyMsg*, ctx->s->sec_mod_instance_count);
|
||||
sub_replies = talloc_zero_array(ctx->pool, SecmListCookiesReplyMsg *,
|
||||
ctx->s->sec_mod_instance_count);
|
||||
if (!sub_replies) {
|
||||
goto reply_and_exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->s->sec_mod_instance_count; i++) {
|
||||
SecmListCookiesReplyMsg * sub_reply = NULL;
|
||||
ret = send_msg(ctx->pool, ctx->s->sec_mod_instances[i].sec_mod_fd_sync, CMD_SECM_LIST_COOKIES,
|
||||
NULL, NULL, NULL);
|
||||
SecmListCookiesReplyMsg *sub_reply = NULL;
|
||||
|
||||
ret = send_msg(ctx->pool,
|
||||
ctx->s->sec_mod_instances[i].sec_mod_fd_sync,
|
||||
CMD_SECM_LIST_COOKIES, NULL, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending list cookies to sec-mod!");
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error sending list cookies to sec-mod!");
|
||||
continue;
|
||||
}
|
||||
ret = recv_msg(ctx->pool, ctx->s->sec_mod_instances[i].sec_mod_fd_sync, CMD_SECM_LIST_COOKIES_REPLY,
|
||||
(void*)&sub_reply, (unpack_func)secm_list_cookies_reply_msg__unpack, MAIN_SEC_MOD_TIMEOUT);
|
||||
ret = recv_msg(ctx->pool,
|
||||
ctx->s->sec_mod_instances[i].sec_mod_fd_sync,
|
||||
CMD_SECM_LIST_COOKIES_REPLY, (void *)&sub_reply,
|
||||
(unpack_func)secm_list_cookies_reply_msg__unpack,
|
||||
MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error receiving list cookies reply");
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error receiving list cookies reply");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -608,7 +624,7 @@ static void method_list_cookies(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
}
|
||||
}
|
||||
|
||||
cookies = talloc_zero_array(ctx->pool, CookieIntMsg*, total_cookies);
|
||||
cookies = talloc_zero_array(ctx->pool, CookieIntMsg *, total_cookies);
|
||||
if (!cookies) {
|
||||
goto reply_and_exit;
|
||||
}
|
||||
@@ -628,11 +644,13 @@ reply_and_exit:
|
||||
reply.cookies = cookies;
|
||||
reply.n_cookies = total_cookies;
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_LIST_COOKIES_REP, &reply,
|
||||
(pack_size_func) secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func) secm_list_cookies_reply_msg__pack);
|
||||
ret = send_msg(
|
||||
ctx->pool, cfd, CTL_CMD_LIST_COOKIES_REP, &reply,
|
||||
(pack_size_func)secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func)secm_list_cookies_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending list cookies reply");
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error sending list cookies reply");
|
||||
}
|
||||
|
||||
if (sub_replies) {
|
||||
@@ -640,7 +658,8 @@ reply_and_exit:
|
||||
if (sub_replies[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
secm_list_cookies_reply_msg__free_unpacked(sub_replies[i], &pa);
|
||||
secm_list_cookies_reply_msg__free_unpacked(
|
||||
sub_replies[i], &pa);
|
||||
}
|
||||
talloc_free(sub_replies);
|
||||
}
|
||||
@@ -650,25 +669,28 @@ reply_and_exit:
|
||||
}
|
||||
}
|
||||
|
||||
static void single_info_common(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size, const char *user, unsigned id)
|
||||
static void single_info_common(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size, const char *user,
|
||||
unsigned int id)
|
||||
{
|
||||
UserListRep rep = USER_LIST_REP__INIT;
|
||||
int ret;
|
||||
unsigned found_user = 0;
|
||||
unsigned int found_user = 0;
|
||||
struct proc_st *ctmp = NULL;
|
||||
|
||||
if (user != NULL)
|
||||
mslog(ctx->s, NULL, LOG_INFO, "providing info for user '%s'", user);
|
||||
mslog(ctx->s, NULL, LOG_INFO, "providing info for user '%s'",
|
||||
user);
|
||||
else
|
||||
mslog(ctx->s, NULL, LOG_INFO, "providing info for ID '%u'", id);
|
||||
|
||||
list_for_each(&ctx->s->proc_list.head, ctmp, list) {
|
||||
if (user == NULL) { /* id */
|
||||
list_for_each(&ctx->s->proc_list.head, ctmp, list)
|
||||
{
|
||||
if (user == NULL) { /* id */
|
||||
if (id == 0 || id == -1 || id != ctmp->pid) {
|
||||
continue;
|
||||
}
|
||||
} else { /* username */
|
||||
} else { /* username */
|
||||
if (strcmp(ctmp->username, user) != 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -683,28 +705,29 @@ static void single_info_common(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
|
||||
found_user = 1;
|
||||
|
||||
if (id != 0) /* id -> one a single element */
|
||||
if (id != 0) /* id -> one a single element */
|
||||
break;
|
||||
}
|
||||
|
||||
if (found_user == 0) {
|
||||
if (user != NULL)
|
||||
mslog(ctx->s, NULL, LOG_INFO, "could not find user '%s'",
|
||||
user);
|
||||
mslog(ctx->s, NULL, LOG_INFO,
|
||||
"could not find user '%s'", user);
|
||||
else
|
||||
mslog(ctx->s, NULL, LOG_INFO, "could not find ID '%u'", id);
|
||||
mslog(ctx->s, NULL, LOG_INFO, "could not find ID '%u'",
|
||||
id);
|
||||
}
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_LIST_REP, &rep,
|
||||
(pack_size_func) user_list_rep__get_packed_size,
|
||||
(pack_func) user_list_rep__pack);
|
||||
(pack_size_func)user_list_rep__get_packed_size,
|
||||
(pack_func)user_list_rep__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
}
|
||||
}
|
||||
|
||||
static void method_user_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_user_info(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
UsernameReq *req;
|
||||
|
||||
@@ -720,8 +743,8 @@ static void method_user_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
username_req__free_unpacked(req, NULL);
|
||||
}
|
||||
|
||||
static void method_id_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_id_info(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
IdReq *req;
|
||||
|
||||
@@ -737,9 +760,8 @@ static void method_id_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
id_req__free_unpacked(req, NULL);
|
||||
}
|
||||
|
||||
static void method_unban_ip(method_ctx *ctx,
|
||||
int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_unban_ip(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
UnbanReq *req;
|
||||
BoolMsg rep = BOOL_MSG__INIT;
|
||||
@@ -749,8 +771,7 @@ static void method_unban_ip(method_ctx *ctx,
|
||||
|
||||
req = unban_req__unpack(NULL, msg_size, msg);
|
||||
if (req == NULL) {
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error parsing unban IP request");
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error parsing unban IP request");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -761,16 +782,16 @@ static void method_unban_ip(method_ctx *ctx,
|
||||
unban_req__free_unpacked(req, NULL);
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_UNBAN_IP_REP, &rep,
|
||||
(pack_size_func) bool_msg__get_packed_size,
|
||||
(pack_func) bool_msg__pack);
|
||||
(pack_size_func)bool_msg__get_packed_size,
|
||||
(pack_func)bool_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending unban IP ctl reply");
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error sending unban IP ctl reply");
|
||||
}
|
||||
}
|
||||
|
||||
static void method_disconnect_user_name(method_ctx *ctx,
|
||||
int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
static void method_disconnect_user_name(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
UsernameReq *req;
|
||||
BoolMsg rep = BOOL_MSG__INIT;
|
||||
@@ -788,7 +809,8 @@ static void method_disconnect_user_name(method_ctx *ctx,
|
||||
}
|
||||
|
||||
/* got the name. Try to disconnect */
|
||||
list_for_each_safe(&ctx->s->proc_list.head, ctmp, cpos, list) {
|
||||
list_for_each_safe(&ctx->s->proc_list.head, ctmp, cpos, list)
|
||||
{
|
||||
if (strcmp(ctmp->username, req->username) == 0) {
|
||||
disconnect_proc(ctx->s, ctmp);
|
||||
rep.status = 1;
|
||||
@@ -798,15 +820,15 @@ static void method_disconnect_user_name(method_ctx *ctx,
|
||||
username_req__free_unpacked(req, NULL);
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_DISCONNECT_NAME_REP, &rep,
|
||||
(pack_size_func) bool_msg__get_packed_size,
|
||||
(pack_func) bool_msg__pack);
|
||||
(pack_size_func)bool_msg__get_packed_size,
|
||||
(pack_func)bool_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
}
|
||||
}
|
||||
|
||||
static void method_disconnect_user_id(method_ctx *ctx, int cfd,
|
||||
uint8_t * msg, unsigned msg_size)
|
||||
static void method_disconnect_user_id(method_ctx *ctx, int cfd, uint8_t *msg,
|
||||
unsigned int msg_size)
|
||||
{
|
||||
IdReq *req;
|
||||
BoolMsg rep = BOOL_MSG__INIT;
|
||||
@@ -818,12 +840,14 @@ static void method_disconnect_user_id(method_ctx *ctx, int cfd,
|
||||
|
||||
req = id_req__unpack(NULL, msg_size, msg);
|
||||
if (req == NULL) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error parsing disconnect_id request");
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error parsing disconnect_id request");
|
||||
return;
|
||||
}
|
||||
|
||||
/* got the ID. Try to disconnect */
|
||||
list_for_each_safe(&ctx->s->proc_list.head, ctmp, cpos, list) {
|
||||
list_for_each_safe(&ctx->s->proc_list.head, ctmp, cpos, list)
|
||||
{
|
||||
if (ctmp->pid == req->id) {
|
||||
disconnect_proc(ctx->s, ctmp);
|
||||
rep.status = 1;
|
||||
@@ -837,8 +861,8 @@ static void method_disconnect_user_id(method_ctx *ctx, int cfd,
|
||||
id_req__free_unpacked(req, NULL);
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_DISCONNECT_ID_REP, &rep,
|
||||
(pack_size_func) bool_msg__get_packed_size,
|
||||
(pack_func) bool_msg__pack);
|
||||
(pack_size_func)bool_msg__get_packed_size,
|
||||
(pack_func)bool_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
}
|
||||
@@ -857,8 +881,9 @@ static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
|
||||
uint8_t cmd;
|
||||
uint8_t buffer[256];
|
||||
method_ctx ctx;
|
||||
struct ctl_watcher_st *wst = container_of(w, struct ctl_watcher_st, ctl_cmd_io);
|
||||
unsigned i, indef = 0;
|
||||
struct ctl_watcher_st *wst =
|
||||
container_of(w, struct ctl_watcher_st, ctl_cmd_io);
|
||||
unsigned int i, indef = 0;
|
||||
|
||||
ctx.s = s;
|
||||
ctx.pool = talloc_new(wst);
|
||||
@@ -879,7 +904,7 @@ static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
|
||||
if (methods[i].cmd == 0) {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"unknown unix ctl message: 0x%.1x",
|
||||
(unsigned)cmd);
|
||||
(unsigned int)cmd);
|
||||
break;
|
||||
} else if (methods[i].cmd == cmd) {
|
||||
indef = methods[i].indefinite;
|
||||
@@ -892,7 +917,7 @@ static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
|
||||
talloc_free(ctx.pool);
|
||||
return;
|
||||
}
|
||||
fail:
|
||||
fail:
|
||||
if (s->top_fd == wst->fd)
|
||||
s->top_fd = -1;
|
||||
close(wst->fd);
|
||||
@@ -900,7 +925,7 @@ static void ctl_cmd_wacher_cb(EV_P_ ev_io *w, int revents)
|
||||
talloc_free(wst);
|
||||
}
|
||||
|
||||
static void ctl_handle_commands(main_server_st * s)
|
||||
static void ctl_handle_commands(main_server_st *s)
|
||||
{
|
||||
int cfd = -1, e, ret;
|
||||
struct sockaddr_un sa;
|
||||
@@ -916,7 +941,8 @@ static void ctl_handle_commands(main_server_st * s)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = check_upeer_id("ctl", GETPCONFIG(s)->log_level, cfd, 0, 0, NULL, NULL);
|
||||
ret = check_upeer_id("ctl", GETPCONFIG(s)->log_level, cfd, 0, 0, NULL,
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "ctl: unauthorized connection");
|
||||
goto fail;
|
||||
@@ -934,12 +960,12 @@ static void ctl_handle_commands(main_server_st * s)
|
||||
ev_io_start(main_loop, &wst->ctl_cmd_io);
|
||||
|
||||
return;
|
||||
fail:
|
||||
fail:
|
||||
if (cfd != -1)
|
||||
close(cfd);
|
||||
}
|
||||
|
||||
void ctl_handler_set_fds(main_server_st * s, ev_io *watcher)
|
||||
void ctl_handler_set_fds(main_server_st *s, ev_io *watcher)
|
||||
{
|
||||
if (GETCONFIG(s)->use_occtl == 0)
|
||||
return;
|
||||
@@ -947,7 +973,7 @@ void ctl_handler_set_fds(main_server_st * s, ev_io *watcher)
|
||||
ev_io_set(watcher, s->ctl_fd, EV_READ);
|
||||
}
|
||||
|
||||
void ctl_handler_run_pending(main_server_st* s, ev_io *watcher)
|
||||
void ctl_handler_run_pending(main_server_st *s, ev_io *watcher)
|
||||
{
|
||||
if (GETCONFIG(s)->use_occtl == 0)
|
||||
return;
|
||||
@@ -955,7 +981,8 @@ void ctl_handler_run_pending(main_server_st* s, ev_io *watcher)
|
||||
ctl_handle_commands(s);
|
||||
}
|
||||
|
||||
void ctl_handler_notify (main_server_st* s, struct proc_st *proc, unsigned connect)
|
||||
void ctl_handler_notify(main_server_st *s, struct proc_st *proc,
|
||||
unsigned int connect)
|
||||
{
|
||||
TopUpdateRep rep = TOP_UPDATE_REP__INIT;
|
||||
UserListRep list = USER_LIST_REP__INIT;
|
||||
@@ -979,20 +1006,20 @@ void ctl_handler_notify (main_server_st* s, struct proc_st *proc, unsigned conne
|
||||
if (connect == 0 && proc->discon_reason) {
|
||||
rep.has_discon_reason = 1;
|
||||
rep.discon_reason = proc->discon_reason;
|
||||
rep.discon_reason_txt = (char*)discon_reason_to_str(proc->discon_reason);
|
||||
rep.discon_reason_txt =
|
||||
(char *)discon_reason_to_str(proc->discon_reason);
|
||||
}
|
||||
|
||||
ret = append_user_info(&ctx, &list, proc);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error appending user info to reply");
|
||||
mslog(s, NULL, LOG_ERR, "error appending user info to reply");
|
||||
goto fail;
|
||||
}
|
||||
rep.user = &list;
|
||||
|
||||
ret = send_msg(pool, s->top_fd, CTL_CMD_TOP_UPDATE_REP, &rep,
|
||||
(pack_size_func) top_update_rep__get_packed_size,
|
||||
(pack_func) top_update_rep__pack);
|
||||
(pack_size_func)top_update_rep__get_packed_size,
|
||||
(pack_func)top_update_rep__pack);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "error sending ctl reply");
|
||||
goto fail;
|
||||
@@ -1000,7 +1027,7 @@ void ctl_handler_notify (main_server_st* s, struct proc_st *proc, unsigned conne
|
||||
|
||||
talloc_free(pool);
|
||||
return;
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(pool);
|
||||
s->top_fd = -1;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#ifndef OC_MAIN_CTL_H
|
||||
# define OC_MAIN_CTL_H
|
||||
#define OC_MAIN_CTL_H
|
||||
|
||||
#include <occtl/ctl.h>
|
||||
#include <ev.h>
|
||||
|
||||
int ctl_handler_init(main_server_st* s);
|
||||
void ctl_handler_deinit(main_server_st* s);
|
||||
int ctl_handler_init(main_server_st *s);
|
||||
void ctl_handler_deinit(main_server_st *s);
|
||||
|
||||
void ctl_handler_set_fds(main_server_st* s, ev_io *watcher);
|
||||
void ctl_handler_run_pending(main_server_st* s, ev_io *watcher);
|
||||
void ctl_handler_notify (main_server_st* s, struct proc_st *proc, unsigned connect);
|
||||
void ctl_handler_set_fds(main_server_st *s, ev_io *watcher);
|
||||
void ctl_handler_run_pending(main_server_st *s, ev_io *watcher);
|
||||
void ctl_handler_notify(main_server_st *s, struct proc_st *proc,
|
||||
unsigned int connect);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
#include <sys/resource.h>
|
||||
#include <grp.h>
|
||||
|
||||
|
||||
#include <main.h>
|
||||
#include <limits.h>
|
||||
|
||||
void init_fd_limits_default(main_server_st * s)
|
||||
void init_fd_limits_default(main_server_st *s)
|
||||
{
|
||||
#ifdef RLIMIT_NOFILE
|
||||
int ret = getrlimit(RLIMIT_NOFILE, &s->fd_limits_default_set);
|
||||
|
||||
if (ret < 0) {
|
||||
oc_syslog(LOG_ERR, "error in getrlimit: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -46,11 +46,11 @@ void init_fd_limits_default(main_server_st * s)
|
||||
|
||||
/* Adjusts the file descriptor limits for the main or worker processes
|
||||
*/
|
||||
void set_main_fd_limits(main_server_st * s)
|
||||
void set_main_fd_limits(main_server_st *s)
|
||||
{
|
||||
#ifdef RLIMIT_NOFILE
|
||||
struct rlimit new_set;
|
||||
unsigned max;
|
||||
unsigned int max;
|
||||
int ret;
|
||||
|
||||
if (GETCONFIG(s)->max_clients > 0)
|
||||
@@ -66,19 +66,19 @@ void set_main_fd_limits(main_server_st * s)
|
||||
ret = setrlimit(RLIMIT_NOFILE, &new_set);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr,
|
||||
"error in setrlimit(%u): %s (cur: %u)\n",
|
||||
max, strerror(errno),
|
||||
(unsigned)s->fd_limits_default_set.
|
||||
rlim_cur);
|
||||
"error in setrlimit(%u): %s (cur: %u)\n", max,
|
||||
strerror(errno),
|
||||
(unsigned int)s->fd_limits_default_set.rlim_cur);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_self_oom_score_adj(main_server_st * s)
|
||||
void set_self_oom_score_adj(main_server_st *s)
|
||||
{
|
||||
#ifdef __linux__
|
||||
static const char proc_self_oom_adj_score_path[] = "/proc/self/oom_score_adj";
|
||||
static const char proc_self_oom_adj_score_path[] =
|
||||
"/proc/self/oom_score_adj";
|
||||
static const char oom_adj_score_value[] = "1000";
|
||||
size_t written = 0;
|
||||
int fd;
|
||||
@@ -87,6 +87,7 @@ void set_self_oom_score_adj(main_server_st * s)
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd == -1) {
|
||||
int e = errno;
|
||||
|
||||
mslog(s, NULL, LOG_ERR, "cannot open %s: %s",
|
||||
proc_self_oom_adj_score_path, strerror(e));
|
||||
goto cleanup;
|
||||
@@ -95,12 +96,13 @@ void set_self_oom_score_adj(main_server_st * s)
|
||||
written = write(fd, oom_adj_score_value, sizeof(oom_adj_score_value));
|
||||
if (written != sizeof(oom_adj_score_value)) {
|
||||
int e = errno;
|
||||
|
||||
mslog(s, NULL, LOG_ERR, "cannot write %s: %s",
|
||||
proc_self_oom_adj_score_path, strerror(e));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@@ -17,15 +17,14 @@
|
||||
*/
|
||||
|
||||
#ifndef MAIN_LIMITS_H
|
||||
# define MAIN_LIMITS_H
|
||||
#define MAIN_LIMITS_H
|
||||
|
||||
|
||||
void init_fd_limits_default(struct main_server_st * s);
|
||||
void init_fd_limits_default(struct main_server_st *s);
|
||||
|
||||
/* Adjusts the file descriptor limits for the main or worker processes
|
||||
*/
|
||||
void set_main_fd_limits(struct main_server_st * s);
|
||||
void set_main_fd_limits(struct main_server_st *s);
|
||||
|
||||
void set_self_oom_score_adj(struct main_server_st * s);
|
||||
void set_self_oom_score_adj(struct main_server_st *s);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,17 +32,18 @@
|
||||
#include "log.h"
|
||||
|
||||
/* proc is optional */
|
||||
void __attribute__ ((format(printf, 4, 5)))
|
||||
_mslog(const main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *fmt, ...)
|
||||
void __attribute__((format(printf, 4, 5))) _mslog(const main_server_st *s,
|
||||
const struct proc_st *proc,
|
||||
int priority, const char *fmt,
|
||||
...)
|
||||
{
|
||||
char buf[512];
|
||||
char ipbuf[128];
|
||||
char name[MAX_USERNAME_SIZE+MAX_HOSTNAME_SIZE+3];
|
||||
const char* ip = NULL;
|
||||
char name[MAX_USERNAME_SIZE + MAX_HOSTNAME_SIZE + 3];
|
||||
const char *ip = NULL;
|
||||
va_list args;
|
||||
int log_prio = DEFAULT_LOG_LEVEL;
|
||||
unsigned have_vhosts;
|
||||
unsigned int have_vhosts;
|
||||
int syslog_prio;
|
||||
|
||||
if (s)
|
||||
@@ -52,8 +53,8 @@ _mslog(const main_server_st * s, const struct proc_st* proc,
|
||||
return;
|
||||
|
||||
if (proc) {
|
||||
ip = human_addr((void*)&proc->remote_addr, proc->remote_addr_len,
|
||||
ipbuf, sizeof(ipbuf));
|
||||
ip = human_addr((void *)&proc->remote_addr,
|
||||
proc->remote_addr_len, ipbuf, sizeof(ipbuf));
|
||||
} else {
|
||||
ip = "";
|
||||
}
|
||||
@@ -62,27 +63,32 @@ _mslog(const main_server_st * s, const struct proc_st* proc,
|
||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
have_vhosts = s?HAVE_VHOSTS(s):0;
|
||||
have_vhosts = s ? HAVE_VHOSTS(s) : 0;
|
||||
|
||||
if (have_vhosts && proc && proc->username[0] != 0) {
|
||||
snprintf(name, sizeof(name), "[%s%s]", PREFIX_VHOST(proc->vhost), proc->username);
|
||||
} else if (have_vhosts && proc && proc->username[0] == 0 && proc->vhost && proc->vhost->name) {
|
||||
snprintf(name, sizeof(name), "[vhost:%s]", VHOSTNAME(proc->vhost));
|
||||
snprintf(name, sizeof(name), "[%s%s]",
|
||||
PREFIX_VHOST(proc->vhost), proc->username);
|
||||
} else if (have_vhosts && proc && proc->username[0] == 0 &&
|
||||
proc->vhost && proc->vhost->name) {
|
||||
snprintf(name, sizeof(name), "[vhost:%s]",
|
||||
VHOSTNAME(proc->vhost));
|
||||
} else if (proc && proc->username[0] != 0) {
|
||||
snprintf(name, sizeof(name), "[%s]", proc->username);
|
||||
} else
|
||||
name[0] = 0;
|
||||
|
||||
_oc_syslog(syslog_prio, "main%s:%s %s", name, ip?ip:"[unknown]", buf);
|
||||
_oc_syslog(syslog_prio, "main%s:%s %s", name, ip ? ip : "[unknown]",
|
||||
buf);
|
||||
}
|
||||
|
||||
void mslog_hex(const main_server_st * s, const struct proc_st* proc,
|
||||
int priority, const char *prefix, uint8_t* bin, unsigned bin_size, unsigned b64)
|
||||
void mslog_hex(const main_server_st *s, const struct proc_st *proc,
|
||||
int priority, const char *prefix, uint8_t *bin,
|
||||
unsigned int bin_size, unsigned int b64)
|
||||
{
|
||||
char buf[512];
|
||||
int ret;
|
||||
size_t buf_size;
|
||||
gnutls_datum_t data = {bin, bin_size};
|
||||
gnutls_datum_t data = { bin, bin_size };
|
||||
int log_prio = DEFAULT_LOG_LEVEL;
|
||||
|
||||
if (s)
|
||||
@@ -92,7 +98,8 @@ void mslog_hex(const main_server_st * s, const struct proc_st* proc,
|
||||
return;
|
||||
|
||||
if (b64) {
|
||||
oc_base64_encode((char*)bin, bin_size, (char*)buf, sizeof(buf));
|
||||
oc_base64_encode((char *)bin, bin_size, (char *)buf,
|
||||
sizeof(buf));
|
||||
} else {
|
||||
buf_size = sizeof(buf);
|
||||
ret = gnutls_hex_encode(&data, buf, &buf_size);
|
||||
@@ -103,13 +110,13 @@ void mslog_hex(const main_server_st * s, const struct proc_st* proc,
|
||||
_mslog(s, proc, priority, "%s %s", prefix, buf);
|
||||
}
|
||||
|
||||
void seclog_hex(const struct sec_mod_st* sec, int priority,
|
||||
const char *prefix, uint8_t* bin, unsigned bin_size, unsigned b64)
|
||||
void seclog_hex(const struct sec_mod_st *sec, int priority, const char *prefix,
|
||||
uint8_t *bin, unsigned int bin_size, unsigned int b64)
|
||||
{
|
||||
char buf[512];
|
||||
int ret;
|
||||
size_t buf_size;
|
||||
gnutls_datum_t data = {bin, bin_size};
|
||||
gnutls_datum_t data = { bin, bin_size };
|
||||
int log_prio;
|
||||
|
||||
log_prio = GETPCONFIG(sec)->log_level;
|
||||
@@ -118,7 +125,8 @@ void seclog_hex(const struct sec_mod_st* sec, int priority,
|
||||
return;
|
||||
|
||||
if (b64) {
|
||||
oc_base64_encode((char*)bin, bin_size, (char*)buf, sizeof(buf));
|
||||
oc_base64_encode((char *)bin, bin_size, (char *)buf,
|
||||
sizeof(buf));
|
||||
} else {
|
||||
buf_size = sizeof(buf);
|
||||
ret = gnutls_hex_encode(&data, buf, &buf_size);
|
||||
@@ -129,8 +137,8 @@ void seclog_hex(const struct sec_mod_st* sec, int priority,
|
||||
seclog(sec, priority, "%s %s", prefix, buf);
|
||||
}
|
||||
|
||||
void __attribute__ ((format(printf, 3, 4)))
|
||||
_seclog(const sec_mod_st* sec, int priority, const char *fmt, ...)
|
||||
void __attribute__((format(printf, 3, 4)))
|
||||
_seclog(const sec_mod_st *sec, int priority, const char *fmt, ...)
|
||||
{
|
||||
char buf[512];
|
||||
va_list args;
|
||||
|
||||
@@ -56,10 +56,11 @@
|
||||
#include <main-ban.h>
|
||||
#include <ccan/list/list.h>
|
||||
|
||||
struct proc_st *new_proc(main_server_st * s, pid_t pid, int cmd_fd,
|
||||
struct sockaddr_storage *remote_addr, socklen_t remote_addr_len,
|
||||
struct sockaddr_storage *our_addr, socklen_t our_addr_len,
|
||||
uint8_t *sid, size_t sid_size)
|
||||
struct proc_st *new_proc(main_server_st *s, pid_t pid, int cmd_fd,
|
||||
struct sockaddr_storage *remote_addr,
|
||||
socklen_t remote_addr_len,
|
||||
struct sockaddr_storage *our_addr,
|
||||
socklen_t our_addr_len, uint8_t *sid, size_t sid_size)
|
||||
{
|
||||
struct proc_st *ctmp;
|
||||
|
||||
@@ -70,7 +71,7 @@ struct proc_st *new_proc(main_server_st * s, pid_t pid, int cmd_fd,
|
||||
ctmp->pid = pid;
|
||||
ctmp->tun_lease.fd = -1;
|
||||
ctmp->fd = cmd_fd;
|
||||
set_cloexec_flag (cmd_fd, 1);
|
||||
set_cloexec_flag(cmd_fd, 1);
|
||||
ctmp->conn_time = time(NULL);
|
||||
|
||||
memcpy(&ctmp->remote_addr, remote_addr, remote_addr_len);
|
||||
@@ -92,7 +93,7 @@ struct proc_st *new_proc(main_server_st * s, pid_t pid, int cmd_fd,
|
||||
|
||||
/* k: whether to kill the process
|
||||
*/
|
||||
void remove_proc(main_server_st * s, struct proc_st *proc, unsigned flags)
|
||||
void remove_proc(main_server_st *s, struct proc_st *proc, unsigned int flags)
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
@@ -102,19 +103,25 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned flags)
|
||||
list_del(&proc->list);
|
||||
s->stats.active_clients--;
|
||||
|
||||
if ((flags&RPROC_KILL) && proc->pid != -1 && proc->pid != 0)
|
||||
if ((flags & RPROC_KILL) && proc->pid != -1 && proc->pid != 0)
|
||||
kill(proc->pid, SIGTERM);
|
||||
|
||||
/* close any pending sessions */
|
||||
if (proc->active_sid && !(flags & RPROC_QUIT)) {
|
||||
if (session_close(&(s->sec_mod_instances[proc->sec_mod_instance_index]), proc) < 0) {
|
||||
mslog(s, proc, LOG_ERR, "error closing session (communication with sec-mod issue)");
|
||||
if (session_close(
|
||||
&(s->sec_mod_instances[proc->sec_mod_instance_index]),
|
||||
proc) < 0) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error closing session (communication with sec-mod issue)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
mslog(s, proc, discon_reason_to_log_level(proc->discon_reason), "user disconnected (reason: %s, rx: %"PRIu64", tx: %"PRIu64")",
|
||||
discon_reason_to_str(proc->discon_reason), proc->bytes_in, proc->bytes_out);
|
||||
mslog(s, proc, discon_reason_to_log_level(proc->discon_reason),
|
||||
"user disconnected (reason: %s, rx: %" PRIu64 ", tx: %" PRIu64
|
||||
")",
|
||||
discon_reason_to_str(proc->discon_reason), proc->bytes_in,
|
||||
proc->bytes_out);
|
||||
|
||||
pid = remove_from_script_list(s, proc);
|
||||
if (proc->status == PS_AUTH_COMPLETED || pid > 0) {
|
||||
@@ -128,8 +135,8 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned flags)
|
||||
user_disconnected(s, proc);
|
||||
}
|
||||
} else { /* pid > 0 or status == PS_AUTH_COMPLETED are mutually exclusive
|
||||
* since PS_AUTH_COMPLETED is set only after a successful script run.
|
||||
*/
|
||||
* since PS_AUTH_COMPLETED is set only after a successful script run.
|
||||
*/
|
||||
user_disconnected(s, proc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,13 +52,14 @@
|
||||
#include <ccan/list/list.h>
|
||||
|
||||
#ifdef HAVE_MALLOC_TRIM
|
||||
# include <malloc.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
static void update_auth_failures(main_server_st * s, uint64_t auth_failures)
|
||||
static void update_auth_failures(main_server_st *s, uint64_t auth_failures)
|
||||
{
|
||||
if (s->stats.auth_failures + auth_failures < s->stats.auth_failures) {
|
||||
mslog(s, NULL, LOG_INFO, "overflow on updating authentication failures; resetting");
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"overflow on updating authentication failures; resetting");
|
||||
s->stats.auth_failures = 0;
|
||||
return;
|
||||
}
|
||||
@@ -66,9 +67,9 @@ static void update_auth_failures(main_server_st * s, uint64_t auth_failures)
|
||||
s->stats.total_auth_failures += auth_failures;
|
||||
}
|
||||
|
||||
int handle_sec_mod_commands(sec_mod_instance_st * sec_mod_instance)
|
||||
int handle_sec_mod_commands(sec_mod_instance_st *sec_mod_instance)
|
||||
{
|
||||
struct main_server_st * s = sec_mod_instance->server;
|
||||
struct main_server_st *s = sec_mod_instance->server;
|
||||
struct iovec iov[3];
|
||||
uint8_t cmd;
|
||||
struct msghdr hdr;
|
||||
@@ -76,6 +77,7 @@ int handle_sec_mod_commands(sec_mod_instance_st * sec_mod_instance)
|
||||
uint8_t *raw;
|
||||
int ret, raw_len, e;
|
||||
void *pool = talloc_new(s);
|
||||
|
||||
PROTOBUF_ALLOCATOR(pa, pool);
|
||||
BanIpMsg *tmsg = NULL;
|
||||
|
||||
@@ -108,14 +110,17 @@ int handle_sec_mod_commands(sec_mod_instance_st * sec_mod_instance)
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (ret < 5 || cmd <= MIN_SECM_CMD || cmd >= MAX_SECM_CMD || (int)length < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "main received invalid message from sec-mod of %d bytes (cmd: %u)\n",
|
||||
(int)length, (unsigned)cmd);
|
||||
if (ret < 5 || cmd <= MIN_SECM_CMD || cmd >= MAX_SECM_CMD ||
|
||||
(int)length < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"main received invalid message from sec-mod of %d bytes (cmd: %u)\n",
|
||||
(int)length, (unsigned int)cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
mslog(s, NULL, LOG_DEBUG, "main received message '%s' from sec-mod of %u bytes\n",
|
||||
cmd_request_to_str(cmd), (unsigned)length);
|
||||
mslog(s, NULL, LOG_DEBUG,
|
||||
"main received message '%s' from sec-mod of %u bytes\n",
|
||||
cmd_request_to_str(cmd), (unsigned int)length);
|
||||
|
||||
raw = talloc_size(pool, length);
|
||||
if (raw == NULL) {
|
||||
@@ -123,86 +128,90 @@ int handle_sec_mod_commands(sec_mod_instance_st * sec_mod_instance)
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
raw_len = force_read_timeout(sec_mod_instance->sec_mod_fd, raw, length, MAIN_SEC_MOD_TIMEOUT);
|
||||
raw_len = force_read_timeout(sec_mod_instance->sec_mod_fd, raw, length,
|
||||
MAIN_SEC_MOD_TIMEOUT);
|
||||
if (raw_len != length) {
|
||||
e = errno;
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"cannot obtain data of cmd %u with length %u from sec-mod socket: %s",
|
||||
(unsigned)cmd, (unsigned)length, strerror(e));
|
||||
(unsigned int)cmd, (unsigned int)length, strerror(e));
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case CMD_SECM_BAN_IP:{
|
||||
BanIpReplyMsg reply = BAN_IP_REPLY_MSG__INIT;
|
||||
case CMD_SECM_BAN_IP: {
|
||||
BanIpReplyMsg reply = BAN_IP_REPLY_MSG__INIT;
|
||||
|
||||
tmsg = ban_ip_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, NULL, LOG_ERR, "error unpacking sec-mod data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
/* No need to authenticate tmsg->ip as sec-mod is trusted */
|
||||
ret = add_str_ip_to_ban_list(s, tmsg->ip, tmsg->score);
|
||||
if (ret < 0) {
|
||||
reply.reply =
|
||||
AUTH__REP__FAILED;
|
||||
} else {
|
||||
/* no need to send a reply at all */
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
reply.sid.data = tmsg->sid.data;
|
||||
reply.sid.len = tmsg->sid.len;
|
||||
reply.has_sid = tmsg->has_sid;
|
||||
|
||||
mslog(s, NULL, LOG_DEBUG, "sending msg %s to sec-mod", cmd_request_to_str(CMD_SECM_BAN_IP_REPLY));
|
||||
|
||||
ret = send_msg(NULL, sec_mod_instance->sec_mod_fd, CMD_SECM_BAN_IP_REPLY,
|
||||
&reply, (pack_size_func)ban_ip_reply_msg__get_packed_size,
|
||||
(pack_func)ban_ip_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"could not send reply cmd %d.",
|
||||
(unsigned)cmd);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
safe_memset(tmsg->sid.data, 0, tmsg->sid.len);
|
||||
safe_memset(raw, 0, raw_len);
|
||||
tmsg = ban_ip_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, NULL, LOG_ERR, "error unpacking sec-mod data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
/* No need to authenticate tmsg->ip as sec-mod is trusted */
|
||||
ret = add_str_ip_to_ban_list(s, tmsg->ip, tmsg->score);
|
||||
if (ret < 0) {
|
||||
reply.reply = AUTH__REP__FAILED;
|
||||
} else {
|
||||
/* no need to send a reply at all */
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
break;
|
||||
case CMD_SECM_STATS:{
|
||||
SecmStatsMsg *smsg = NULL;
|
||||
reply.sid.data = tmsg->sid.data;
|
||||
reply.sid.len = tmsg->sid.len;
|
||||
reply.has_sid = tmsg->has_sid;
|
||||
|
||||
smsg = secm_stats_msg__unpack(&pa, raw_len, raw);
|
||||
if (smsg == NULL) {
|
||||
mslog(s, NULL, LOG_ERR, "error unpacking sec-mod data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sec_mod_instance->secmod_client_entries = smsg->secmod_client_entries;
|
||||
sec_mod_instance->tlsdb_entries = smsg->secmod_tlsdb_entries;
|
||||
sec_mod_instance->max_auth_time = smsg->secmod_max_auth_time;
|
||||
sec_mod_instance->avg_auth_time = smsg->secmod_avg_auth_time;
|
||||
update_auth_failures(s, smsg->secmod_auth_failures);
|
||||
mslog(s, NULL, LOG_DEBUG, "sending msg %s to sec-mod",
|
||||
cmd_request_to_str(CMD_SECM_BAN_IP_REPLY));
|
||||
|
||||
ret = send_msg(
|
||||
NULL, sec_mod_instance->sec_mod_fd,
|
||||
CMD_SECM_BAN_IP_REPLY, &reply,
|
||||
(pack_size_func)ban_ip_reply_msg__get_packed_size,
|
||||
(pack_func)ban_ip_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "could not send reply cmd %d.",
|
||||
(unsigned int)cmd);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
break;
|
||||
safe_memset(tmsg->sid.data, 0, tmsg->sid.len);
|
||||
safe_memset(raw, 0, raw_len);
|
||||
}
|
||||
|
||||
break;
|
||||
case CMD_SECM_STATS: {
|
||||
SecmStatsMsg *smsg = NULL;
|
||||
|
||||
smsg = secm_stats_msg__unpack(&pa, raw_len, raw);
|
||||
if (smsg == NULL) {
|
||||
mslog(s, NULL, LOG_ERR, "error unpacking sec-mod data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sec_mod_instance->secmod_client_entries =
|
||||
smsg->secmod_client_entries;
|
||||
sec_mod_instance->tlsdb_entries = smsg->secmod_tlsdb_entries;
|
||||
sec_mod_instance->max_auth_time = smsg->secmod_max_auth_time;
|
||||
sec_mod_instance->avg_auth_time = smsg->secmod_avg_auth_time;
|
||||
update_auth_failures(s, smsg->secmod_auth_failures);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
mslog(s, NULL, LOG_ERR, "unknown CMD from sec-mod 0x%x.", (unsigned)cmd);
|
||||
mslog(s, NULL, LOG_ERR, "unknown CMD from sec-mod 0x%x.",
|
||||
(unsigned int)cmd);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (tmsg != NULL)
|
||||
ban_ip_msg__free_unpacked(tmsg, &pa);
|
||||
talloc_free(raw);
|
||||
@@ -211,25 +220,29 @@ int handle_sec_mod_commands(sec_mod_instance_st * sec_mod_instance)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void append_routes(sec_mod_instance_st * sec_mod_instance, proc_st *proc, GroupCfgSt *gc)
|
||||
static void append_routes(sec_mod_instance_st *sec_mod_instance, proc_st *proc,
|
||||
GroupCfgSt *gc)
|
||||
{
|
||||
vhost_cfg_st *vhost = proc->vhost;
|
||||
|
||||
/* if we have known_iroutes, we must append them to the routes list */
|
||||
if (vhost->perm_config.config->known_iroutes_size > 0 || vhost->perm_config.config->append_routes) {
|
||||
if (vhost->perm_config.config->known_iroutes_size > 0 ||
|
||||
vhost->perm_config.config->append_routes) {
|
||||
char **old_routes = gc->routes;
|
||||
unsigned old_routes_size = gc->n_routes;
|
||||
unsigned i, j, append;
|
||||
unsigned to_append = 0;
|
||||
unsigned int old_routes_size = gc->n_routes;
|
||||
unsigned int i, j, append;
|
||||
unsigned int to_append = 0;
|
||||
|
||||
to_append = vhost->perm_config.config->known_iroutes_size;
|
||||
if (vhost->perm_config.config->append_routes)
|
||||
to_append += vhost->perm_config.config->network.routes_size;
|
||||
to_append +=
|
||||
vhost->perm_config.config->network.routes_size;
|
||||
|
||||
gc->n_routes = 0;
|
||||
gc->routes = talloc_size(proc, sizeof(char*)*(old_routes_size+to_append));
|
||||
gc->routes = talloc_size(
|
||||
proc, sizeof(char *) * (old_routes_size + to_append));
|
||||
|
||||
for (i=0;i<old_routes_size;i++) {
|
||||
for (i = 0; i < old_routes_size; i++) {
|
||||
gc->routes[i] = talloc_strdup(proc, old_routes[i]);
|
||||
if (gc->routes[i] == NULL)
|
||||
break;
|
||||
@@ -238,17 +251,25 @@ static void append_routes(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
|
||||
if (gc->routes) {
|
||||
/* Append any iroutes that are known and don't match the client's */
|
||||
for (i=0;i<vhost->perm_config.config->known_iroutes_size;i++) {
|
||||
for (i = 0;
|
||||
i < vhost->perm_config.config->known_iroutes_size;
|
||||
i++) {
|
||||
append = 1;
|
||||
for (j=0;j<gc->n_iroutes;j++) {
|
||||
if (strcmp(gc->iroutes[j], vhost->perm_config.config->known_iroutes[i]) == 0) {
|
||||
for (j = 0; j < gc->n_iroutes; j++) {
|
||||
if (strcmp(gc->iroutes[j],
|
||||
vhost->perm_config.config
|
||||
->known_iroutes[i]) ==
|
||||
0) {
|
||||
append = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (append) {
|
||||
gc->routes[gc->n_routes] = talloc_strdup(proc, vhost->perm_config.config->known_iroutes[i]);
|
||||
gc->routes[gc->n_routes] = talloc_strdup(
|
||||
proc,
|
||||
vhost->perm_config.config
|
||||
->known_iroutes[i]);
|
||||
if (gc->routes[gc->n_routes] == NULL)
|
||||
break;
|
||||
gc->n_routes++;
|
||||
@@ -259,8 +280,13 @@ static void append_routes(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
if (vhost->perm_config.config->append_routes) {
|
||||
/* Append all global routes */
|
||||
if (gc->routes) {
|
||||
for (i=0;i<vhost->perm_config.config->network.routes_size;i++) {
|
||||
gc->routes[gc->n_routes] = talloc_strdup(proc, vhost->perm_config.config->network.routes[i]);
|
||||
for (i = 0; i < vhost->perm_config.config
|
||||
->network.routes_size;
|
||||
i++) {
|
||||
gc->routes[gc->n_routes] = talloc_strdup(
|
||||
proc,
|
||||
vhost->perm_config.config
|
||||
->network.routes[i]);
|
||||
if (gc->routes[gc->n_routes] == NULL)
|
||||
break;
|
||||
gc->n_routes++;
|
||||
@@ -268,24 +294,36 @@ static void append_routes(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
|
||||
/* Append no-routes */
|
||||
if (vhost->perm_config.config->network.no_routes_size == 0)
|
||||
if (vhost->perm_config.config->network.no_routes_size ==
|
||||
0)
|
||||
return;
|
||||
|
||||
old_routes = gc->no_routes;
|
||||
old_routes_size = gc->n_no_routes;
|
||||
|
||||
gc->n_no_routes = 0;
|
||||
gc->no_routes = talloc_size(proc, sizeof(char*)*(old_routes_size+vhost->perm_config.config->network.no_routes_size));
|
||||
gc->no_routes = talloc_size(
|
||||
proc,
|
||||
sizeof(char *) *
|
||||
(old_routes_size +
|
||||
vhost->perm_config.config->network
|
||||
.no_routes_size));
|
||||
|
||||
for (i=0;i<old_routes_size;i++) {
|
||||
gc->no_routes[i] = talloc_strdup(proc, old_routes[i]);
|
||||
for (i = 0; i < old_routes_size; i++) {
|
||||
gc->no_routes[i] =
|
||||
talloc_strdup(proc, old_routes[i]);
|
||||
if (gc->no_routes[i] == NULL)
|
||||
break;
|
||||
gc->n_no_routes++;
|
||||
}
|
||||
|
||||
for (i=0;i<vhost->perm_config.config->network.no_routes_size;i++) {
|
||||
gc->no_routes[gc->n_no_routes] = talloc_strdup(proc, vhost->perm_config.config->network.no_routes[i]);
|
||||
for (i = 0;
|
||||
i <
|
||||
vhost->perm_config.config->network.no_routes_size;
|
||||
i++) {
|
||||
gc->no_routes[gc->n_no_routes] = talloc_strdup(
|
||||
proc, vhost->perm_config.config->network
|
||||
.no_routes[i]);
|
||||
if (gc->no_routes[gc->n_no_routes] == NULL)
|
||||
break;
|
||||
gc->n_no_routes++;
|
||||
@@ -294,13 +332,13 @@ static void append_routes(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc, GroupCfgSt *gc)
|
||||
static void apply_default_config(sec_mod_instance_st *sec_mod_instance,
|
||||
proc_st *proc, GroupCfgSt *gc)
|
||||
{
|
||||
vhost_cfg_st *vhost = proc->vhost;
|
||||
|
||||
if (!gc->has_no_udp) {
|
||||
gc->no_udp = (vhost->perm_config.udp_port!=0)?0:1;
|
||||
gc->no_udp = (vhost->perm_config.udp_port != 0) ? 0 : 1;
|
||||
gc->has_no_udp = 1;
|
||||
}
|
||||
|
||||
@@ -313,7 +351,8 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
|
||||
if (gc->no_routes == NULL) {
|
||||
gc->no_routes = vhost->perm_config.config->network.no_routes;
|
||||
gc->n_no_routes = vhost->perm_config.config->network.no_routes_size;
|
||||
gc->n_no_routes =
|
||||
vhost->perm_config.config->network.no_routes_size;
|
||||
}
|
||||
|
||||
if (gc->dns == NULL) {
|
||||
@@ -332,12 +371,14 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
|
||||
if (!gc->has_interim_update_secs) {
|
||||
gc->interim_update_secs = vhost->perm_config.config->stats_report_time;
|
||||
gc->interim_update_secs =
|
||||
vhost->perm_config.config->stats_report_time;
|
||||
gc->has_interim_update_secs = 1;
|
||||
}
|
||||
|
||||
if (!gc->has_session_timeout_secs) {
|
||||
gc->session_timeout_secs = vhost->perm_config.config->session_timeout;
|
||||
gc->session_timeout_secs =
|
||||
vhost->perm_config.config->session_timeout;
|
||||
gc->has_session_timeout_secs = 1;
|
||||
}
|
||||
|
||||
@@ -351,7 +392,8 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
|
||||
if (!gc->ipv4_netmask) {
|
||||
gc->ipv4_netmask = vhost->perm_config.config->network.ipv4_netmask;
|
||||
gc->ipv4_netmask =
|
||||
vhost->perm_config.config->network.ipv4_netmask;
|
||||
}
|
||||
|
||||
if (!gc->ipv6_net) {
|
||||
@@ -359,12 +401,14 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
|
||||
if (!gc->has_ipv6_prefix) {
|
||||
gc->ipv6_prefix = vhost->perm_config.config->network.ipv6_prefix;
|
||||
gc->ipv6_prefix =
|
||||
vhost->perm_config.config->network.ipv6_prefix;
|
||||
gc->has_ipv6_prefix = 1;
|
||||
}
|
||||
|
||||
if (!gc->has_ipv6_subnet_prefix) {
|
||||
gc->ipv6_subnet_prefix = vhost->perm_config.config->network.ipv6_subnet_prefix;
|
||||
gc->ipv6_subnet_prefix =
|
||||
vhost->perm_config.config->network.ipv6_subnet_prefix;
|
||||
gc->has_ipv6_subnet_prefix = 1;
|
||||
}
|
||||
|
||||
@@ -374,12 +418,14 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
|
||||
#ifdef ANYCONNECT_CLIENT_COMPAT
|
||||
if (!gc->xml_config_file) {
|
||||
gc->xml_config_file = vhost->perm_config.config->xml_config_file;
|
||||
gc->xml_config_file =
|
||||
vhost->perm_config.config->xml_config_file;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!gc->has_client_bypass_protocol) {
|
||||
gc->client_bypass_protocol = vhost->perm_config.config->client_bypass_protocol;
|
||||
gc->client_bypass_protocol =
|
||||
vhost->perm_config.config->client_bypass_protocol;
|
||||
gc->has_client_bypass_protocol = 1;
|
||||
}
|
||||
|
||||
@@ -414,7 +460,8 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
|
||||
if (!gc->has_max_same_clients) {
|
||||
gc->max_same_clients = vhost->perm_config.config->max_same_clients;
|
||||
gc->max_same_clients =
|
||||
vhost->perm_config.config->max_same_clients;
|
||||
gc->has_max_same_clients = 1;
|
||||
}
|
||||
|
||||
@@ -424,7 +471,8 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
|
||||
if (!gc->has_restrict_user_to_routes) {
|
||||
gc->restrict_user_to_routes = vhost->perm_config.config->restrict_user_to_routes;
|
||||
gc->restrict_user_to_routes =
|
||||
vhost->perm_config.config->restrict_user_to_routes;
|
||||
gc->has_restrict_user_to_routes = 1;
|
||||
}
|
||||
|
||||
@@ -439,7 +487,8 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
}
|
||||
|
||||
if (!gc->has_mobile_idle_timeout) {
|
||||
gc->mobile_idle_timeout = vhost->perm_config.config->mobile_idle_timeout;
|
||||
gc->mobile_idle_timeout =
|
||||
vhost->perm_config.config->mobile_idle_timeout;
|
||||
gc->has_mobile_idle_timeout = 1;
|
||||
}
|
||||
|
||||
@@ -453,10 +502,11 @@ void apply_default_config(sec_mod_instance_st * sec_mod_instance, proc_st *proc,
|
||||
(*proc->config_usage_count)++;
|
||||
}
|
||||
|
||||
int session_open(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc, const uint8_t *cookie, unsigned cookie_size)
|
||||
int session_open(sec_mod_instance_st *sec_mod_instance, struct proc_st *proc,
|
||||
const uint8_t *cookie, unsigned int cookie_size)
|
||||
{
|
||||
int ret, e;
|
||||
main_server_st * s = sec_mod_instance->server;
|
||||
main_server_st *s = sec_mod_instance->server;
|
||||
SecmSessionOpenMsg ireq = SECM_SESSION_OPEN_MSG__INIT;
|
||||
SecmSessionReplyMsg *msg = NULL;
|
||||
char str_ipv4[MAX_IP_STR];
|
||||
@@ -466,37 +516,43 @@ int session_open(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc, c
|
||||
if (cookie == NULL || cookie_size != SID_SIZE)
|
||||
return -1;
|
||||
|
||||
ireq.sid.data = (void*)cookie;
|
||||
ireq.sid.data = (void *)cookie;
|
||||
ireq.sid.len = cookie_size;
|
||||
|
||||
if (proc->ipv4 &&
|
||||
human_addr2((struct sockaddr *)&proc->ipv4->rip, proc->ipv4->rip_len,
|
||||
str_ipv4, sizeof(str_ipv4), 0) != NULL) {
|
||||
if (proc->ipv4 && human_addr2((struct sockaddr *)&proc->ipv4->rip,
|
||||
proc->ipv4->rip_len, str_ipv4,
|
||||
sizeof(str_ipv4), 0) != NULL) {
|
||||
ireq.ipv4 = str_ipv4;
|
||||
}
|
||||
|
||||
if (proc->ipv6 &&
|
||||
human_addr2((struct sockaddr *)&proc->ipv6->rip, proc->ipv6->rip_len,
|
||||
str_ipv6, sizeof(str_ipv6), 0) != NULL) {
|
||||
if (proc->ipv6 && human_addr2((struct sockaddr *)&proc->ipv6->rip,
|
||||
proc->ipv6->rip_len, str_ipv6,
|
||||
sizeof(str_ipv6), 0) != NULL) {
|
||||
ireq.ipv6 = str_ipv6;
|
||||
}
|
||||
|
||||
mslog(s, proc, LOG_DEBUG, "sending msg %s to sec-mod", cmd_request_to_str(CMD_SECM_SESSION_OPEN));
|
||||
mslog(s, proc, LOG_DEBUG, "sending msg %s to sec-mod",
|
||||
cmd_request_to_str(CMD_SECM_SESSION_OPEN));
|
||||
|
||||
ret = send_msg(proc, sec_mod_instance->sec_mod_fd_sync, CMD_SECM_SESSION_OPEN,
|
||||
&ireq, (pack_size_func)secm_session_open_msg__get_packed_size,
|
||||
(pack_func)secm_session_open_msg__pack);
|
||||
ret = send_msg(proc, sec_mod_instance->sec_mod_fd_sync,
|
||||
CMD_SECM_SESSION_OPEN, &ireq,
|
||||
(pack_size_func)secm_session_open_msg__get_packed_size,
|
||||
(pack_func)secm_session_open_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error sending message to sec-mod cmd socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = recv_msg(proc, sec_mod_instance->sec_mod_fd_sync, CMD_SECM_SESSION_REPLY,
|
||||
(void *)&msg, (unpack_func) secm_session_reply_msg__unpack, MAIN_SEC_MOD_TIMEOUT);
|
||||
ret = recv_msg(proc, sec_mod_instance->sec_mod_fd_sync,
|
||||
CMD_SECM_SESSION_REPLY, (void *)&msg,
|
||||
(unpack_func)secm_session_reply_msg__unpack,
|
||||
MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
mslog(s, proc, LOG_ERR, "error receiving auth reply message from sec-mod cmd socket: %s", strerror(e));
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error receiving auth reply message from sec-mod cmd socket: %s",
|
||||
strerror(e));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -507,30 +563,37 @@ int session_open(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc, c
|
||||
}
|
||||
|
||||
if (msg->username == NULL) {
|
||||
mslog(s, proc, LOG_INFO, "no username present in session reply");
|
||||
mslog(s, proc, LOG_INFO,
|
||||
"no username present in session reply");
|
||||
return -1;
|
||||
}
|
||||
strlcpy(proc->username, msg->username, sizeof(proc->username));
|
||||
|
||||
if (msg->user_agent != NULL) {
|
||||
strlcpy(proc->user_agent, msg->user_agent, sizeof(proc->user_agent));
|
||||
strlcpy(proc->user_agent, msg->user_agent,
|
||||
sizeof(proc->user_agent));
|
||||
}
|
||||
|
||||
if (msg->device_type != NULL) {
|
||||
strlcpy(proc->device_type, msg->device_type, sizeof(proc->device_type));
|
||||
strlcpy(proc->device_type, msg->device_type,
|
||||
sizeof(proc->device_type));
|
||||
}
|
||||
|
||||
if (msg->device_platform != NULL) {
|
||||
strlcpy(proc->device_platform, msg->device_platform, sizeof(proc->device_platform));
|
||||
strlcpy(proc->device_platform, msg->device_platform,
|
||||
sizeof(proc->device_platform));
|
||||
}
|
||||
|
||||
/* override the group name in order to load the correct configuration in
|
||||
* case his group is specified in the certificate */
|
||||
if (msg->groupname)
|
||||
strlcpy(proc->groupname, msg->groupname, sizeof(proc->groupname));
|
||||
strlcpy(proc->groupname, msg->groupname,
|
||||
sizeof(proc->groupname));
|
||||
|
||||
if (msg->config == NULL) {
|
||||
mslog(s, proc, LOG_INFO, "received invalid configuration for '%s'; could not initiate session", proc->username);
|
||||
mslog(s, proc, LOG_INFO,
|
||||
"received invalid configuration for '%s'; could not initiate session",
|
||||
proc->username);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -548,13 +611,15 @@ int session_open(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc, c
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (human_addr2((struct sockaddr *)&proc->remote_addr, proc->remote_addr_len,
|
||||
str_ip, sizeof(str_ip), 0) == NULL)
|
||||
if (human_addr2((struct sockaddr *)&proc->remote_addr,
|
||||
proc->remote_addr_len, str_ip,
|
||||
sizeof(str_ip), 0) == NULL)
|
||||
return -1;
|
||||
|
||||
if (strcmp(str_ip, msg->ip) != 0) {
|
||||
mslog(s, proc, LOG_INFO, "user '%s' is re-using cookie from different IP (prev: %s, current: %s); rejecting",
|
||||
proc->username, msg->ip, str_ip);
|
||||
mslog(s, proc, LOG_INFO,
|
||||
"user '%s' is re-using cookie from different IP (prev: %s, current: %s); rejecting",
|
||||
proc->username, msg->ip, str_ip);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -568,8 +633,10 @@ static void reset_stats(main_server_st *s, time_t now)
|
||||
unsigned int i;
|
||||
unsigned long max_auth_time = 0;
|
||||
unsigned long avg_auth_time = 0;
|
||||
for (i = 0; i < s->sec_mod_instance_count; i ++) {
|
||||
max_auth_time = MAX(max_auth_time, s->sec_mod_instances[i].max_auth_time);
|
||||
|
||||
for (i = 0; i < s->sec_mod_instance_count; i++) {
|
||||
max_auth_time = MAX(max_auth_time,
|
||||
s->sec_mod_instances[i].max_auth_time);
|
||||
s->sec_mod_instances[i].max_auth_time = 0;
|
||||
avg_auth_time += s->sec_mod_instances[i].avg_auth_time;
|
||||
s->sec_mod_instances[i].avg_auth_time = 0;
|
||||
@@ -577,20 +644,34 @@ static void reset_stats(main_server_st *s, time_t now)
|
||||
if (s->sec_mod_instance_count != 0)
|
||||
avg_auth_time /= s->sec_mod_instance_count;
|
||||
mslog(s, NULL, LOG_INFO, "Start statistics block");
|
||||
mslog(s, NULL, LOG_INFO, "Total sessions handled: %lu", (unsigned long)s->stats.total_sessions_closed);
|
||||
mslog(s, NULL, LOG_INFO, "Sessions handled: %lu", (unsigned long)s->stats.sessions_closed);
|
||||
mslog(s, NULL, LOG_INFO, "Maximum session time: %lu min", (unsigned long)s->stats.max_session_mins);
|
||||
mslog(s, NULL, LOG_INFO, "Average session time: %lu min", (unsigned long)s->stats.avg_session_mins);
|
||||
mslog(s, NULL, LOG_INFO, "Closed due to timeout sessions: %lu", (unsigned long)s->stats.session_timeouts);
|
||||
mslog(s, NULL, LOG_INFO, "Closed due to timeout (idle) sessions: %lu", (unsigned long)s->stats.session_idle_timeouts);
|
||||
mslog(s, NULL, LOG_INFO, "Closed due to error sessions: %lu", (unsigned long)s->stats.session_errors);
|
||||
mslog(s, NULL, LOG_INFO, "Total sessions handled: %lu",
|
||||
(unsigned long)s->stats.total_sessions_closed);
|
||||
mslog(s, NULL, LOG_INFO, "Sessions handled: %lu",
|
||||
(unsigned long)s->stats.sessions_closed);
|
||||
mslog(s, NULL, LOG_INFO, "Maximum session time: %lu min",
|
||||
(unsigned long)s->stats.max_session_mins);
|
||||
mslog(s, NULL, LOG_INFO, "Average session time: %lu min",
|
||||
(unsigned long)s->stats.avg_session_mins);
|
||||
mslog(s, NULL, LOG_INFO, "Closed due to timeout sessions: %lu",
|
||||
(unsigned long)s->stats.session_timeouts);
|
||||
mslog(s, NULL, LOG_INFO, "Closed due to timeout (idle) sessions: %lu",
|
||||
(unsigned long)s->stats.session_idle_timeouts);
|
||||
mslog(s, NULL, LOG_INFO, "Closed due to error sessions: %lu",
|
||||
(unsigned long)s->stats.session_errors);
|
||||
|
||||
mslog(s, NULL, LOG_INFO, "Total authentication failures: %lu", (unsigned long)s->stats.total_auth_failures);
|
||||
mslog(s, NULL, LOG_INFO, "Authentication failures: %lu", (unsigned long)s->stats.auth_failures);
|
||||
mslog(s, NULL, LOG_INFO, "Maximum authentication time: %lu sec", max_auth_time);
|
||||
mslog(s, NULL, LOG_INFO, "Average authentication time: %lu sec", avg_auth_time);
|
||||
mslog(s, NULL, LOG_INFO, "Data in: %lu, out: %lu kbytes", (unsigned long)s->stats.kbytes_in, (unsigned long)s->stats.kbytes_out);
|
||||
mslog(s, NULL, LOG_INFO, "End of statistics block; resetting non-total stats");
|
||||
mslog(s, NULL, LOG_INFO, "Total authentication failures: %lu",
|
||||
(unsigned long)s->stats.total_auth_failures);
|
||||
mslog(s, NULL, LOG_INFO, "Authentication failures: %lu",
|
||||
(unsigned long)s->stats.auth_failures);
|
||||
mslog(s, NULL, LOG_INFO, "Maximum authentication time: %lu sec",
|
||||
max_auth_time);
|
||||
mslog(s, NULL, LOG_INFO, "Average authentication time: %lu sec",
|
||||
avg_auth_time);
|
||||
mslog(s, NULL, LOG_INFO, "Data in: %lu, out: %lu kbytes",
|
||||
(unsigned long)s->stats.kbytes_in,
|
||||
(unsigned long)s->stats.kbytes_out);
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"End of statistics block; resetting non-total stats");
|
||||
|
||||
s->stats.session_idle_timeouts = 0;
|
||||
s->stats.session_timeouts = 0;
|
||||
@@ -601,10 +682,9 @@ static void reset_stats(main_server_st *s, time_t now)
|
||||
s->stats.kbytes_in = 0;
|
||||
s->stats.kbytes_out = 0;
|
||||
s->stats.max_session_mins = 0;
|
||||
|
||||
}
|
||||
|
||||
static void update_main_stats(main_server_st * s, struct proc_st *proc)
|
||||
static void update_main_stats(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
uint64_t kb_in, kb_out;
|
||||
time_t now = time(NULL), stime;
|
||||
@@ -629,13 +709,13 @@ static void update_main_stats(main_server_st * s, struct proc_st *proc)
|
||||
goto reset;
|
||||
}
|
||||
|
||||
kb_in = proc->bytes_in/1000;
|
||||
kb_out = proc->bytes_out/1000;
|
||||
kb_in = proc->bytes_in / 1000;
|
||||
kb_out = proc->bytes_out / 1000;
|
||||
|
||||
if (s->stats.kbytes_in + kb_in < s->stats.kbytes_in)
|
||||
if (s->stats.kbytes_in + kb_in < s->stats.kbytes_in)
|
||||
goto reset;
|
||||
|
||||
if (s->stats.kbytes_out + kb_out < s->stats.kbytes_out)
|
||||
if (s->stats.kbytes_out + kb_out < s->stats.kbytes_out)
|
||||
goto reset;
|
||||
|
||||
s->stats.kbytes_in += kb_in;
|
||||
@@ -647,25 +727,30 @@ static void update_main_stats(main_server_st * s, struct proc_st *proc)
|
||||
s->stats.max_mtu = proc->mtu;
|
||||
|
||||
/* connection time in minutes */
|
||||
stime = (now - proc->conn_time)/60;
|
||||
stime = (now - proc->conn_time) / 60;
|
||||
if (stime > 0) {
|
||||
s->stats.avg_session_mins = ((s->stats.sessions_closed-1) * s->stats.avg_session_mins + stime) / s->stats.sessions_closed;
|
||||
s->stats.avg_session_mins = ((s->stats.sessions_closed - 1) *
|
||||
s->stats.avg_session_mins +
|
||||
stime) /
|
||||
s->stats.sessions_closed;
|
||||
if (stime > s->stats.max_session_mins)
|
||||
s->stats.max_session_mins = stime;
|
||||
}
|
||||
|
||||
return;
|
||||
reset:
|
||||
mslog(s, NULL, LOG_INFO, "overflow on updating server statistics, resetting stats");
|
||||
reset:
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"overflow on updating server statistics, resetting stats");
|
||||
reset_stats(s, now);
|
||||
}
|
||||
|
||||
int session_close(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc)
|
||||
int session_close(sec_mod_instance_st *sec_mod_instance, struct proc_st *proc)
|
||||
{
|
||||
main_server_st * s = sec_mod_instance->server;
|
||||
main_server_st *s = sec_mod_instance->server;
|
||||
int ret, e;
|
||||
SecmSessionCloseMsg ireq = SECM_SESSION_CLOSE_MSG__INIT;
|
||||
CliStatsMsg *msg = NULL;
|
||||
|
||||
PROTOBUF_ALLOCATOR(pa, proc);
|
||||
|
||||
ireq.uptime = time(NULL) - proc->conn_time;
|
||||
@@ -680,22 +765,28 @@ int session_close(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc)
|
||||
if (proc->invalidated)
|
||||
ireq.server_disconnected = 1;
|
||||
|
||||
mslog(s, proc, LOG_DEBUG, "sending msg %s to sec-mod", cmd_request_to_str(CMD_SECM_SESSION_CLOSE));
|
||||
mslog(s, proc, LOG_DEBUG, "sending msg %s to sec-mod",
|
||||
cmd_request_to_str(CMD_SECM_SESSION_CLOSE));
|
||||
|
||||
ret = send_msg(proc, sec_mod_instance->sec_mod_fd_sync, CMD_SECM_SESSION_CLOSE,
|
||||
&ireq, (pack_size_func)secm_session_close_msg__get_packed_size,
|
||||
(pack_func)secm_session_close_msg__pack);
|
||||
ret = send_msg(proc, sec_mod_instance->sec_mod_fd_sync,
|
||||
CMD_SECM_SESSION_CLOSE, &ireq,
|
||||
(pack_size_func)secm_session_close_msg__get_packed_size,
|
||||
(pack_func)secm_session_close_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error sending message to sec-mod cmd socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = recv_msg(proc, sec_mod_instance->sec_mod_fd_sync, CMD_SECM_CLI_STATS,
|
||||
(void *)&msg, (unpack_func) cli_stats_msg__unpack, MAIN_SEC_MOD_TIMEOUT);
|
||||
ret = recv_msg(proc, sec_mod_instance->sec_mod_fd_sync,
|
||||
CMD_SECM_CLI_STATS, (void *)&msg,
|
||||
(unpack_func)cli_stats_msg__unpack,
|
||||
MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
mslog(s, proc, LOG_ERR, "error receiving auth cli stats message from sec-mod cmd socket: %s", strerror(e));
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error receiving auth cli stats message from sec-mod cmd socket: %s",
|
||||
strerror(e));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -712,26 +803,29 @@ int session_close(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int secmod_reload(sec_mod_instance_st * sec_mod_instance)
|
||||
int secmod_reload(sec_mod_instance_st *sec_mod_instance)
|
||||
{
|
||||
main_server_st * s = sec_mod_instance->server;
|
||||
main_server_st *s = sec_mod_instance->server;
|
||||
int ret, e;
|
||||
|
||||
mslog(s, NULL, LOG_DEBUG, "sending msg %s to sec-mod", cmd_request_to_str(CMD_SECM_RELOAD));
|
||||
mslog(s, NULL, LOG_DEBUG, "sending msg %s to sec-mod",
|
||||
cmd_request_to_str(CMD_SECM_RELOAD));
|
||||
|
||||
ret = send_msg(s->main_pool, sec_mod_instance->sec_mod_fd_sync, CMD_SECM_RELOAD,
|
||||
NULL, NULL, NULL);
|
||||
ret = send_msg(s->main_pool, sec_mod_instance->sec_mod_fd_sync,
|
||||
CMD_SECM_RELOAD, NULL, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error sending message to sec-mod cmd socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = recv_msg(s->main_pool, sec_mod_instance->sec_mod_fd_sync, CMD_SECM_RELOAD_REPLY,
|
||||
NULL, NULL, MAIN_SEC_MOD_TIMEOUT);
|
||||
ret = recv_msg(s->main_pool, sec_mod_instance->sec_mod_fd_sync,
|
||||
CMD_SECM_RELOAD_REPLY, NULL, NULL, MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
mslog(s, NULL, LOG_ERR, "error receiving reload reply message from sec-mod cmd socket: %s", strerror(e));
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error receiving reload reply message from sec-mod cmd socket: %s",
|
||||
strerror(e));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -743,7 +837,8 @@ static void clear_unneeded_mem(struct list_head *vconfig)
|
||||
vhost_cfg_st *vhost = NULL;
|
||||
|
||||
/* deinitialize certificate credentials etc. */
|
||||
list_for_each_rev(vconfig, vhost, list) {
|
||||
list_for_each_rev(vconfig, vhost, list)
|
||||
{
|
||||
tls_vhost_deinit(vhost);
|
||||
}
|
||||
}
|
||||
@@ -752,47 +847,59 @@ static void clear_unneeded_mem(struct list_head *vconfig)
|
||||
* The sync_fd is used by main to send synchronous commands- commands which
|
||||
* expect a reply immediately.
|
||||
*/
|
||||
void run_sec_mod(sec_mod_instance_st * sec_mod_instance, unsigned int instance_index)
|
||||
void run_sec_mod(sec_mod_instance_st *sec_mod_instance,
|
||||
unsigned int instance_index)
|
||||
{
|
||||
int e, fd[2], ret;
|
||||
int sfd[2];
|
||||
pid_t pid;
|
||||
const char *p;
|
||||
|
||||
main_server_st * s = sec_mod_instance->server;
|
||||
main_server_st *s = sec_mod_instance->server;
|
||||
|
||||
/* fills sec_mod_instance->socket_file */
|
||||
|
||||
snprintf(sec_mod_instance->socket_file, sizeof(sec_mod_instance->socket_file), "%s.%d", secmod_socket_file_name(GETPCONFIG(s)), instance_index);
|
||||
mslog(s, NULL, LOG_DEBUG, "created sec-mod socket file (%s)", sec_mod_instance->socket_file);
|
||||
snprintf(sec_mod_instance->socket_file,
|
||||
sizeof(sec_mod_instance->socket_file), "%s.%d",
|
||||
secmod_socket_file_name(GETPCONFIG(s)), instance_index);
|
||||
mslog(s, NULL, LOG_DEBUG, "created sec-mod socket file (%s)",
|
||||
sec_mod_instance->socket_file);
|
||||
|
||||
if (GETPCONFIG(s)->chroot_dir != NULL) {
|
||||
ret = snprintf(sec_mod_instance->full_socket_file, sizeof(sec_mod_instance->full_socket_file), "%s/%s",
|
||||
GETPCONFIG(s)->chroot_dir, sec_mod_instance->socket_file);
|
||||
ret = snprintf(sec_mod_instance->full_socket_file,
|
||||
sizeof(sec_mod_instance->full_socket_file),
|
||||
"%s/%s", GETPCONFIG(s)->chroot_dir,
|
||||
sec_mod_instance->socket_file);
|
||||
if (ret != strlen(sec_mod_instance->full_socket_file)) {
|
||||
mslog(s, NULL, LOG_ERR, "too long chroot path; cannot create socket: %s", sec_mod_instance->full_socket_file);
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"too long chroot path; cannot create socket: %s",
|
||||
sec_mod_instance->full_socket_file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
strlcpy(sec_mod_instance->full_socket_file, sec_mod_instance->socket_file, sizeof(sec_mod_instance->full_socket_file));
|
||||
strlcpy(sec_mod_instance->full_socket_file,
|
||||
sec_mod_instance->socket_file,
|
||||
sizeof(sec_mod_instance->full_socket_file));
|
||||
}
|
||||
|
||||
p = sec_mod_instance->full_socket_file;
|
||||
|
||||
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "error creating sec-mod command socket");
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error creating sec-mod command socket");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sfd);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "error creating sec-mod sync command socket");
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"error creating sec-mod sync command socket");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid == 0) { /* child */
|
||||
if (pid == 0) { /* child */
|
||||
clear_lists(s);
|
||||
kill_on_parent_kill(SIGTERM);
|
||||
|
||||
@@ -804,17 +911,19 @@ void run_sec_mod(sec_mod_instance_st * sec_mod_instance, unsigned int instance_i
|
||||
setproctitle(PACKAGE "-sm");
|
||||
close(fd[1]);
|
||||
close(sfd[1]);
|
||||
set_cloexec_flag (fd[0], 1);
|
||||
set_cloexec_flag (sfd[0], 1);
|
||||
set_cloexec_flag(fd[0], 1);
|
||||
set_cloexec_flag(sfd[0], 1);
|
||||
clear_unneeded_mem(s->vconfig);
|
||||
sec_mod_server(s->main_pool, s->config_pool, s->vconfig, p, fd[0], sfd[0], sizeof(s->hmac_key), s->hmac_key, instance_index);
|
||||
sec_mod_server(s->main_pool, s->config_pool, s->vconfig, p,
|
||||
fd[0], sfd[0], sizeof(s->hmac_key), s->hmac_key,
|
||||
instance_index);
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (pid > 0) { /* parent */
|
||||
} else if (pid > 0) { /* parent */
|
||||
close(fd[0]);
|
||||
close(sfd[0]);
|
||||
sec_mod_instance->sec_mod_pid = pid;
|
||||
set_cloexec_flag (fd[1], 1);
|
||||
set_cloexec_flag (sfd[1], 1);
|
||||
set_cloexec_flag(fd[1], 1);
|
||||
set_cloexec_flag(sfd[1], 1);
|
||||
sec_mod_instance->sec_mod_fd_sync = sfd[1];
|
||||
sec_mod_instance->sec_mod_fd = fd[1];
|
||||
return;
|
||||
|
||||
222
src/main-user.c
222
src/main-user.c
@@ -34,7 +34,7 @@
|
||||
#include <gnutls/crypto.h>
|
||||
#include <tlslib.h>
|
||||
#ifdef HAVE_LIBUTIL
|
||||
# include <utmpx.h>
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
#include <gettime.h>
|
||||
|
||||
@@ -49,13 +49,14 @@
|
||||
|
||||
#define OCSERV_FW_SCRIPT "/usr/libexec/ocserv-fw"
|
||||
|
||||
#define APPEND_TO_STR(str, val) \
|
||||
do { \
|
||||
ret = str_append_str(str, val); \
|
||||
if (ret < 0) { \
|
||||
mslog(s, proc, LOG_ERR, "could not append value to environment\n"); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
#define APPEND_TO_STR(str, val) \
|
||||
do { \
|
||||
ret = str_append_str(str, val); \
|
||||
if (ret < 0) { \
|
||||
mslog(s, proc, LOG_ERR, \
|
||||
"could not append value to environment\n"); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef enum script_type_t {
|
||||
@@ -64,14 +65,14 @@ typedef enum script_type_t {
|
||||
SCRIPT_DISCONNECT
|
||||
} script_type_t;
|
||||
|
||||
static const char * const type_name[] = {"up", "host-update", "down"};
|
||||
static const char *const type_name[] = { "up", "host-update", "down" };
|
||||
|
||||
static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
static void export_fw_info(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
str_st str4;
|
||||
str_st str6;
|
||||
str_st str_common;
|
||||
unsigned i, negate = 0;
|
||||
unsigned int i, negate = 0;
|
||||
int ret;
|
||||
|
||||
str_init(&str4, proc);
|
||||
@@ -82,7 +83,7 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
* with legacy software such as iptables and ip6tables. */
|
||||
|
||||
/* append custom routes to str */
|
||||
for (i=0;i<proc->config->n_routes;i++) {
|
||||
for (i = 0; i < proc->config->n_routes; i++) {
|
||||
APPEND_TO_STR(&str_common, proc->config->routes[i]);
|
||||
APPEND_TO_STR(&str_common, " ");
|
||||
|
||||
@@ -95,17 +96,20 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
}
|
||||
}
|
||||
|
||||
if (str4.length > 0 && setenv("OCSERV_ROUTES4", (char*)str4.data, 1) == -1) {
|
||||
if (str4.length > 0 &&
|
||||
setenv("OCSERV_ROUTES4", (char *)str4.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export routes\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (str6.length > 0 && setenv("OCSERV_ROUTES6", (char*)str6.data, 1) == -1) {
|
||||
if (str6.length > 0 &&
|
||||
setenv("OCSERV_ROUTES6", (char *)str6.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export routes\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (str_common.length > 0 && setenv("OCSERV_ROUTES", (char*)str_common.data, 1) == -1) {
|
||||
if (str_common.length > 0 &&
|
||||
setenv("OCSERV_ROUTES", (char *)str_common.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export routes\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -117,7 +121,7 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
str_reset(&str_common);
|
||||
|
||||
/* append custom no_routes to str */
|
||||
for (i=0;i<proc->config->n_no_routes;i++) {
|
||||
for (i = 0; i < proc->config->n_no_routes; i++) {
|
||||
APPEND_TO_STR(&str_common, proc->config->no_routes[i]);
|
||||
APPEND_TO_STR(&str_common, " ");
|
||||
|
||||
@@ -130,24 +134,28 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
}
|
||||
}
|
||||
|
||||
if (str4.length > 0 && setenv("OCSERV_NO_ROUTES4", (char*)str4.data, 1) == -1) {
|
||||
if (str4.length > 0 &&
|
||||
setenv("OCSERV_NO_ROUTES4", (char *)str4.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export no-routes\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (str6.length > 0 && setenv("OCSERV_NO_ROUTES6", (char*)str6.data, 1) == -1) {
|
||||
if (str6.length > 0 &&
|
||||
setenv("OCSERV_NO_ROUTES6", (char *)str6.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export no-routes\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (str_common.length > 0 && setenv("OCSERV_NO_ROUTES", (char*)str_common.data, 1) == -1) {
|
||||
if (str_common.length > 0 &&
|
||||
setenv("OCSERV_NO_ROUTES", (char *)str_common.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export no-routes\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (proc->config->restrict_user_to_routes) {
|
||||
if (setenv("OCSERV_RESTRICT_TO_ROUTES", "1", 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export OCSERV_RESTRICT_TO_ROUTES\n");
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not export OCSERV_RESTRICT_TO_ROUTES\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -158,7 +166,7 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
str_reset(&str_common);
|
||||
|
||||
if (proc->config->n_dns > 0) {
|
||||
for (i=0;i<proc->config->n_dns;i++) {
|
||||
for (i = 0; i < proc->config->n_dns; i++) {
|
||||
APPEND_TO_STR(&str_common, proc->config->dns[i]);
|
||||
APPEND_TO_STR(&str_common, " ");
|
||||
|
||||
@@ -172,17 +180,20 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
}
|
||||
}
|
||||
|
||||
if (str4.length > 0 && setenv("OCSERV_DNS4", (char*)str4.data, 1) == -1) {
|
||||
if (str4.length > 0 &&
|
||||
setenv("OCSERV_DNS4", (char *)str4.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export DNS servers\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (str6.length > 0 && setenv("OCSERV_DNS6", (char*)str6.data, 1) == -1) {
|
||||
if (str6.length > 0 &&
|
||||
setenv("OCSERV_DNS6", (char *)str6.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export DNS servers\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (str_common.length > 0 && setenv("OCSERV_DNS", (char*)str_common.data, 1) == -1) {
|
||||
if (str_common.length > 0 &&
|
||||
setenv("OCSERV_DNS", (char *)str_common.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export DNS servers\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -196,35 +207,45 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
str_reset(&str_common);
|
||||
|
||||
if (proc->config->n_fw_ports > 0) {
|
||||
for (i=0;i<proc->config->n_fw_ports;i++) {
|
||||
for (i = 0; i < proc->config->n_fw_ports; i++) {
|
||||
if (proc->config->fw_ports[i]->negate)
|
||||
negate = 1;
|
||||
|
||||
switch (proc->config->fw_ports[i]->proto) {
|
||||
case PROTO_UDP:
|
||||
ret = str_append_printf(&str_common, "udp %u ", proc->config->fw_ports[i]->port);
|
||||
ret = str_append_printf(
|
||||
&str_common, "udp %u ",
|
||||
proc->config->fw_ports[i]->port);
|
||||
break;
|
||||
case PROTO_TCP:
|
||||
ret = str_append_printf(&str_common, "tcp %u ", proc->config->fw_ports[i]->port);
|
||||
ret = str_append_printf(
|
||||
&str_common, "tcp %u ",
|
||||
proc->config->fw_ports[i]->port);
|
||||
break;
|
||||
case PROTO_SCTP:
|
||||
ret = str_append_printf(&str_common, "sctp %u ", proc->config->fw_ports[i]->port);
|
||||
ret = str_append_printf(
|
||||
&str_common, "sctp %u ",
|
||||
proc->config->fw_ports[i]->port);
|
||||
break;
|
||||
case PROTO_ICMP:
|
||||
ret = str_append_printf(&str_common, "icmp all ");
|
||||
ret = str_append_printf(&str_common,
|
||||
"icmp all ");
|
||||
break;
|
||||
case PROTO_ESP:
|
||||
ret = str_append_printf(&str_common, "esp all ");
|
||||
ret = str_append_printf(&str_common,
|
||||
"esp all ");
|
||||
break;
|
||||
case PROTO_ICMPv6:
|
||||
ret = str_append_printf(&str_common, "icmpv6 all ");
|
||||
ret = str_append_printf(&str_common,
|
||||
"icmpv6 all ");
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR, "could not append value to environment\n");
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not append value to environment\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -232,13 +253,17 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
|
||||
if (str_common.length > 0) {
|
||||
if (negate) {
|
||||
if (setenv("OCSERV_DENY_PORTS", (char*)str_common.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export DENY_PORTS\n");
|
||||
if (setenv("OCSERV_DENY_PORTS", (char *)str_common.data,
|
||||
1) == -1) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not export DENY_PORTS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
if (setenv("OCSERV_ALLOW_PORTS", (char*)str_common.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR, "could not export ALLOW_PORTS\n");
|
||||
if (setenv("OCSERV_ALLOW_PORTS",
|
||||
(char *)str_common.data, 1) == -1) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not export ALLOW_PORTS\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -247,12 +272,12 @@ static void export_fw_info(main_server_st *s, struct proc_st* proc)
|
||||
str_clear(&str_common);
|
||||
}
|
||||
|
||||
static
|
||||
int call_script(main_server_st *s, struct proc_st* proc, script_type_t type)
|
||||
static int call_script(main_server_st *s, struct proc_st *proc,
|
||||
script_type_t type)
|
||||
{
|
||||
pid_t pid;
|
||||
int ret;
|
||||
const char* script, *next_script = NULL;
|
||||
pid_t pid;
|
||||
int ret;
|
||||
const char *script, *next_script = NULL;
|
||||
|
||||
if (type == SCRIPT_CONNECT)
|
||||
script = GETCONFIG(s)->connect_script;
|
||||
@@ -262,7 +287,8 @@ const char* script, *next_script = NULL;
|
||||
script = GETCONFIG(s)->disconnect_script;
|
||||
|
||||
if (type != SCRIPT_HOST_UPDATE) {
|
||||
if (proc->config->restrict_user_to_routes || proc->config->n_fw_ports > 0) {
|
||||
if (proc->config->restrict_user_to_routes ||
|
||||
proc->config->n_fw_ports > 0) {
|
||||
next_script = script;
|
||||
script = OCSERV_FW_SCRIPT;
|
||||
}
|
||||
@@ -279,20 +305,32 @@ const char* script, *next_script = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &sig_default_set, NULL);
|
||||
|
||||
snprintf(real, sizeof(real), "%u", (unsigned)proc->pid);
|
||||
snprintf(real, sizeof(real), "%u", (unsigned int)proc->pid);
|
||||
setenv("ID", real, 1);
|
||||
|
||||
if (proc->remote_addr_len > 0) {
|
||||
if ((ret=getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, real, sizeof(real), NULL, 0, NI_NUMERICHOST)) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot determine peer address: %s; script failed", gai_strerror(ret));
|
||||
ret = getnameinfo((void *)&proc->remote_addr,
|
||||
proc->remote_addr_len, real,
|
||||
sizeof(real), NULL, 0,
|
||||
NI_NUMERICHOST);
|
||||
if (ret != 0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot determine peer address: %s; script failed",
|
||||
gai_strerror(ret));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
setenv("IP_REAL", real, 1);
|
||||
}
|
||||
|
||||
if (proc->our_addr_len > 0) {
|
||||
if ((ret=getnameinfo((void*)&proc->our_addr, proc->our_addr_len, real, sizeof(real), NULL, 0, NI_NUMERICHOST)) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot determine our address: %s", gai_strerror(ret));
|
||||
ret = getnameinfo((void *)&proc->our_addr,
|
||||
proc->our_addr_len, real,
|
||||
sizeof(real), NULL, 0,
|
||||
NI_NUMERICHOST);
|
||||
if (ret != 0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot determine our address: %s",
|
||||
gai_strerror(ret));
|
||||
} else {
|
||||
setenv("IP_REAL_LOCAL", real, 1);
|
||||
}
|
||||
@@ -300,16 +338,24 @@ const char* script, *next_script = NULL;
|
||||
|
||||
if (proc->ipv4 != NULL || proc->ipv6 != NULL) {
|
||||
if (proc->ipv4 && proc->ipv4->lip_len > 0) {
|
||||
if (getnameinfo((void*)&proc->ipv4->lip, proc->ipv4->lip_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot determine local VPN address; script failed");
|
||||
if (getnameinfo((void *)&proc->ipv4->lip,
|
||||
proc->ipv4->lip_len, local,
|
||||
sizeof(local), NULL, 0,
|
||||
NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot determine local VPN address; script failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
setenv("IP_LOCAL", local, 1);
|
||||
}
|
||||
|
||||
if (proc->ipv6 && proc->ipv6->lip_len > 0) {
|
||||
if (getnameinfo((void*)&proc->ipv6->lip, proc->ipv6->lip_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot determine local VPN PtP address; script failed");
|
||||
if (getnameinfo((void *)&proc->ipv6->lip,
|
||||
proc->ipv6->lip_len, local,
|
||||
sizeof(local), NULL, 0,
|
||||
NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot determine local VPN PtP address; script failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (local[0] == 0)
|
||||
@@ -318,22 +364,31 @@ const char* script, *next_script = NULL;
|
||||
}
|
||||
|
||||
if (proc->ipv4 && proc->ipv4->rip_len > 0) {
|
||||
if (getnameinfo((void*)&proc->ipv4->rip, proc->ipv4->rip_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot determine local VPN address; script failed");
|
||||
if (getnameinfo((void *)&proc->ipv4->rip,
|
||||
proc->ipv4->rip_len, remote,
|
||||
sizeof(remote), NULL, 0,
|
||||
NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot determine local VPN address; script failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
setenv("IP_REMOTE", remote, 1);
|
||||
}
|
||||
if (proc->ipv6 && proc->ipv6->rip_len > 0) {
|
||||
if (getnameinfo((void*)&proc->ipv6->rip, proc->ipv6->rip_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG, "cannot determine local VPN PtP address; script failed");
|
||||
if (getnameinfo((void *)&proc->ipv6->rip,
|
||||
proc->ipv6->rip_len, remote,
|
||||
sizeof(remote), NULL, 0,
|
||||
NI_NUMERICHOST) != 0) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot determine local VPN PtP address; script failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (remote[0] == 0)
|
||||
setenv("IP_REMOTE", remote, 1);
|
||||
setenv("IPV6_REMOTE", remote, 1);
|
||||
|
||||
snprintf(remote, sizeof(remote), "%u", proc->ipv6->prefix);
|
||||
snprintf(remote, sizeof(remote), "%u",
|
||||
proc->ipv6->prefix);
|
||||
setenv("IPV6_PREFIX", remote, 1);
|
||||
}
|
||||
}
|
||||
@@ -355,12 +410,16 @@ const char* script, *next_script = NULL;
|
||||
setenv("REASON", "host-update", 1);
|
||||
} else if (type == SCRIPT_DISCONNECT) {
|
||||
/* use remote as temp buffer */
|
||||
snprintf(remote, sizeof(remote), "%lu", (unsigned long)proc->bytes_in);
|
||||
snprintf(remote, sizeof(remote), "%lu",
|
||||
(unsigned long)proc->bytes_in);
|
||||
setenv("STATS_BYTES_IN", remote, 1);
|
||||
snprintf(remote, sizeof(remote), "%lu", (unsigned long)proc->bytes_out);
|
||||
snprintf(remote, sizeof(remote), "%lu",
|
||||
(unsigned long)proc->bytes_out);
|
||||
setenv("STATS_BYTES_OUT", remote, 1);
|
||||
if (proc->conn_time > 0) {
|
||||
snprintf(remote, sizeof(remote), "%lu", (unsigned long)(time(NULL)-proc->conn_time));
|
||||
snprintf(remote, sizeof(remote), "%lu",
|
||||
(unsigned long)(time(NULL) -
|
||||
proc->conn_time));
|
||||
setenv("STATS_DURATION", remote, 1);
|
||||
}
|
||||
setenv("REASON", "disconnect", 1);
|
||||
@@ -372,18 +431,25 @@ const char* script, *next_script = NULL;
|
||||
/* set stdout to be stderr to avoid confusing scripts - note we have stdout closed */
|
||||
if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
|
||||
int e = errno;
|
||||
mslog(s, proc, LOG_INFO, "cannot dup2(STDERR_FILENO, STDOUT_FILENO): %s", strerror(e));
|
||||
|
||||
mslog(s, proc, LOG_INFO,
|
||||
"cannot dup2(STDERR_FILENO, STDOUT_FILENO): %s",
|
||||
strerror(e));
|
||||
}
|
||||
|
||||
if (next_script) {
|
||||
setenv("OCSERV_NEXT_SCRIPT", next_script, 1);
|
||||
mslog(s, proc, LOG_DEBUG, "executing script %s %s (next: %s)", type_name[type], script, next_script);
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"executing script %s %s (next: %s)",
|
||||
type_name[type], script, next_script);
|
||||
} else
|
||||
mslog(s, proc, LOG_DEBUG, "executing script %s %s", type_name[type], script);
|
||||
mslog(s, proc, LOG_DEBUG, "executing script %s %s",
|
||||
type_name[type], script);
|
||||
|
||||
ret = execl(script, script, NULL);
|
||||
if (ret == -1) {
|
||||
mslog(s, proc, LOG_ERR, "Could not execute script %s", script);
|
||||
mslog(s, proc, LOG_ERR, "Could not execute script %s",
|
||||
script);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -404,8 +470,7 @@ const char* script, *next_script = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
static void add_utmp_entry(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
#ifdef HAVE_LIBUTIL
|
||||
struct utmpx entry;
|
||||
@@ -421,15 +486,19 @@ add_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
strlcpy(entry.ut_user, proc->username, sizeof(entry.ut_user));
|
||||
#ifdef __linux__
|
||||
if (proc->remote_addr_len == sizeof(struct sockaddr_in))
|
||||
memcpy(entry.ut_addr_v6, SA_IN_P(&proc->remote_addr), sizeof(struct in_addr));
|
||||
memcpy(entry.ut_addr_v6, SA_IN_P(&proc->remote_addr),
|
||||
sizeof(struct in_addr));
|
||||
else
|
||||
memcpy(entry.ut_addr_v6, SA_IN6_P(&proc->remote_addr), sizeof(struct in6_addr));
|
||||
memcpy(entry.ut_addr_v6, SA_IN6_P(&proc->remote_addr),
|
||||
sizeof(struct in6_addr));
|
||||
#endif
|
||||
|
||||
gettime(&tv);
|
||||
entry.ut_tv.tv_sec = tv.tv_sec;
|
||||
entry.ut_tv.tv_usec = tv.tv_nsec / 1000;
|
||||
getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, entry.ut_host, sizeof(entry.ut_host), NULL, 0, NI_NUMERICHOST);
|
||||
getnameinfo((void *)&proc->remote_addr, proc->remote_addr_len,
|
||||
entry.ut_host, sizeof(entry.ut_host), NULL, 0,
|
||||
NI_NUMERICHOST);
|
||||
|
||||
setutxent();
|
||||
pututxline(&entry);
|
||||
@@ -443,7 +512,7 @@ add_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void remove_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
static void remove_utmp_entry(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
#ifdef HAVE_LIBUTIL
|
||||
struct utmpx entry;
|
||||
@@ -457,7 +526,8 @@ static void remove_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.ut_type = DEAD_PROCESS;
|
||||
if (proc->tun_lease.name[0] != 0)
|
||||
strlcpy(entry.ut_line, proc->tun_lease.name, sizeof(entry.ut_line));
|
||||
strlcpy(entry.ut_line, proc->tun_lease.name,
|
||||
sizeof(entry.ut_line));
|
||||
entry.ut_pid = proc->pid;
|
||||
|
||||
setutxent();
|
||||
@@ -474,11 +544,11 @@ static void remove_utmp_entry(main_server_st *s, struct proc_st* proc)
|
||||
#endif
|
||||
}
|
||||
|
||||
int user_connected(main_server_st *s, struct proc_st* proc)
|
||||
int user_connected(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
ctl_handler_notify(s,proc, 1);
|
||||
ctl_handler_notify(s, proc, 1);
|
||||
add_utmp_entry(s, proc);
|
||||
|
||||
ret = call_script(s, proc, SCRIPT_CONNECT);
|
||||
@@ -488,7 +558,7 @@ int ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void user_hostname_update(main_server_st *s, struct proc_st* proc)
|
||||
void user_hostname_update(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
if (proc->host_updated != 0)
|
||||
return;
|
||||
@@ -496,9 +566,9 @@ void user_hostname_update(main_server_st *s, struct proc_st* proc)
|
||||
proc->host_updated = 1;
|
||||
}
|
||||
|
||||
void user_disconnected(main_server_st *s, struct proc_st* proc)
|
||||
void user_disconnected(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
ctl_handler_notify(s,proc, 0);
|
||||
ctl_handler_notify(s, proc, 0);
|
||||
remove_utmp_entry(s, proc);
|
||||
call_script(s, proc, SCRIPT_DISCONNECT);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
#include <main-ban.h>
|
||||
#include <ccan/list/list.h>
|
||||
|
||||
int set_tun_mtu(main_server_st * s, struct proc_st *proc, unsigned mtu)
|
||||
int set_tun_mtu(main_server_st *s, struct proc_st *proc, unsigned int mtu)
|
||||
{
|
||||
int fd, ret, e;
|
||||
struct ifreq ifr;
|
||||
@@ -79,15 +79,15 @@ int set_tun_mtu(main_server_st * s, struct proc_st *proc, unsigned mtu)
|
||||
ret = ioctl(fd, SIOCSIFMTU, &ifr);
|
||||
if (ret != 0) {
|
||||
e = errno;
|
||||
mslog(s, proc, LOG_INFO, "ioctl SIOCSIFMTU(%d) error: %s",
|
||||
mtu, strerror(e));
|
||||
mslog(s, proc, LOG_INFO, "ioctl SIOCSIFMTU(%d) error: %s", mtu,
|
||||
strerror(e));
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
proc->mtu = mtu;
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
fail:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
@@ -119,8 +119,7 @@ int handle_script_exit(main_server_st *s, struct proc_st *proc, int code)
|
||||
mslog(s, proc, LOG_INFO,
|
||||
"failed authentication attempt for user '%s'",
|
||||
proc->username);
|
||||
ret =
|
||||
send_cookie_auth_reply(s, proc, AUTH__REP__FAILED);
|
||||
ret = send_cookie_auth_reply(s, proc, AUTH__REP__FAILED);
|
||||
if (ret < 0) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"could not send reply auth cmd.");
|
||||
@@ -130,7 +129,7 @@ int handle_script_exit(main_server_st *s, struct proc_st *proc, int code)
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
/* we close the lease tun fd both on success and failure.
|
||||
* The parent doesn't need to keep the tunfd, and if it does,
|
||||
* it causes issues to client.
|
||||
@@ -143,7 +142,8 @@ int handle_script_exit(main_server_st *s, struct proc_st *proc, int code)
|
||||
}
|
||||
|
||||
/* This is the function after which proc is populated */
|
||||
static int accept_user(main_server_st * s, struct proc_st *proc, unsigned cmd)
|
||||
static int accept_user(main_server_st *s, struct proc_st *proc,
|
||||
unsigned int cmd)
|
||||
{
|
||||
int ret;
|
||||
const char *group;
|
||||
@@ -169,8 +169,7 @@ static int accept_user(main_server_st * s, struct proc_st *proc, unsigned cmd)
|
||||
|
||||
if (cmd == AUTH_COOKIE_REQ) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"user of group '%s' authenticated (using cookie)",
|
||||
group);
|
||||
"user of group '%s' authenticated (using cookie)", group);
|
||||
} else {
|
||||
mslog(s, proc, LOG_INFO,
|
||||
"user of group '%s' authenticated but from unknown state! rejecting.",
|
||||
@@ -194,7 +193,7 @@ static int accept_user(main_server_st * s, struct proc_st *proc, unsigned cmd)
|
||||
* @result: the auth result
|
||||
*/
|
||||
static int handle_cookie_auth_res(main_server_st *s, struct proc_st *proc,
|
||||
unsigned cmd, int result)
|
||||
unsigned int cmd, int result)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -214,7 +213,7 @@ static int handle_cookie_auth_res(main_server_st *s, struct proc_st *proc,
|
||||
ret = ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
finished:
|
||||
finished:
|
||||
if (ret == ERR_WAIT_FOR_SCRIPT) {
|
||||
/* we will wait for script termination to send our reply.
|
||||
* The notification of peer will be done in handle_script_exit().
|
||||
@@ -230,20 +229,20 @@ static int handle_cookie_auth_res(main_server_st *s, struct proc_st *proc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_worker_commands(main_server_st * s, struct proc_st *proc)
|
||||
int handle_worker_commands(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
uint8_t cmd;
|
||||
AuthCookieRequestMsg *auth_cookie_req;
|
||||
size_t length;
|
||||
uint8_t *raw;
|
||||
int ret, raw_len, e;
|
||||
|
||||
PROTOBUF_ALLOCATOR(pa, proc);
|
||||
|
||||
ret = recv_msg_headers(proc->fd, &cmd, MAX_WAIT_SECS);
|
||||
if (ret < 0) {
|
||||
if (ret == ERR_PEER_TERMINATED)
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"worker terminated");
|
||||
mslog(s, proc, LOG_DEBUG, "worker terminated");
|
||||
else
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"cannot obtain metadata from worker's command socket");
|
||||
@@ -253,14 +252,15 @@ int handle_worker_commands(main_server_st * s, struct proc_st *proc)
|
||||
length = ret;
|
||||
|
||||
if (length > MAX_MSG_SIZE) {
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"received too big message (%d)", (int)length);
|
||||
mslog(s, proc, LOG_DEBUG, "received too big message (%d)",
|
||||
(int)length);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mslog(s, proc, LOG_DEBUG, "main received worker's message '%s' of %u bytes\n",
|
||||
cmd_request_to_str(cmd), (unsigned)length);
|
||||
mslog(s, proc, LOG_DEBUG,
|
||||
"main received worker's message '%s' of %u bytes\n",
|
||||
cmd_request_to_str(cmd), (unsigned int)length);
|
||||
|
||||
raw = talloc_size(proc, length);
|
||||
if (raw == NULL) {
|
||||
@@ -279,138 +279,145 @@ int handle_worker_commands(main_server_st * s, struct proc_st *proc)
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case CMD_BAN_IP:{
|
||||
BanIpMsg *tmsg;
|
||||
BanIpReplyMsg reply = BAN_IP_REPLY_MSG__INIT;
|
||||
char remote_address[MAX_IP_STR];
|
||||
case CMD_BAN_IP: {
|
||||
BanIpMsg *tmsg;
|
||||
BanIpReplyMsg reply = BAN_IP_REPLY_MSG__INIT;
|
||||
char remote_address[MAX_IP_STR];
|
||||
|
||||
tmsg = ban_ip_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, NULL, LOG_ERR, "error unpacking worker data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
human_addr2((struct sockaddr *)&proc->remote_addr, proc->remote_addr_len, remote_address, sizeof(remote_address), 0);
|
||||
|
||||
ret = add_str_ip_to_ban_list(s, remote_address, tmsg->score);
|
||||
|
||||
if (tmsg->has_discon_reason) {
|
||||
proc->discon_reason = tmsg->discon_reason;
|
||||
}
|
||||
|
||||
ban_ip_msg__free_unpacked(tmsg, &pa);
|
||||
|
||||
if (ret < 0) {
|
||||
reply.reply =
|
||||
AUTH__REP__FAILED;
|
||||
} else {
|
||||
reply.reply =
|
||||
AUTH__REP__OK;
|
||||
}
|
||||
|
||||
ret =
|
||||
send_msg_to_worker(s, proc, CMD_BAN_IP_REPLY, &reply,
|
||||
(pack_size_func)
|
||||
ban_ip_reply_msg__get_packed_size,
|
||||
(pack_func)
|
||||
ban_ip_reply_msg__pack);
|
||||
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR,
|
||||
"could not send reply cmd %d.",
|
||||
(unsigned)cmd);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_TUN_MTU:{
|
||||
TunMtuMsg *tmsg;
|
||||
unsigned minimum_mtu = RFC_791_MTU;
|
||||
unsigned maximum_mtu =
|
||||
proc->vhost->perm_config.config->default_mtu != 0 ?
|
||||
proc->vhost->perm_config.config->default_mtu :
|
||||
MAX_DTLS_MTU;
|
||||
|
||||
if (proc->status != PS_AUTH_COMPLETED) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"received TUN MTU in unauthenticated state.");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmsg = tun_mtu_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, proc, LOG_ERR, "error unpacking data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (tmsg->mtu < minimum_mtu || tmsg->mtu > maximum_mtu) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"worker process invalid MTU %d", (int)tmsg->mtu);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
set_tun_mtu(s, proc, tmsg->mtu);
|
||||
|
||||
tun_mtu_msg__free_unpacked(tmsg, &pa);
|
||||
tmsg = ban_ip_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, NULL, LOG_ERR, "error unpacking worker data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
break;
|
||||
case CMD_SESSION_INFO:{
|
||||
SessionInfoMsg *tmsg;
|
||||
human_addr2((struct sockaddr *)&proc->remote_addr,
|
||||
proc->remote_addr_len, remote_address,
|
||||
sizeof(remote_address), 0);
|
||||
|
||||
tmsg = session_info_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, proc, LOG_ERR, "error unpacking session info data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
ret = add_str_ip_to_ban_list(s, remote_address, tmsg->score);
|
||||
|
||||
if (tmsg->tls_ciphersuite)
|
||||
strlcpy(proc->tls_ciphersuite, tmsg->tls_ciphersuite,
|
||||
sizeof(proc->tls_ciphersuite));
|
||||
if (tmsg->dtls_ciphersuite)
|
||||
strlcpy(proc->dtls_ciphersuite, tmsg->dtls_ciphersuite,
|
||||
sizeof(proc->dtls_ciphersuite));
|
||||
if (tmsg->cstp_compr)
|
||||
strlcpy(proc->cstp_compr, tmsg->cstp_compr,
|
||||
sizeof(proc->cstp_compr));
|
||||
if (tmsg->dtls_compr)
|
||||
strlcpy(proc->dtls_compr, tmsg->dtls_compr,
|
||||
sizeof(proc->dtls_compr));
|
||||
if (tmsg->has_discon_reason) {
|
||||
proc->discon_reason = tmsg->discon_reason;
|
||||
}
|
||||
|
||||
if (proc->hostname[0] != 0) {
|
||||
user_hostname_update(s, proc);
|
||||
}
|
||||
ban_ip_msg__free_unpacked(tmsg, &pa);
|
||||
|
||||
if (GETCONFIG(s)->listen_proxy_proto) {
|
||||
if (tmsg->has_remote_addr && tmsg->remote_addr.len <= sizeof(struct sockaddr_storage)) {
|
||||
proc_table_update_ip(s, proc, (struct sockaddr_storage*)tmsg->remote_addr.data, tmsg->remote_addr.len);
|
||||
if (ret < 0) {
|
||||
reply.reply = AUTH__REP__FAILED;
|
||||
} else {
|
||||
reply.reply = AUTH__REP__OK;
|
||||
}
|
||||
|
||||
/* If the address is in the BAN list, terminate it */
|
||||
if (check_if_banned(s, &proc->remote_addr, proc->remote_addr_len) != 0) {
|
||||
if (proc->pid != -1 && proc->pid != 0) {
|
||||
kill_proc(proc);
|
||||
}
|
||||
ret = send_msg_to_worker(
|
||||
s, proc, CMD_BAN_IP_REPLY, &reply,
|
||||
(pack_size_func)ban_ip_reply_msg__get_packed_size,
|
||||
(pack_func)ban_ip_reply_msg__pack);
|
||||
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "could not send reply cmd %d.",
|
||||
(unsigned int)cmd);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
} break;
|
||||
case CMD_TUN_MTU: {
|
||||
TunMtuMsg *tmsg;
|
||||
unsigned int minimum_mtu = RFC_791_MTU;
|
||||
unsigned int maximum_mtu =
|
||||
proc->vhost->perm_config.config->default_mtu != 0 ?
|
||||
proc->vhost->perm_config.config->default_mtu :
|
||||
MAX_DTLS_MTU;
|
||||
|
||||
if (proc->status != PS_AUTH_COMPLETED) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"received TUN MTU in unauthenticated state.");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmsg = tun_mtu_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, proc, LOG_ERR, "error unpacking data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (tmsg->mtu < minimum_mtu || tmsg->mtu > maximum_mtu) {
|
||||
mslog(s, proc, LOG_ERR, "worker process invalid MTU %d",
|
||||
(int)tmsg->mtu);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
set_tun_mtu(s, proc, tmsg->mtu);
|
||||
|
||||
tun_mtu_msg__free_unpacked(tmsg, &pa);
|
||||
}
|
||||
|
||||
break;
|
||||
case CMD_SESSION_INFO: {
|
||||
SessionInfoMsg *tmsg;
|
||||
|
||||
tmsg = session_info_msg__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error unpacking session info data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (tmsg->tls_ciphersuite)
|
||||
strlcpy(proc->tls_ciphersuite, tmsg->tls_ciphersuite,
|
||||
sizeof(proc->tls_ciphersuite));
|
||||
if (tmsg->dtls_ciphersuite)
|
||||
strlcpy(proc->dtls_ciphersuite, tmsg->dtls_ciphersuite,
|
||||
sizeof(proc->dtls_ciphersuite));
|
||||
if (tmsg->cstp_compr)
|
||||
strlcpy(proc->cstp_compr, tmsg->cstp_compr,
|
||||
sizeof(proc->cstp_compr));
|
||||
if (tmsg->dtls_compr)
|
||||
strlcpy(proc->dtls_compr, tmsg->dtls_compr,
|
||||
sizeof(proc->dtls_compr));
|
||||
|
||||
if (proc->hostname[0] != 0) {
|
||||
user_hostname_update(s, proc);
|
||||
}
|
||||
|
||||
if (GETCONFIG(s)->listen_proxy_proto) {
|
||||
if (tmsg->has_remote_addr &&
|
||||
tmsg->remote_addr.len <=
|
||||
sizeof(struct sockaddr_storage)) {
|
||||
proc_table_update_ip(
|
||||
s, proc,
|
||||
(struct sockaddr_storage *)
|
||||
tmsg->remote_addr.data,
|
||||
tmsg->remote_addr.len);
|
||||
|
||||
/* If the address is in the BAN list, terminate it */
|
||||
if (check_if_banned(s, &proc->remote_addr,
|
||||
proc->remote_addr_len) !=
|
||||
0) {
|
||||
if (proc->pid != -1 && proc->pid != 0) {
|
||||
kill_proc(proc);
|
||||
}
|
||||
}
|
||||
|
||||
if (tmsg->has_our_addr && tmsg->our_addr.len <= sizeof(struct sockaddr_storage) &&
|
||||
tmsg->our_addr.len > 0) {
|
||||
memcpy(&proc->our_addr, tmsg->our_addr.data, tmsg->our_addr.len);
|
||||
proc->our_addr_len = tmsg->our_addr.len;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
session_info_msg__free_unpacked(tmsg, &pa);
|
||||
if (tmsg->has_our_addr &&
|
||||
tmsg->our_addr.len <=
|
||||
sizeof(struct sockaddr_storage) &&
|
||||
tmsg->our_addr.len > 0) {
|
||||
memcpy(&proc->our_addr, tmsg->our_addr.data,
|
||||
tmsg->our_addr.len);
|
||||
proc->our_addr_len = tmsg->our_addr.len;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
session_info_msg__free_unpacked(tmsg, &pa);
|
||||
}
|
||||
|
||||
break;
|
||||
case AUTH_COOKIE_REQ:
|
||||
if (proc->status != PS_AUTH_INACTIVE) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
@@ -420,19 +427,23 @@ int handle_worker_commands(main_server_st * s, struct proc_st *proc)
|
||||
}
|
||||
|
||||
auth_cookie_req =
|
||||
auth_cookie_request_msg__unpack(&pa, raw_len, raw);
|
||||
auth_cookie_request_msg__unpack(&pa, raw_len, raw);
|
||||
if (auth_cookie_req == NULL) {
|
||||
mslog(s, proc, LOG_ERR, "error unpacking cookie data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
proc->sec_mod_instance_index = auth_cookie_req->cookie.data[0] % s->sec_mod_instance_count;
|
||||
proc->sec_mod_instance_index = auth_cookie_req->cookie.data[0] %
|
||||
s->sec_mod_instance_count;
|
||||
|
||||
ret = handle_auth_cookie_req(&s->sec_mod_instances[proc->sec_mod_instance_index], proc, auth_cookie_req);
|
||||
ret = handle_auth_cookie_req(
|
||||
&s->sec_mod_instances[proc->sec_mod_instance_index],
|
||||
proc, auth_cookie_req);
|
||||
|
||||
safe_memset(raw, 0, raw_len);
|
||||
safe_memset(auth_cookie_req->cookie.data, 0, auth_cookie_req->cookie.len);
|
||||
safe_memset(auth_cookie_req->cookie.data, 0,
|
||||
auth_cookie_req->cookie.len);
|
||||
|
||||
auth_cookie_request_msg__free_unpacked(auth_cookie_req, &pa);
|
||||
|
||||
@@ -444,39 +455,41 @@ int handle_worker_commands(main_server_st * s, struct proc_st *proc)
|
||||
break;
|
||||
|
||||
#if defined(CAPTURE_LATENCY_SUPPORT)
|
||||
case CMD_LATENCY_STATS_DELTA:{
|
||||
LatencyStatsDelta * tmsg;
|
||||
case CMD_LATENCY_STATS_DELTA: {
|
||||
LatencyStatsDelta *tmsg;
|
||||
|
||||
if (proc->status != PS_AUTH_COMPLETED) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"received LATENCY STATS DELTA in unauthenticated state.");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
tmsg = latency_stats_delta__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, proc, LOG_ERR, "error unpacking latency stats delta data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
s->stats.delta_latency_stats.median_total += tmsg->median_delta;
|
||||
s->stats.delta_latency_stats.rms_total += tmsg->rms_delta;
|
||||
s->stats.delta_latency_stats.sample_count += tmsg->sample_count_delta;
|
||||
|
||||
latency_stats_delta__free_unpacked(tmsg, &pa);
|
||||
if (proc->status != PS_AUTH_COMPLETED) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"received LATENCY STATS DELTA in unauthenticated state.");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
tmsg = latency_stats_delta__unpack(&pa, raw_len, raw);
|
||||
if (tmsg == NULL) {
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"error unpacking latency stats delta data");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
s->stats.delta_latency_stats.median_total += tmsg->median_delta;
|
||||
s->stats.delta_latency_stats.rms_total += tmsg->rms_delta;
|
||||
s->stats.delta_latency_stats.sample_count +=
|
||||
tmsg->sample_count_delta;
|
||||
|
||||
latency_stats_delta__free_unpacked(tmsg, &pa);
|
||||
} break;
|
||||
#endif
|
||||
default:
|
||||
mslog(s, proc, LOG_ERR, "unknown CMD from worker: 0x%x", (unsigned)cmd);
|
||||
mslog(s, proc, LOG_ERR, "unknown CMD from worker: 0x%x",
|
||||
(unsigned int)cmd);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
cleanup:
|
||||
talloc_free(raw);
|
||||
|
||||
return ret;
|
||||
|
||||
865
src/main.c
865
src/main.c
File diff suppressed because it is too large
Load Diff
139
src/main.h
139
src/main.h
@@ -20,7 +20,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_MAIN_H
|
||||
# define OC_MAIN_H
|
||||
#define OC_MAIN_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -40,8 +40,8 @@
|
||||
#include <namespace.h>
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
# include <limits.h>
|
||||
# define SOL_IP IPPROTO_IP
|
||||
#include <limits.h>
|
||||
#define SOL_IP IPPROTO_IP
|
||||
#endif
|
||||
|
||||
#define COOKIE_KEY_SIZE 16
|
||||
@@ -56,7 +56,8 @@ extern ev_timer maintainance_watcher;
|
||||
|
||||
#define MAIN_MAINTENANCE_TIME (900)
|
||||
|
||||
int cmd_parser (void *pool, int argc, char **argv, struct list_head *head, bool worker);
|
||||
int cmd_parser(void *pool, int argc, char **argv, struct list_head *head,
|
||||
bool worker);
|
||||
|
||||
#if defined(CAPTURE_LATENCY_SUPPORT)
|
||||
#define LATENCY_AGGREGATION_TIME (60)
|
||||
@@ -89,7 +90,7 @@ struct script_wait_st {
|
||||
struct list_node list;
|
||||
|
||||
pid_t pid;
|
||||
struct proc_st* proc;
|
||||
struct proc_st *proc;
|
||||
};
|
||||
|
||||
/* Each worker process maps to a unique proc_st structure.
|
||||
@@ -102,7 +103,7 @@ typedef struct proc_st {
|
||||
struct list_node list;
|
||||
int fd; /* the command file descriptor */
|
||||
pid_t pid;
|
||||
unsigned pid_killed; /* if explicitly disconnected */
|
||||
unsigned int pid_killed; /* if explicitly disconnected */
|
||||
|
||||
time_t udp_fd_receive_time; /* when the corresponding process has received a UDP fd */
|
||||
|
||||
@@ -112,7 +113,7 @@ typedef struct proc_st {
|
||||
struct tun_lease_st tun_lease;
|
||||
struct ip_lease_st *ipv4;
|
||||
struct ip_lease_st *ipv6;
|
||||
unsigned leases_in_use; /* someone else got our IP leases */
|
||||
unsigned int leases_in_use; /* someone else got our IP leases */
|
||||
|
||||
struct sockaddr_storage remote_addr; /* peer address (CSTP) */
|
||||
socklen_t remote_addr_len;
|
||||
@@ -125,20 +126,21 @@ typedef struct proc_st {
|
||||
|
||||
/* The SID which acts as a cookie */
|
||||
uint8_t sid[SID_SIZE];
|
||||
unsigned active_sid;
|
||||
unsigned int active_sid;
|
||||
|
||||
/* non zero if the sid has been invalidated and must not be allowed
|
||||
* to reconnect. */
|
||||
unsigned invalidated;
|
||||
unsigned int invalidated;
|
||||
|
||||
/* whether the host-update script has already been called */
|
||||
unsigned host_updated;
|
||||
unsigned int host_updated;
|
||||
|
||||
/* The DTLS session ID associated with the TLS session
|
||||
* it is either generated or restored from a cookie.
|
||||
*/
|
||||
uint8_t dtls_session_id[GNUTLS_MAX_SESSION_ID];
|
||||
unsigned dtls_session_id_size; /* would act as a flag if session_id is set */
|
||||
unsigned int
|
||||
dtls_session_id_size; /* would act as a flag if session_id is set */
|
||||
|
||||
/* The following are set by the worker process (or by a stored cookie) */
|
||||
char username[MAX_USERNAME_SIZE]; /* the owner */
|
||||
@@ -154,7 +156,7 @@ typedef struct proc_st {
|
||||
char dtls_ciphersuite[MAX_CIPHERSUITE_NAME];
|
||||
char cstp_compr[8];
|
||||
char dtls_compr[8];
|
||||
unsigned mtu;
|
||||
unsigned int mtu;
|
||||
unsigned int sec_mod_instance_index;
|
||||
|
||||
/* if the session is initiated by a cookie the following two are set
|
||||
@@ -163,7 +165,7 @@ typedef struct proc_st {
|
||||
*/
|
||||
uint8_t ipv4_seed[4];
|
||||
|
||||
unsigned status; /* PS_AUTH_ */
|
||||
unsigned int status; /* PS_AUTH_ */
|
||||
|
||||
/* these are filled in after the worker process dies, using the
|
||||
* Cli stats message. */
|
||||
@@ -171,7 +173,8 @@ typedef struct proc_st {
|
||||
uint64_t bytes_out;
|
||||
uint32_t discon_reason; /* filled on session close */
|
||||
|
||||
unsigned applied_iroutes; /* whether the iroutes in the config have been successfully applied */
|
||||
unsigned int
|
||||
applied_iroutes; /* whether the iroutes in the config have been successfully applied */
|
||||
|
||||
/* The following we rely on talloc for deallocation */
|
||||
GroupCfgSt *config; /* custom user/group config */
|
||||
@@ -205,7 +208,7 @@ struct proc_hash_db_st {
|
||||
struct htable *db_dtls_ip;
|
||||
struct htable *db_dtls_id;
|
||||
struct htable *db_sid;
|
||||
unsigned total;
|
||||
unsigned int total;
|
||||
};
|
||||
|
||||
#if defined(CAPTURE_LATENCY_SUPPORT)
|
||||
@@ -223,10 +226,10 @@ struct main_stats_st {
|
||||
uint64_t sessions_closed; /* sessions closed since last reset */
|
||||
uint64_t kbytes_in;
|
||||
uint64_t kbytes_out;
|
||||
unsigned min_mtu;
|
||||
unsigned max_mtu;
|
||||
unsigned int min_mtu;
|
||||
unsigned int max_mtu;
|
||||
|
||||
unsigned active_clients;
|
||||
unsigned int active_clients;
|
||||
time_t start_time;
|
||||
time_t last_reset;
|
||||
|
||||
@@ -245,20 +248,20 @@ struct main_stats_st {
|
||||
};
|
||||
|
||||
typedef struct sec_mod_instance_st {
|
||||
struct main_server_st * server;
|
||||
struct main_server_st *server;
|
||||
char socket_file[_POSIX_PATH_MAX];
|
||||
char full_socket_file[_POSIX_PATH_MAX];
|
||||
pid_t sec_mod_pid;
|
||||
|
||||
struct sockaddr_un secmod_addr;
|
||||
unsigned secmod_addr_len;
|
||||
unsigned int secmod_addr_len;
|
||||
|
||||
int sec_mod_fd; /* messages are sent and received async */
|
||||
int sec_mod_fd_sync; /* messages are send in a sync order (ping-pong). Only main sends. */
|
||||
/* updated on the cli_stats_msg from sec-mod.
|
||||
* Holds the number of entries in secmod list of users */
|
||||
unsigned secmod_client_entries;
|
||||
unsigned tlsdb_entries;
|
||||
unsigned int secmod_client_entries;
|
||||
unsigned int tlsdb_entries;
|
||||
uint32_t avg_auth_time; /* in seconds */
|
||||
uint32_t max_auth_time; /* in seconds */
|
||||
|
||||
@@ -285,13 +288,13 @@ typedef struct main_server_st {
|
||||
|
||||
struct main_stats_st stats;
|
||||
|
||||
void * auth_extra;
|
||||
void *auth_extra;
|
||||
|
||||
/* This one is on worker pool */
|
||||
struct worker_st *ws;
|
||||
|
||||
unsigned int sec_mod_instance_count;
|
||||
sec_mod_instance_st * sec_mod_instances;
|
||||
sec_mod_instance_st *sec_mod_instances;
|
||||
|
||||
int top_fd;
|
||||
int ctl_fd;
|
||||
@@ -310,52 +313,55 @@ typedef struct main_server_st {
|
||||
struct rlimit fd_limits_default_set;
|
||||
#endif
|
||||
|
||||
struct if_address_st * if_addresses;
|
||||
struct if_address_st *if_addresses;
|
||||
unsigned int if_addresses_count;
|
||||
} main_server_st;
|
||||
|
||||
void clear_lists(main_server_st *s);
|
||||
|
||||
int handle_worker_commands(main_server_st *s, struct proc_st* cur);
|
||||
int handle_sec_mod_commands(sec_mod_instance_st * sec_mod_instances);
|
||||
int handle_worker_commands(main_server_st *s, struct proc_st *cur);
|
||||
int handle_sec_mod_commands(sec_mod_instance_st *sec_mod_instances);
|
||||
|
||||
int user_connected(main_server_st *s, struct proc_st* cur);
|
||||
void user_hostname_update(main_server_st *s, struct proc_st* cur);
|
||||
void user_disconnected(main_server_st *s, struct proc_st* cur);
|
||||
int user_connected(main_server_st *s, struct proc_st *cur);
|
||||
void user_hostname_update(main_server_st *s, struct proc_st *cur);
|
||||
void user_disconnected(main_server_st *s, struct proc_st *cur);
|
||||
|
||||
int send_udp_fd(main_server_st* s, struct proc_st * proc, int fd);
|
||||
int send_udp_fd(main_server_st *s, struct proc_st *proc, int fd);
|
||||
|
||||
int session_open(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc, const uint8_t *cookie, unsigned cookie_size);
|
||||
int session_close(sec_mod_instance_st * sec_mod_instance, struct proc_st *proc);
|
||||
int session_open(sec_mod_instance_st *sec_mod_instance, struct proc_st *proc,
|
||||
const uint8_t *cookie, unsigned int cookie_size);
|
||||
int session_close(sec_mod_instance_st *sec_mod_instance, struct proc_st *proc);
|
||||
|
||||
int open_tun(main_server_st* s, struct proc_st* proc);
|
||||
void close_tun(main_server_st* s, struct proc_st* proc);
|
||||
void reset_tun(struct proc_st* proc);
|
||||
int set_tun_mtu(main_server_st* s, struct proc_st * proc, unsigned mtu);
|
||||
int open_tun(main_server_st *s, struct proc_st *proc);
|
||||
void close_tun(main_server_st *s, struct proc_st *proc);
|
||||
void reset_tun(struct proc_st *proc);
|
||||
int set_tun_mtu(main_server_st *s, struct proc_st *proc, unsigned int mtu);
|
||||
|
||||
int send_cookie_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
AUTHREP r);
|
||||
int send_cookie_auth_reply(main_server_st *s, struct proc_st *proc, AUTHREP r);
|
||||
|
||||
int handle_auth_cookie_req(sec_mod_instance_st * sec_mod_instance, struct proc_st* proc,
|
||||
const AuthCookieRequestMsg * req);
|
||||
int handle_auth_cookie_req(sec_mod_instance_st *sec_mod_instance,
|
||||
struct proc_st *proc,
|
||||
const AuthCookieRequestMsg *req);
|
||||
|
||||
int check_multiple_users(main_server_st *s, struct proc_st* proc);
|
||||
int handle_script_exit(main_server_st *s, struct proc_st* proc, int code);
|
||||
int check_multiple_users(main_server_st *s, struct proc_st *proc);
|
||||
int handle_script_exit(main_server_st *s, struct proc_st *proc, int code);
|
||||
|
||||
void run_sec_mod(sec_mod_instance_st * sec_mod_instance, unsigned int instance_index);
|
||||
void run_sec_mod(sec_mod_instance_st *sec_mod_instance,
|
||||
unsigned int instance_index);
|
||||
|
||||
struct proc_st *new_proc(main_server_st * s, pid_t pid, int cmd_fd,
|
||||
struct sockaddr_storage *remote_addr, socklen_t remote_addr_len,
|
||||
struct sockaddr_storage *our_addr, socklen_t our_addr_len,
|
||||
uint8_t *sid, size_t sid_size);
|
||||
struct proc_st *new_proc(main_server_st *s, pid_t pid, int cmd_fd,
|
||||
struct sockaddr_storage *remote_addr,
|
||||
socklen_t remote_addr_len,
|
||||
struct sockaddr_storage *our_addr,
|
||||
socklen_t our_addr_len, uint8_t *sid, size_t sid_size);
|
||||
|
||||
/* kill the pid */
|
||||
#define RPROC_KILL 1
|
||||
/* we are on shutdown, don't wait for anything */
|
||||
#define RPROC_QUIT (1<<1)
|
||||
#define RPROC_QUIT (1 << 1)
|
||||
|
||||
void remove_proc(main_server_st* s, struct proc_st *proc, unsigned flags);
|
||||
void proc_to_zombie(main_server_st* s, struct proc_st *proc);
|
||||
void remove_proc(main_server_st *s, struct proc_st *proc, unsigned int flags);
|
||||
void proc_to_zombie(main_server_st *s, struct proc_st *proc);
|
||||
|
||||
inline static void disconnect_proc(main_server_st *s, proc_st *proc)
|
||||
{
|
||||
@@ -365,34 +371,39 @@ inline static void disconnect_proc(main_server_st *s, proc_st *proc)
|
||||
/* if it has a PID, send a signal so that we cleanup
|
||||
* and sec-mod gets stats orderly */
|
||||
if (proc->pid != -1 && proc->pid != 0) {
|
||||
kill(proc->pid, SIGTERM);
|
||||
kill(proc->pid, SIGTERM);
|
||||
} else {
|
||||
remove_proc(s, proc, RPROC_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
void put_into_cgroup(main_server_st * s, const char* cgroup, pid_t pid);
|
||||
void put_into_cgroup(main_server_st *s, const char *cgroup, pid_t pid);
|
||||
|
||||
inline static
|
||||
int send_msg_to_worker(main_server_st* s, struct proc_st* proc, uint8_t cmd,
|
||||
const void* msg, pack_size_func get_size, pack_func pack)
|
||||
inline static int send_msg_to_worker(main_server_st *s, struct proc_st *proc,
|
||||
uint8_t cmd, const void *msg,
|
||||
pack_size_func get_size, pack_func pack)
|
||||
{
|
||||
mslog(s, proc, LOG_DEBUG, "sending message '%s' to worker", cmd_request_to_str(cmd));
|
||||
mslog(s, proc, LOG_DEBUG, "sending message '%s' to worker",
|
||||
cmd_request_to_str(cmd));
|
||||
return send_msg(proc, proc->fd, cmd, msg, get_size, pack);
|
||||
}
|
||||
|
||||
inline static
|
||||
int send_socket_msg_to_worker(main_server_st* s, struct proc_st* proc, uint8_t cmd,
|
||||
int socketfd, const void* msg, pack_size_func get_size, pack_func pack)
|
||||
inline static int send_socket_msg_to_worker(main_server_st *s,
|
||||
struct proc_st *proc, uint8_t cmd,
|
||||
int socketfd, const void *msg,
|
||||
pack_size_func get_size,
|
||||
pack_func pack)
|
||||
{
|
||||
mslog(s, proc, LOG_DEBUG, "sending (socket) message %u to worker", (unsigned)cmd);
|
||||
return send_socket_msg(proc, proc->fd, cmd, socketfd, msg, get_size, pack);
|
||||
mslog(s, proc, LOG_DEBUG, "sending (socket) message %u to worker",
|
||||
(unsigned int)cmd);
|
||||
return send_socket_msg(proc, proc->fd, cmd, socketfd, msg, get_size,
|
||||
pack);
|
||||
}
|
||||
|
||||
int secmod_reload(sec_mod_instance_st * sec_mod_instance);
|
||||
int secmod_reload(sec_mod_instance_st *sec_mod_instance);
|
||||
|
||||
const char *secmod_socket_file_name(struct perm_cfg_st *perm_config);
|
||||
void restore_secmod_socket_file_name(const char * save_path);
|
||||
void restore_secmod_socket_file_name(const char *save_path);
|
||||
void clear_vhosts(struct list_head *head);
|
||||
|
||||
void request_reload(int signo);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined(LINUX_NAMESPACES)
|
||||
@@ -45,7 +44,8 @@ static int init_default_namespace(void)
|
||||
int fd;
|
||||
|
||||
pid = getpid();
|
||||
if (snprintf(netns_path, sizeof(netns_path), "/proc/%d/ns/net", pid) < 0)
|
||||
if (snprintf(netns_path, sizeof(netns_path), "/proc/%d/ns/net", pid) <
|
||||
0)
|
||||
return -1;
|
||||
|
||||
fd = open(netns_path, O_RDONLY | O_CLOEXEC);
|
||||
@@ -64,7 +64,8 @@ static int init_listen_namespace(const char *ns_name)
|
||||
int error;
|
||||
int fd;
|
||||
|
||||
if (snprintf(netns_path, sizeof(netns_path), "/var/run/netns/%s", ns_name) < 0)
|
||||
if (snprintf(netns_path, sizeof(netns_path), "/var/run/netns/%s",
|
||||
ns_name) < 0)
|
||||
return -1;
|
||||
|
||||
fd = open(netns_path, O_RDONLY | O_CLOEXEC);
|
||||
@@ -101,16 +102,19 @@ int close_namespaces(struct netns_fds *netns)
|
||||
}
|
||||
|
||||
/* opens a socket in the namespace described by <nsfd> */
|
||||
int socket_netns(const struct netns_fds *fds, int domain, int type, int protocol)
|
||||
int socket_netns(const struct netns_fds *fds, int domain, int type,
|
||||
int protocol)
|
||||
{
|
||||
int sock;
|
||||
|
||||
if (fds->default_fd >= 0 && fds->listen_fd && setns(fds->listen_fd, CLONE_NEWNET) == -1)
|
||||
if (fds->default_fd >= 0 && fds->listen_fd &&
|
||||
setns(fds->listen_fd, CLONE_NEWNET) == -1)
|
||||
return -1;
|
||||
|
||||
sock = socket(domain, type, protocol);
|
||||
|
||||
if (fds->default_fd >= 0 && fds->listen_fd && setns(fds->default_fd, CLONE_NEWNET) == -1) {
|
||||
if (fds->default_fd >= 0 && fds->listen_fd &&
|
||||
setns(fds->default_fd, CLONE_NEWNET) == -1) {
|
||||
if (sock >= 0)
|
||||
close(sock);
|
||||
return -1;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
#ifndef OC_NAMESPACE_H
|
||||
# define OC_NAMESPACE_H
|
||||
#define OC_NAMESPACE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -27,7 +27,7 @@ struct netns_fds {
|
||||
|
||||
#if defined(LINUX_NAMESPACES)
|
||||
|
||||
int socket_netns(const struct netns_fds*, int domain, int type, int protocol);
|
||||
int socket_netns(const struct netns_fds *, int domain, int type, int protocol);
|
||||
int open_namespaces(struct netns_fds *netns, struct perm_cfg_st *config);
|
||||
int close_namespaces(struct netns_fds *netns);
|
||||
|
||||
@@ -36,10 +36,11 @@ int close_namespaces(struct netns_fds *netns);
|
||||
#define open_namespaces(netns, config) (-1)
|
||||
#define close_namespaces(netns) (-1)
|
||||
|
||||
static inline int socket_netns(__attribute__((unused)) const struct netns_fds* fds,
|
||||
static inline int socket_netns(__attribute__((unused))
|
||||
const struct netns_fds *fds,
|
||||
int domain, int type, int protocol)
|
||||
{
|
||||
return socket(domain, type, protocol);
|
||||
return socket(domain, type, protocol);
|
||||
}
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
@@ -26,52 +26,57 @@
|
||||
#include <occtl/occtl.h>
|
||||
|
||||
typedef struct uid_entries_st {
|
||||
char* user;
|
||||
unsigned user_size;
|
||||
char *user;
|
||||
unsigned int user_size;
|
||||
char id[8];
|
||||
unsigned id_size;
|
||||
unsigned int id_size;
|
||||
} uid_entries_st;
|
||||
|
||||
static uid_entries_st *entries = NULL;
|
||||
static unsigned entries_size = 0;
|
||||
static unsigned max_entries_size = 0;
|
||||
static uid_entries_st *entries;
|
||||
static unsigned int entries_size;
|
||||
static unsigned int max_entries_size;
|
||||
|
||||
void entries_clear(void)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
for (i=0;i<entries_size;i++) {
|
||||
for (i = 0; i < entries_size; i++) {
|
||||
talloc_free(entries[i].user);
|
||||
entries[i].user = 0;
|
||||
}
|
||||
entries_size = 0;
|
||||
}
|
||||
|
||||
void entries_add(void *pool, const char* user, unsigned user_size, unsigned id)
|
||||
void entries_add(void *pool, const char *user, unsigned int user_size,
|
||||
unsigned int id)
|
||||
{
|
||||
if (entries_size+1 > max_entries_size) {
|
||||
if (entries_size + 1 > max_entries_size) {
|
||||
max_entries_size += 128;
|
||||
entries = talloc_realloc_size(pool, entries, sizeof(uid_entries_st)*max_entries_size);
|
||||
entries = talloc_realloc_size(pool, entries,
|
||||
sizeof(uid_entries_st) *
|
||||
max_entries_size);
|
||||
}
|
||||
|
||||
entries[entries_size].user = talloc_strdup(pool, user);
|
||||
entries[entries_size].user_size = user_size;
|
||||
entries[entries_size].id_size =
|
||||
snprintf(entries[entries_size].id, sizeof(entries[entries_size].id), "%u", id);
|
||||
snprintf(entries[entries_size].id,
|
||||
sizeof(entries[entries_size].id), "%u", id);
|
||||
|
||||
entries_size++;
|
||||
}
|
||||
|
||||
char* search_for_user(unsigned idx, const char* match, int match_size)
|
||||
char *search_for_user(unsigned int idx, const char *match, int match_size)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
if (idx >= entries_size)
|
||||
return NULL;
|
||||
|
||||
for (i=idx;i<entries_size;i++) {
|
||||
for (i = idx; i < entries_size; i++) {
|
||||
if (match_size <= entries[i].user_size) {
|
||||
if (strncasecmp(match, entries[i].user, match_size) == 0)
|
||||
if (strncasecmp(match, entries[i].user, match_size) ==
|
||||
0)
|
||||
return strdup(entries[i].user);
|
||||
}
|
||||
}
|
||||
@@ -79,16 +84,17 @@ unsigned i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* search_for_id(unsigned idx, const char* match, int match_size)
|
||||
char *search_for_id(unsigned int idx, const char *match, int match_size)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
if (idx >= entries_size)
|
||||
return NULL;
|
||||
|
||||
for (i=idx;i<entries_size;i++) {
|
||||
for (i = idx; i < entries_size; i++) {
|
||||
if (match_size <= entries[i].id_size) {
|
||||
if (strncasecmp(match, entries[i].id, match_size) == 0) {
|
||||
if (strncasecmp(match, entries[i].id, match_size) ==
|
||||
0) {
|
||||
return strdup(entries[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef CTL_H
|
||||
# define CTL_H
|
||||
#define CTL_H
|
||||
|
||||
#define OCCTL_UNIX_SOCKET "/var/run/occtl.socket"
|
||||
|
||||
|
||||
@@ -30,23 +30,23 @@
|
||||
|
||||
#ifdef HAVE_GEOIP
|
||||
|
||||
# include <GeoIP.h>
|
||||
# include <GeoIPCity.h>
|
||||
#include <GeoIP.h>
|
||||
#include <GeoIPCity.h>
|
||||
|
||||
extern void _GeoIP_setup_dbfilename(void);
|
||||
# define p_GeoIP_setup_dbfilename _GeoIP_setup_dbfilename
|
||||
# define pGeoIP_open_type GeoIP_open_type
|
||||
# define pGeoIP_country_name_by_id GeoIP_country_name_by_id
|
||||
# define pGeoIP_delete GeoIP_delete
|
||||
# define pGeoIP_record_by_ipnum GeoIP_record_by_ipnum
|
||||
# define pGeoIP_id_by_ipnum GeoIP_id_by_ipnum
|
||||
# define pGeoIP_id_by_ipnum_v6 GeoIP_id_by_ipnum_v6
|
||||
# define pGeoIP_record_by_ipnum_v6 GeoIP_record_by_ipnum_v6
|
||||
# define pGeoIP_code_by_id GeoIP_code_by_id
|
||||
#define p_GeoIP_setup_dbfilename _GeoIP_setup_dbfilename
|
||||
#define pGeoIP_open_type GeoIP_open_type
|
||||
#define pGeoIP_country_name_by_id GeoIP_country_name_by_id
|
||||
#define pGeoIP_delete GeoIP_delete
|
||||
#define pGeoIP_record_by_ipnum GeoIP_record_by_ipnum
|
||||
#define pGeoIP_id_by_ipnum GeoIP_id_by_ipnum
|
||||
#define pGeoIP_id_by_ipnum_v6 GeoIP_id_by_ipnum_v6
|
||||
#define pGeoIP_record_by_ipnum_v6 GeoIP_record_by_ipnum_v6
|
||||
#define pGeoIP_code_by_id GeoIP_code_by_id
|
||||
|
||||
int geo_setup(void)
|
||||
{
|
||||
static unsigned init = 0;
|
||||
static unsigned int init;
|
||||
|
||||
if (init == 0) {
|
||||
p_GeoIP_setup_dbfilename();
|
||||
@@ -56,7 +56,8 @@ int geo_setup(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void geo_ipv4_lookup(struct in_addr ip, char **country, char **city, char **coord)
|
||||
void geo_ipv4_lookup(struct in_addr ip, char **country, char **city,
|
||||
char **coord)
|
||||
{
|
||||
GeoIP *gi;
|
||||
GeoIPRecord *gir;
|
||||
@@ -68,7 +69,8 @@ void geo_ipv4_lookup(struct in_addr ip, char **country, char **city, char **coor
|
||||
|
||||
ip.s_addr = ntohl(ip.s_addr);
|
||||
|
||||
gi = pGeoIP_open_type(GEOIP_COUNTRY_EDITION, GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
gi = pGeoIP_open_type(GEOIP_COUNTRY_EDITION,
|
||||
GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
if (gi != NULL) {
|
||||
gi->charset = GEOIP_CHARSET_UTF8;
|
||||
|
||||
@@ -83,7 +85,8 @@ void geo_ipv4_lookup(struct in_addr ip, char **country, char **city, char **coor
|
||||
pGeoIP_delete(gi);
|
||||
}
|
||||
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV1, GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV1,
|
||||
GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
if (gi != NULL) {
|
||||
gi->charset = GEOIP_CHARSET_UTF8;
|
||||
|
||||
@@ -93,12 +96,14 @@ void geo_ipv4_lookup(struct in_addr ip, char **country, char **city, char **coor
|
||||
*city = strdup(gir->city);
|
||||
|
||||
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude, gir->longitude) < 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude,
|
||||
gir->longitude) < 0)
|
||||
*coord = NULL;
|
||||
|
||||
pGeoIP_delete(gi);
|
||||
} else {
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV0, GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV0,
|
||||
GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
if (gi != NULL) {
|
||||
gi->charset = GEOIP_CHARSET_UTF8;
|
||||
|
||||
@@ -108,7 +113,8 @@ void geo_ipv4_lookup(struct in_addr ip, char **country, char **city, char **coor
|
||||
*city = strdup(gir->city);
|
||||
|
||||
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude, gir->longitude) < 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude,
|
||||
gir->longitude) < 0)
|
||||
*coord = NULL;
|
||||
|
||||
pGeoIP_delete(gi);
|
||||
@@ -116,7 +122,8 @@ void geo_ipv4_lookup(struct in_addr ip, char **country, char **city, char **coor
|
||||
}
|
||||
}
|
||||
|
||||
void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city, char **coord)
|
||||
void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city,
|
||||
char **coord)
|
||||
{
|
||||
GeoIP *gi;
|
||||
GeoIPRecord *gir;
|
||||
@@ -126,7 +133,8 @@ void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city, char **co
|
||||
if (geo_setup() != 0)
|
||||
return;
|
||||
|
||||
gi = pGeoIP_open_type(GEOIP_COUNTRY_EDITION_V6, GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
gi = pGeoIP_open_type(GEOIP_COUNTRY_EDITION_V6,
|
||||
GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
if (gi != NULL) {
|
||||
gi->charset = GEOIP_CHARSET_UTF8;
|
||||
|
||||
@@ -141,7 +149,8 @@ void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city, char **co
|
||||
pGeoIP_delete(gi);
|
||||
}
|
||||
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV1_V6, GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV1_V6,
|
||||
GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
if (gi != NULL) {
|
||||
gi->charset = GEOIP_CHARSET_UTF8;
|
||||
|
||||
@@ -151,12 +160,14 @@ void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city, char **co
|
||||
*city = strdup(gir->city);
|
||||
|
||||
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude, gir->longitude) < 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude,
|
||||
gir->longitude) < 0)
|
||||
*coord = NULL;
|
||||
|
||||
pGeoIP_delete(gi);
|
||||
} else {
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV0_V6, GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV0_V6,
|
||||
GEOIP_STANDARD | GEOIP_SILENCE);
|
||||
if (gi != NULL) {
|
||||
gi->charset = GEOIP_CHARSET_UTF8;
|
||||
|
||||
@@ -166,7 +177,8 @@ void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city, char **co
|
||||
*city = strdup(gir->city);
|
||||
|
||||
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude, gir->longitude) < 0)
|
||||
if (asprintf(coord, "%f,%f", gir->latitude,
|
||||
gir->longitude) < 0)
|
||||
*coord = NULL;
|
||||
|
||||
pGeoIP_delete(gi);
|
||||
@@ -174,7 +186,7 @@ void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city, char **co
|
||||
}
|
||||
}
|
||||
|
||||
char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
char *geo_lookup(const char *ip, char *buf, unsigned int buf_size)
|
||||
{
|
||||
char *country = NULL;
|
||||
char *city = NULL;
|
||||
@@ -209,7 +221,7 @@ char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
|
||||
return buf;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
free(country);
|
||||
free(city);
|
||||
free(coord);
|
||||
@@ -218,7 +230,7 @@ char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
}
|
||||
|
||||
#else
|
||||
char * geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
char *geo_lookup(const char *ip, char *buf, unsigned int buf_size)
|
||||
{
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
|
||||
#ifndef GEOIP_H
|
||||
# define GEOIP_H
|
||||
#define GEOIP_H
|
||||
|
||||
char * geo_lookup(const char *ip, char *buf, unsigned buf_size);
|
||||
char *geo_lookup(const char *ip, char *buf, unsigned int buf_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,45 +28,49 @@
|
||||
|
||||
typedef struct ip_entries_st {
|
||||
char ip[MAX_IP_STR];
|
||||
unsigned ip_size;
|
||||
unsigned int ip_size;
|
||||
} ip_entries_st;
|
||||
|
||||
static ip_entries_st *ip_entries = NULL;
|
||||
static unsigned ip_entries_size = 0;
|
||||
static unsigned max_ip_entries_size = 0;
|
||||
static ip_entries_st *ip_entries;
|
||||
static unsigned int ip_entries_size;
|
||||
static unsigned int max_ip_entries_size;
|
||||
|
||||
void ip_entries_clear(void)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
for (i=0;i<ip_entries_size;i++) {
|
||||
for (i = 0; i < ip_entries_size; i++) {
|
||||
ip_entries[i].ip_size = 0;
|
||||
}
|
||||
ip_entries_size = 0;
|
||||
}
|
||||
|
||||
void ip_entries_add(void *pool, const char* ip, unsigned ip_size)
|
||||
void ip_entries_add(void *pool, const char *ip, unsigned int ip_size)
|
||||
{
|
||||
if (ip_entries_size+1 > max_ip_entries_size) {
|
||||
if (ip_entries_size + 1 > max_ip_entries_size) {
|
||||
max_ip_entries_size += 128;
|
||||
ip_entries = talloc_realloc_size(pool, ip_entries, sizeof(ip_entries_st)*max_ip_entries_size);
|
||||
ip_entries = talloc_realloc_size(pool, ip_entries,
|
||||
sizeof(ip_entries_st) *
|
||||
max_ip_entries_size);
|
||||
}
|
||||
|
||||
strlcpy(ip_entries[ip_entries_size].ip, ip, sizeof(ip_entries[ip_entries_size].ip));
|
||||
strlcpy(ip_entries[ip_entries_size].ip, ip,
|
||||
sizeof(ip_entries[ip_entries_size].ip));
|
||||
ip_entries[ip_entries_size].ip_size = ip_size;
|
||||
ip_entries_size++;
|
||||
}
|
||||
|
||||
char* search_for_ip(unsigned idx, const char* match, int match_size)
|
||||
char *search_for_ip(unsigned int idx, const char *match, int match_size)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
if (idx >= ip_entries_size)
|
||||
return NULL;
|
||||
|
||||
for (i=idx;i<ip_entries_size;i++) {
|
||||
for (i = idx; i < ip_entries_size; i++) {
|
||||
if (match_size <= ip_entries[i].ip_size) {
|
||||
if (strncasecmp(match, ip_entries[i].ip, match_size) == 0)
|
||||
if (strncasecmp(match, ip_entries[i].ip, match_size) ==
|
||||
0)
|
||||
return strdup(ip_entries[i].ip);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,21 +26,22 @@
|
||||
/* Escapes @val and stores it in tmp. A fixed string is returned
|
||||
* in case tmp is too small.
|
||||
*/
|
||||
char *json_escape_val(char *tmp, unsigned tmp_size, const char *val)
|
||||
char *json_escape_val(char *tmp, unsigned int tmp_size, const char *val)
|
||||
{
|
||||
unsigned val_len = strlen(val);
|
||||
unsigned i, j;
|
||||
unsigned int val_len = strlen(val);
|
||||
unsigned int i, j;
|
||||
|
||||
for (i=j=0;i<val_len;i++) {
|
||||
for (i = j = 0; i < val_len; i++) {
|
||||
if (j + 7 >= tmp_size)
|
||||
return "(invalid)";
|
||||
if (val[i] == '"' || val[i] == '\\') {
|
||||
snprintf(&tmp[j], 3, "\\%c", val[i]);
|
||||
j+=2;
|
||||
snprintf(&tmp[j], 3, "\\%c", val[i]);
|
||||
j += 2;
|
||||
} else if (val[i] <= 0x1F) {
|
||||
snprintf(&tmp[j], 7, "\\u00%02x", (unsigned)val[i]);
|
||||
j+=6;
|
||||
} else tmp[j++] = val[i];
|
||||
snprintf(&tmp[j], 7, "\\u00%02x", (unsigned int)val[i]);
|
||||
j += 6;
|
||||
} else
|
||||
tmp[j++] = val[i];
|
||||
}
|
||||
tmp[j] = 0;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
#ifndef JSON_H
|
||||
# define JSON_H
|
||||
char *json_escape_val(char *tmp, unsigned tmp_size, const char *val);
|
||||
#define JSON_H
|
||||
char *json_escape_val(char *tmp, unsigned int tmp_size, const char *val);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,21 +38,21 @@
|
||||
#define MAXMINDDB_LOCATION_CITY "/usr/share/GeoIP/GeoLite2-City.mmdb"
|
||||
#endif
|
||||
|
||||
#define pMMDB_close MMDB_close
|
||||
#define pMMDB_get_value MMDB_get_value
|
||||
#define pMMDB_close MMDB_close
|
||||
#define pMMDB_get_value MMDB_get_value
|
||||
#define pMMDB_lookup_string MMDB_lookup_string
|
||||
#define pMMDB_open MMDB_open
|
||||
#define pMMDB_open MMDB_open
|
||||
|
||||
void process_result_from_mmdb_lookup(MMDB_entry_data_s * entry_data, int status,
|
||||
void process_result_from_mmdb_lookup(MMDB_entry_data_s *entry_data, int status,
|
||||
char **output)
|
||||
{
|
||||
if (MMDB_SUCCESS == status) {
|
||||
if (status == MMDB_SUCCESS) {
|
||||
if (entry_data->has_data) {
|
||||
if (entry_data->type == MMDB_DATA_TYPE_UTF8_STRING) {
|
||||
*output =
|
||||
(char *)calloc(entry_data->data_size + 1,
|
||||
sizeof(char));
|
||||
if (NULL != *output) {
|
||||
*output = (char *)calloc(entry_data->data_size +
|
||||
1,
|
||||
sizeof(char));
|
||||
if (*output != NULL) {
|
||||
memcpy(*output, entry_data->utf8_string,
|
||||
entry_data->data_size);
|
||||
} else {
|
||||
@@ -66,7 +66,7 @@ void process_result_from_mmdb_lookup(MMDB_entry_data_s * entry_data, int status,
|
||||
/* Else fail silently */
|
||||
}
|
||||
|
||||
char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
char *geo_lookup(const char *ip, char *buf, unsigned int buf_size)
|
||||
{
|
||||
MMDB_s mmdb;
|
||||
MMDB_entry_data_s entry_data;
|
||||
@@ -74,33 +74,30 @@ char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
double latitude, longitude;
|
||||
char *country = NULL, *ccode = NULL;
|
||||
char *coord = NULL;
|
||||
unsigned found = 0;
|
||||
unsigned int found = 0;
|
||||
|
||||
/* Open the system maxmind database with countries */
|
||||
status = pMMDB_open(MAXMINDDB_LOCATION_COUNTRY, MMDB_MODE_MMAP, &mmdb);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
if (status == MMDB_SUCCESS) {
|
||||
/* Lookup IP address in the database */
|
||||
MMDB_lookup_result_s result =
|
||||
pMMDB_lookup_string(&mmdb, ip, &gai_error, &mmdb_error);
|
||||
if (MMDB_SUCCESS == mmdb_error) {
|
||||
pMMDB_lookup_string(&mmdb, ip, &gai_error, &mmdb_error);
|
||||
if (mmdb_error == MMDB_SUCCESS) {
|
||||
/* If the lookup was successful and an entry was found */
|
||||
if (result.found_entry) {
|
||||
memset(&entry_data, 0,
|
||||
sizeof(MMDB_entry_data_s));
|
||||
/* Travel the path in the tree like structure of the MMDB and store the value if found */
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"country", "names", "en",
|
||||
NULL);
|
||||
process_result_from_mmdb_lookup(&entry_data,
|
||||
status,
|
||||
&country);
|
||||
status = pMMDB_get_value(&result.entry,
|
||||
&entry_data, "country",
|
||||
"names", "en", NULL);
|
||||
process_result_from_mmdb_lookup(
|
||||
&entry_data, status, &country);
|
||||
memset(&entry_data, 0,
|
||||
sizeof(MMDB_entry_data_s));
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"country", "iso_code",
|
||||
NULL);
|
||||
status = pMMDB_get_value(&result.entry,
|
||||
&entry_data, "country",
|
||||
"iso_code", NULL);
|
||||
process_result_from_mmdb_lookup(&entry_data,
|
||||
status, &ccode);
|
||||
}
|
||||
@@ -112,11 +109,11 @@ char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
|
||||
/* Open the system maxmind database with cities - which actually does not contain names of the cities */
|
||||
status = pMMDB_open(MAXMINDDB_LOCATION_CITY, MMDB_MODE_MMAP, &mmdb);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
if (status == MMDB_SUCCESS) {
|
||||
/* Lookup IP address in the database */
|
||||
MMDB_lookup_result_s result =
|
||||
pMMDB_lookup_string(&mmdb, ip, &gai_error, &mmdb_error);
|
||||
if (MMDB_SUCCESS == mmdb_error) {
|
||||
pMMDB_lookup_string(&mmdb, ip, &gai_error, &mmdb_error);
|
||||
if (mmdb_error == MMDB_SUCCESS) {
|
||||
/* If the lookup was successful and an entry was found */
|
||||
if (result.found_entry) {
|
||||
memset(&entry_data, 0,
|
||||
@@ -124,32 +121,32 @@ char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
// NOTE: Information about the city is not available in the free database, so there is not way
|
||||
// for me to implement this functionality right now, but it should be easy to add for anyone with
|
||||
// access to the paid databases.
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"location", "latitude",
|
||||
NULL);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
status = pMMDB_get_value(&result.entry,
|
||||
&entry_data,
|
||||
"location", "latitude",
|
||||
NULL);
|
||||
if (status == MMDB_SUCCESS) {
|
||||
if (entry_data.has_data) {
|
||||
if (entry_data.type ==
|
||||
MMDB_DATA_TYPE_DOUBLE) {
|
||||
latitude =
|
||||
entry_data.
|
||||
double_value;
|
||||
entry_data
|
||||
.double_value;
|
||||
++coordinates;
|
||||
}
|
||||
}
|
||||
}
|
||||
status =
|
||||
pMMDB_get_value(&result.entry, &entry_data,
|
||||
"location", "longitude",
|
||||
NULL);
|
||||
if (MMDB_SUCCESS == status) {
|
||||
status = pMMDB_get_value(&result.entry,
|
||||
&entry_data,
|
||||
"location",
|
||||
"longitude", NULL);
|
||||
if (status == MMDB_SUCCESS) {
|
||||
if (entry_data.has_data) {
|
||||
if (entry_data.type ==
|
||||
MMDB_DATA_TYPE_DOUBLE) {
|
||||
longitude =
|
||||
entry_data.
|
||||
double_value;
|
||||
entry_data
|
||||
.double_value;
|
||||
++coordinates;
|
||||
}
|
||||
}
|
||||
@@ -161,7 +158,6 @@ char *geo_lookup(const char *ip, char *buf, unsigned buf_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
pMMDB_close(&mmdb);
|
||||
}
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
#include <netlink/route/link.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static struct nl_sock *sock = NULL;
|
||||
static int nl_failed = 0;
|
||||
static struct nl_sock *sock;
|
||||
static int nl_failed;
|
||||
|
||||
static int open_netlink(void)
|
||||
{
|
||||
int err;
|
||||
int err;
|
||||
|
||||
if (sock != NULL)
|
||||
return 0;
|
||||
@@ -52,7 +52,8 @@ int err;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0) {
|
||||
err = nl_connect(sock, NETLINK_ROUTE);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "nl: error in nl_connect (%d)", err);
|
||||
goto error;
|
||||
}
|
||||
@@ -68,8 +69,8 @@ error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
value2speed(unsigned long bytes, time_t time, char* output, unsigned output_size)
|
||||
static void value2speed(unsigned long bytes, time_t time, char *output,
|
||||
unsigned int output_size)
|
||||
{
|
||||
unsigned long speed;
|
||||
|
||||
@@ -80,7 +81,8 @@ value2speed(unsigned long bytes, time_t time, char* output, unsigned output_size
|
||||
bytes2human(speed, output, output_size, "/s");
|
||||
}
|
||||
|
||||
void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_st *params, unsigned have_more)
|
||||
void print_iface_stats(const char *iface, time_t since, FILE *out,
|
||||
cmd_params_st *params, unsigned int have_more)
|
||||
{
|
||||
uint64_t tx, rx;
|
||||
char buf1[32], buf2[32];
|
||||
@@ -106,21 +108,30 @@ void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_s
|
||||
bytes2human(rx, buf1, sizeof(buf1), NULL);
|
||||
bytes2human(tx, buf2, sizeof(buf2), NULL);
|
||||
if (HAVE_JSON(params)) {
|
||||
fprintf(out, " \"RX\": \"%"PRIu64"\",\n \"TX\": \"%"PRIu64"\",\n", rx, tx);
|
||||
fprintf(out, " \"_RX\": \"%s\",\n \"_TX\": \"%s\",\n", buf1, buf2);
|
||||
fprintf(out,
|
||||
" \"RX\": \"%" PRIu64 "\",\n \"TX\": \"%" PRIu64
|
||||
"\",\n",
|
||||
rx, tx);
|
||||
fprintf(out, " \"_RX\": \"%s\",\n \"_TX\": \"%s\",\n",
|
||||
buf1, buf2);
|
||||
} else
|
||||
fprintf(out, "\tRX: %"PRIu64" (%s) TX: %"PRIu64" (%s)\n", rx, buf1, tx, buf2);
|
||||
fprintf(out, "\tRX: %" PRIu64 " (%s) TX: %" PRIu64 " (%s)\n",
|
||||
rx, buf1, tx, buf2);
|
||||
|
||||
value2speed(rx, diff, buf1, sizeof(buf1));
|
||||
value2speed(tx, diff, buf2, sizeof(buf2));
|
||||
if (HAVE_JSON(params))
|
||||
fprintf(out, " \"Average RX\": \"%s\",\n \"Average TX\": \"%s\"%s\n", buf1, buf2, have_more?",":"");
|
||||
fprintf(out,
|
||||
" \"Average RX\": \"%s\",\n \"Average TX\": \"%s\"%s\n",
|
||||
buf1, buf2, have_more ? "," : "");
|
||||
else
|
||||
fprintf(out, "\tAverage bandwidth RX: %s TX: %s\n", buf1, buf2);
|
||||
fprintf(out, "\tAverage bandwidth RX: %s TX: %s\n", buf1,
|
||||
buf2);
|
||||
}
|
||||
|
||||
#else
|
||||
void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_st *params, unsigned have_more)
|
||||
void print_iface_stats(const char *iface, time_t since, FILE *out,
|
||||
cmd_params_st *params, unsigned int have_more)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -30,15 +30,18 @@
|
||||
#include <locale.h>
|
||||
#include <occtl/occtl.h>
|
||||
|
||||
int syslog_open = 0;
|
||||
int syslog_open;
|
||||
|
||||
static int handle_reset_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
static int handle_help_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
static int handle_exit_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
static int handle_reset_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
static int handle_help_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
static int handle_exit_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
unsigned name_size;
|
||||
unsigned int name_size;
|
||||
char *arg;
|
||||
cmd_func func;
|
||||
char *doc;
|
||||
@@ -47,15 +50,15 @@ typedef struct {
|
||||
} commands_st;
|
||||
|
||||
#define ENTRY(name, arg, func, doc, show, npc) \
|
||||
{name, sizeof(name)-1, arg, func, doc, show, npc}
|
||||
{ name, sizeof(name) - 1, arg, func, doc, show, npc }
|
||||
|
||||
static const commands_st commands[] = {
|
||||
ENTRY("disconnect user", "[NAME]", handle_disconnect_user_cmd,
|
||||
"Disconnect the specified user", 1, 1),
|
||||
ENTRY("disconnect id", "[ID]", handle_disconnect_id_cmd,
|
||||
"Disconnect the specified ID", 1, 1),
|
||||
ENTRY("unban ip", "[IP]", handle_unban_ip_cmd,
|
||||
"Unban the specified IP", 1, 1),
|
||||
ENTRY("unban ip", "[IP]", handle_unban_ip_cmd, "Unban the specified IP",
|
||||
1, 1),
|
||||
ENTRY("reload", NULL, handle_reload_cmd,
|
||||
"Reloads the server configuration", 1, 1),
|
||||
ENTRY("show status", NULL, handle_status_cmd,
|
||||
@@ -80,8 +83,7 @@ static const commands_st commands[] = {
|
||||
"Prints information on the specified ID", 1, 1),
|
||||
ENTRY("show events", NULL, handle_events_cmd,
|
||||
"Provides information about connecting users", 1, 1),
|
||||
ENTRY("stop", "now", handle_stop_cmd,
|
||||
"Terminates the server", 1, 1),
|
||||
ENTRY("stop", "now", handle_stop_cmd, "Terminates the server", 1, 1),
|
||||
ENTRY("reset", NULL, handle_reset_cmd, "Resets the screen and terminal",
|
||||
0, 0),
|
||||
ENTRY("help", "or ?", handle_help_cmd, "Prints this help", 0, 0),
|
||||
@@ -93,10 +95,10 @@ static const commands_st commands[] = {
|
||||
"Alias for show sessions all", -1, 1),
|
||||
ENTRY("show cookies valid", NULL, handle_list_valid_sessions_cmd,
|
||||
"Alias for show sessions valid", -1, 1),
|
||||
{NULL, 0, NULL, NULL}
|
||||
{ NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
static void print_commands(unsigned interactive)
|
||||
static void print_commands(unsigned int interactive)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -121,10 +123,10 @@ static void print_commands(unsigned interactive)
|
||||
}
|
||||
|
||||
#ifndef HAVE_ORIG_READLINE
|
||||
# define whitespace(x) c_isspace(x)
|
||||
#define whitespace(x) c_isspace(x)
|
||||
#endif
|
||||
|
||||
unsigned need_help(const char *arg)
|
||||
unsigned int need_help(const char *arg)
|
||||
{
|
||||
while (whitespace(*arg))
|
||||
arg++;
|
||||
@@ -135,11 +137,11 @@ unsigned need_help(const char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned check_cmd_help(const char *line)
|
||||
unsigned int check_cmd_help(const char *line)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned len = (line!=NULL)?strlen(line):0;
|
||||
unsigned status = 0, tlen;
|
||||
unsigned len = (line != NULL) ? strlen(line) : 0;
|
||||
unsigned int status = 0, tlen;
|
||||
|
||||
while (len > 0 && (line[len - 1] == '?' || whitespace(line[len - 1])))
|
||||
len--;
|
||||
@@ -167,8 +169,7 @@ unsigned check_cmd_help(const char *line)
|
||||
return status;
|
||||
}
|
||||
|
||||
static
|
||||
void usage(void)
|
||||
static void usage(void)
|
||||
{
|
||||
printf("occtl: [OPTIONS...] {COMMAND}\n\n");
|
||||
printf(" -s --socket-file Specify the server's occtl socket file\n");
|
||||
@@ -181,18 +182,16 @@ void usage(void)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static
|
||||
void version(void)
|
||||
static void version(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"OpenConnect server control (occtl) version %s\n", VERSION);
|
||||
fprintf(stderr, "OpenConnect server control (occtl) version %s\n",
|
||||
VERSION);
|
||||
fprintf(stderr, "Copyright (C) 2014-2017 Red Hat and others.\n");
|
||||
fprintf(stderr,
|
||||
"ocserv comes with ABSOLUTELY NO WARRANTY. This is free software,\n");
|
||||
fprintf(stderr,
|
||||
"and you are welcome to redistribute it under the conditions of the\n");
|
||||
fprintf(stderr,
|
||||
"GNU General Public License version 2.\n");
|
||||
fprintf(stderr, "GNU General Public License version 2.\n");
|
||||
fprintf(stderr, "\nFor help type ? or 'help'\n");
|
||||
fprintf(stderr,
|
||||
"==================================================================\n");
|
||||
@@ -217,47 +216,50 @@ static char *rl_gets(char *line_read)
|
||||
return line_read;
|
||||
}
|
||||
|
||||
void
|
||||
bytes2human(unsigned long bytes, char* output, unsigned output_size, const char* suffix)
|
||||
void bytes2human(unsigned long bytes, char *output, unsigned int output_size,
|
||||
const char *suffix)
|
||||
{
|
||||
double data;
|
||||
double data;
|
||||
|
||||
if (suffix == NULL)
|
||||
suffix = "";
|
||||
|
||||
if (bytes > 1000 && bytes < 1000 * 1000) {
|
||||
data = ((double) bytes) / 1000;
|
||||
data = ((double)bytes) / 1000;
|
||||
snprintf(output, output_size, "%.1f kB%s", data, suffix);
|
||||
} else if (bytes >= 1000 * 1000 && bytes < 1000 * 1000 * 1000) {
|
||||
data = ((double) bytes) / (1000 * 1000);
|
||||
data = ((double)bytes) / (1000 * 1000);
|
||||
snprintf(output, output_size, "%.1f MB%s", data, suffix);
|
||||
} else if (bytes >= 1000 * 1000 * 1000) {
|
||||
data = ((double) bytes) / (1000 * 1000 * 1000);
|
||||
data = ((double)bytes) / (1000 * 1000 * 1000);
|
||||
snprintf(output, output_size, "%.1f GB%s", data, suffix);
|
||||
} else {
|
||||
snprintf(output, output_size, "%lu bytes%s", bytes, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
time2human(uint64_t microseconds, char* output, unsigned output_size)
|
||||
void time2human(uint64_t microseconds, char *output, unsigned int output_size)
|
||||
{
|
||||
if (microseconds < 1000) {
|
||||
snprintf(output, output_size, "<1ms");
|
||||
} else if (microseconds < 1000000) {
|
||||
snprintf(output, output_size, "%" PRIu64 "ms", microseconds / 1000);
|
||||
snprintf(output, output_size, "%" PRIu64 "ms",
|
||||
microseconds / 1000);
|
||||
} else {
|
||||
snprintf(output, output_size, "%" PRIu64 "s", microseconds / 1000000);
|
||||
snprintf(output, output_size, "%" PRIu64 "s",
|
||||
microseconds / 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_help_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params)
|
||||
static int handle_help_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params)
|
||||
{
|
||||
print_commands(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_reset_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params)
|
||||
static int handle_reset_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params)
|
||||
{
|
||||
rl_reset_terminal(NULL);
|
||||
#ifdef HAVE_ORIG_READLINE
|
||||
@@ -267,7 +269,8 @@ static int handle_reset_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *pa
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_exit_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params)
|
||||
static int handle_exit_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params)
|
||||
{
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -275,14 +278,13 @@ static int handle_exit_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *par
|
||||
/* checks whether an input command of type " list users" matches
|
||||
* the given cmd (e.g., "list users"). If yes it executes func() and returns true.
|
||||
*/
|
||||
static
|
||||
unsigned check_cmd(const char *cmd, const char *input,
|
||||
CONN_TYPE * conn, int need_preconn, cmd_func func, int *status,
|
||||
cmd_params_st *params)
|
||||
static unsigned int check_cmd(const char *cmd, const char *input,
|
||||
CONN_TYPE *conn, int need_preconn, cmd_func func,
|
||||
int *status, cmd_params_st *params)
|
||||
{
|
||||
char *t, *p;
|
||||
unsigned len, tlen;
|
||||
unsigned i, ret = 0;
|
||||
unsigned int len, tlen;
|
||||
unsigned int i, ret = 0;
|
||||
char prev;
|
||||
|
||||
while (whitespace(*input))
|
||||
@@ -310,7 +312,8 @@ unsigned check_cmd(const char *cmd, const char *input,
|
||||
if (len == 0)
|
||||
goto cleanup;
|
||||
|
||||
if (tlen >= len && strncasecmp(cmd, t, len) == 0 && cmd[len] == 0) { /* match */
|
||||
if (tlen >= len && strncasecmp(cmd, t, len) == 0 &&
|
||||
cmd[len] == 0) { /* match */
|
||||
p = t + len;
|
||||
while (whitespace(*p))
|
||||
p++;
|
||||
@@ -331,7 +334,7 @@ unsigned check_cmd(const char *cmd, const char *input,
|
||||
conn_posthandle(conn);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
talloc_free(t);
|
||||
|
||||
return ret;
|
||||
@@ -341,7 +344,8 @@ char *stripwhite(char *string)
|
||||
{
|
||||
register char *s, *t;
|
||||
|
||||
for (s = string; whitespace(*s); s++) ;
|
||||
for (s = string; whitespace(*s); s++)
|
||||
;
|
||||
|
||||
if (*s == 0)
|
||||
return (s);
|
||||
@@ -354,8 +358,7 @@ char *stripwhite(char *string)
|
||||
return s;
|
||||
}
|
||||
|
||||
static
|
||||
int handle_cmd(CONN_TYPE * conn, char *line, cmd_params_st *params)
|
||||
static int handle_cmd(CONN_TYPE *conn, char *line, cmd_params_st *params)
|
||||
{
|
||||
char *cline;
|
||||
unsigned int i;
|
||||
@@ -370,17 +373,15 @@ int handle_cmd(CONN_TYPE * conn, char *line, cmd_params_st *params)
|
||||
if (commands[i].name == NULL)
|
||||
goto error;
|
||||
|
||||
if (check_cmd
|
||||
(commands[i].name, cline, conn,
|
||||
commands[i].need_preconn,
|
||||
commands[i].func,
|
||||
&status, params) != 0)
|
||||
if (check_cmd(commands[i].name, cline, conn,
|
||||
commands[i].need_preconn, commands[i].func,
|
||||
&status, params) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
error:
|
||||
error:
|
||||
if (check_cmd_help(line) == 0) {
|
||||
fprintf(stderr, "unknown command: %s\n", line);
|
||||
fprintf(stderr,
|
||||
@@ -394,9 +395,9 @@ int handle_cmd(CONN_TYPE * conn, char *line, cmd_params_st *params)
|
||||
*/
|
||||
static char *merge_args(int argc, char **argv)
|
||||
{
|
||||
unsigned size = 0;
|
||||
unsigned int size = 0;
|
||||
char *data, *p;
|
||||
unsigned i, len;
|
||||
unsigned int i, len;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
size += strlen(argv[i]) + 1;
|
||||
@@ -423,12 +424,12 @@ static char *merge_args(int argc, char **argv)
|
||||
return data;
|
||||
}
|
||||
|
||||
static unsigned int cmd_start = 0;
|
||||
static unsigned int cmd_start;
|
||||
static char *command_generator(const char *text, int state)
|
||||
{
|
||||
static int list_index, len;
|
||||
static int entries_idx;
|
||||
unsigned name_size;
|
||||
unsigned int name_size;
|
||||
char *name, *arg;
|
||||
char *ret;
|
||||
|
||||
@@ -450,35 +451,29 @@ static char *command_generator(const char *text, int state)
|
||||
if (cmd_start > name_size) {
|
||||
/* check for user or ID options */
|
||||
if (rl_line_buffer != NULL &&
|
||||
strncasecmp(rl_line_buffer, name, name_size) == 0
|
||||
&&
|
||||
strncasecmp(rl_line_buffer, name, name_size) == 0 &&
|
||||
/* make sure only one argument is appended */
|
||||
rl_line_buffer[name_size] != 0 &&
|
||||
strchr(&rl_line_buffer[name_size + 1],
|
||||
' ') == NULL) {
|
||||
|
||||
strchr(&rl_line_buffer[name_size + 1], ' ') ==
|
||||
NULL) {
|
||||
if (arg != NULL) {
|
||||
ret = NULL;
|
||||
if (strcmp(arg, "[NAME]") == 0)
|
||||
ret =
|
||||
search_for_user(entries_idx,
|
||||
text, len);
|
||||
ret = search_for_user(
|
||||
entries_idx, text, len);
|
||||
else if (strcmp(arg, "[ID]") == 0)
|
||||
ret =
|
||||
search_for_id(entries_idx,
|
||||
text, len);
|
||||
ret = search_for_id(entries_idx,
|
||||
text, len);
|
||||
else if (strcmp(arg, "[IP]") == 0)
|
||||
ret =
|
||||
search_for_ip(entries_idx,
|
||||
text, len);
|
||||
ret = search_for_ip(entries_idx,
|
||||
text, len);
|
||||
else if (strcmp(arg, "[SID]") == 0)
|
||||
ret =
|
||||
search_for_session(entries_idx,
|
||||
text, len);
|
||||
ret = search_for_session(
|
||||
entries_idx, text, len);
|
||||
if (ret != NULL) {
|
||||
entries_idx++;
|
||||
}
|
||||
list_index--; /* restart at the same cmd */
|
||||
list_index--; /* restart at the same cmd */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -489,8 +484,8 @@ static char *command_generator(const char *text, int state)
|
||||
if (cmd_start > 0 && name[cmd_start - 1] != ' ')
|
||||
continue;
|
||||
|
||||
if (rl_line_buffer != NULL
|
||||
&& strncasecmp(rl_line_buffer, name, cmd_start) != 0)
|
||||
if (rl_line_buffer != NULL &&
|
||||
strncasecmp(rl_line_buffer, name, cmd_start) != 0)
|
||||
continue;
|
||||
|
||||
name += cmd_start;
|
||||
@@ -530,7 +525,8 @@ void initialize_readline(void)
|
||||
ocsignal(SIGINT, handle_sigint);
|
||||
}
|
||||
|
||||
static int single_cmd(int argc, char **argv, void *pool, const char *file, cmd_params_st *params)
|
||||
static int single_cmd(int argc, char **argv, void *pool, const char *file,
|
||||
cmd_params_st *params)
|
||||
{
|
||||
CONN_TYPE *conn;
|
||||
char *line;
|
||||
@@ -545,7 +541,6 @@ static int single_cmd(int argc, char **argv, void *pool, const char *file, cmd_p
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *line = NULL;
|
||||
@@ -573,14 +568,14 @@ int main(int argc, char **argv)
|
||||
|
||||
if (argc > 1) {
|
||||
while (argc > 1 && argv[1][0] == '-') {
|
||||
if (argv[1][1] == 'j'
|
||||
|| (argv[1][1] == '-' && argv[1][2] == 'j')) {
|
||||
if (argv[1][1] == 'j' ||
|
||||
(argv[1][1] == '-' && argv[1][2] == 'j')) {
|
||||
params.json = 1;
|
||||
|
||||
argv += 1;
|
||||
argc -= 1;
|
||||
} else if (argv[1][1] == 'n'
|
||||
|| (argv[1][1] == '-' && argv[1][2] == 'n')) {
|
||||
} else if (argv[1][1] == 'n' ||
|
||||
(argv[1][1] == '-' && argv[1][2] == 'n')) {
|
||||
params.no_pager = 1;
|
||||
|
||||
argv += 1;
|
||||
@@ -595,12 +590,13 @@ int main(int argc, char **argv)
|
||||
params.json = 0;
|
||||
goto interactive;
|
||||
}
|
||||
} else if (argv[1][1] == 'v'
|
||||
|| (argv[1][1] == '-' && argv[1][2] == 'v')) {
|
||||
} else if (argv[1][1] == 'v' ||
|
||||
(argv[1][1] == '-' && argv[1][2] == 'v')) {
|
||||
version();
|
||||
exit(EXIT_SUCCESS);
|
||||
} else if (argc > 2 && (argv[1][1] == 's'
|
||||
|| (argv[1][1] == '-' && argv[1][2] == 's'))) {
|
||||
} else if (argc > 2 &&
|
||||
(argv[1][1] == 's' ||
|
||||
(argv[1][1] == '-' && argv[1][2] == 's'))) {
|
||||
file = talloc_strdup(gl_pool, argv[2]);
|
||||
|
||||
if (argc == 3) {
|
||||
@@ -622,7 +618,7 @@ int main(int argc, char **argv)
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
interactive:
|
||||
interactive:
|
||||
conn = conn_init(gl_pool, file);
|
||||
|
||||
initialize_readline();
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#ifndef OCCTL_H
|
||||
# define OCCTL_H
|
||||
#define OCCTL_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "common.h"
|
||||
|
||||
#ifdef HAVE_ORIG_READLINE
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#else
|
||||
# include <readline.h>
|
||||
#include <readline.h>
|
||||
#endif
|
||||
|
||||
#define DATE_TIME_FMT "%Y-%m-%d %H:%M"
|
||||
@@ -19,87 +19,110 @@
|
||||
#define HAVE_JSON(params) (params && params->json)
|
||||
|
||||
typedef struct cmd_params_st {
|
||||
unsigned json;
|
||||
unsigned no_pager;
|
||||
unsigned debug;
|
||||
unsigned int json;
|
||||
unsigned int no_pager;
|
||||
unsigned int debug;
|
||||
} cmd_params_st;
|
||||
|
||||
FILE* pager_start(cmd_params_st *params);
|
||||
void pager_stop(FILE* fp);
|
||||
FILE *pager_start(cmd_params_st *params);
|
||||
void pager_stop(FILE *fp);
|
||||
void print_time_ival7(char output[MAX_TMPSTR_SIZE], time_t t1, time_t t2);
|
||||
void print_iface_stats(const char *iface, time_t since, FILE * out, cmd_params_st *params, unsigned have_more);
|
||||
int print_list_entries(FILE* out, cmd_params_st *params, const char* name, char **val, unsigned vsize, unsigned have_more);
|
||||
int print_fwport_entries(FILE* out, cmd_params_st *params, const char* name, FwPortSt **val, unsigned vsize, unsigned have_more);
|
||||
void print_iface_stats(const char *iface, time_t since, FILE *out,
|
||||
cmd_params_st *params, unsigned int have_more);
|
||||
int print_list_entries(FILE *out, cmd_params_st *params, const char *name,
|
||||
char **val, unsigned int vsize, unsigned int have_more);
|
||||
int print_fwport_entries(FILE *out, cmd_params_st *params, const char *name,
|
||||
FwPortSt **val, unsigned int vsize,
|
||||
unsigned int have_more);
|
||||
void print_start_block(FILE *out, cmd_params_st *params);
|
||||
void print_end_block(FILE *out, cmd_params_st *params, unsigned have_more);
|
||||
void print_end_block(FILE *out, cmd_params_st *params, unsigned int have_more);
|
||||
void print_array_block(FILE *out, cmd_params_st *params);
|
||||
void print_end_array_block(FILE *out, cmd_params_st *params);
|
||||
void print_separator(FILE *out, cmd_params_st *params);
|
||||
void print_single_value(FILE *out, cmd_params_st *params, const char *name, const char *value, unsigned have_more);
|
||||
void print_single_value_int(FILE *out, cmd_params_st *params, const char *name, long i, unsigned have_more);
|
||||
void print_single_value_ex(FILE *out, cmd_params_st *params, const char *name, const char *value, const char *ex, unsigned have_more);
|
||||
void print_pair_value(FILE *out, cmd_params_st *params, const char *name1, const char *value1, const char *name2, const char *value2, unsigned have_more);
|
||||
void print_single_value(FILE *out, cmd_params_st *params, const char *name,
|
||||
const char *value, unsigned int have_more);
|
||||
void print_single_value_int(FILE *out, cmd_params_st *params, const char *name,
|
||||
long i, unsigned int have_more);
|
||||
void print_single_value_ex(FILE *out, cmd_params_st *params, const char *name,
|
||||
const char *value, const char *ex,
|
||||
unsigned int have_more);
|
||||
void print_pair_value(FILE *out, cmd_params_st *params, const char *name1,
|
||||
const char *value1, const char *name2, const char *value2,
|
||||
unsigned int have_more);
|
||||
|
||||
void bytes2human(unsigned long bytes, char *output, unsigned int output_size,
|
||||
const char *suffix);
|
||||
|
||||
void
|
||||
bytes2human(unsigned long bytes, char* output, unsigned output_size, const char* suffix);
|
||||
void time2human(uint64_t microseconds, char *output, unsigned int output_size);
|
||||
|
||||
void
|
||||
time2human(uint64_t microseconds, char* output, unsigned output_size);
|
||||
|
||||
char* search_for_id(unsigned idx, const char* match, int match_size);
|
||||
char* search_for_user(unsigned idx, const char* match, int match_size);
|
||||
void entries_add(void *pool, const char* user, unsigned user_size, unsigned id);
|
||||
char *search_for_id(unsigned int idx, const char *match, int match_size);
|
||||
char *search_for_user(unsigned int idx, const char *match, int match_size);
|
||||
void entries_add(void *pool, const char *user, unsigned int user_size,
|
||||
unsigned int id);
|
||||
void entries_clear(void);
|
||||
|
||||
void session_entries_add(void *pool, const char* session);
|
||||
void session_entries_add(void *pool, const char *session);
|
||||
void session_entries_clear(void);
|
||||
char* search_for_session(unsigned idx, const char* match, int match_size);
|
||||
char *search_for_session(unsigned int idx, const char *match, int match_size);
|
||||
|
||||
char* search_for_ip(unsigned idx, const char* match, int match_size);
|
||||
void ip_entries_add(void *pool, const char* ip, unsigned ip_size);
|
||||
char *search_for_ip(unsigned int idx, const char *match, int match_size);
|
||||
void ip_entries_add(void *pool, const char *ip, unsigned int ip_size);
|
||||
void ip_entries_clear(void);
|
||||
|
||||
#define DEFAULT_TIMEOUT (10*1000)
|
||||
#define DEFAULT_TIMEOUT (10 * 1000)
|
||||
#define NO_GROUP "(none)"
|
||||
#define NO_USER "(none)"
|
||||
|
||||
#define ERR_SERVER_UNREACHABLE "could not send message; possibly insufficient permissions or server is offline.\n"
|
||||
#define ERR_SERVER_UNREACHABLE \
|
||||
"could not send message; possibly insufficient permissions or server is offline.\n"
|
||||
|
||||
unsigned need_help(const char *arg);
|
||||
unsigned check_cmd_help(const char *line);
|
||||
unsigned int need_help(const char *arg);
|
||||
unsigned int check_cmd_help(const char *line);
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
# include <dbus/dbus.h>
|
||||
# define CONN_TYPE struct dbus_ctx
|
||||
#include <dbus/dbus.h>
|
||||
#define CONN_TYPE struct dbus_ctx
|
||||
#else
|
||||
# define CONN_TYPE struct unix_ctx
|
||||
#define CONN_TYPE struct unix_ctx
|
||||
#endif
|
||||
|
||||
CONN_TYPE *conn_init(void *pool, const char *socket_file);
|
||||
void conn_close(CONN_TYPE*);
|
||||
void conn_close(CONN_TYPE *);
|
||||
|
||||
int conn_prehandle(CONN_TYPE *ctx);
|
||||
void conn_posthandle(CONN_TYPE *ctx);
|
||||
|
||||
typedef int (*cmd_func) (CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
typedef int (*cmd_func)(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
|
||||
int handle_status_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_users_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_iroutes_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_banned_ips_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_all_sessions_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_valid_sessions_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_show_session_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_status_cmd(CONN_TYPE *conn, const char *arg, cmd_params_st *params);
|
||||
int handle_list_users_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_list_iroutes_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_list_banned_ips_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_list_all_sessions_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_list_valid_sessions_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_show_session_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
|
||||
int handle_list_banned_points_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_show_user_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_show_id_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_disconnect_user_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_unban_ip_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_disconnect_id_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_reload_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_stop_cmd(CONN_TYPE * conn, const char *arg, cmd_params_st *params);
|
||||
int handle_events_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *params);
|
||||
int handle_list_banned_points_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_show_user_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_show_id_cmd(CONN_TYPE *conn, const char *arg, cmd_params_st *params);
|
||||
int handle_disconnect_user_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_unban_ip_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_disconnect_id_cmd(CONN_TYPE *conn, const char *arg,
|
||||
cmd_params_st *params);
|
||||
int handle_reload_cmd(CONN_TYPE *conn, const char *arg, cmd_params_st *params);
|
||||
int handle_stop_cmd(CONN_TYPE *conn, const char *arg, cmd_params_st *params);
|
||||
int handle_events_cmd(struct unix_ctx *ctx, const char *arg,
|
||||
cmd_params_st *params);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
#include <unistd.h>
|
||||
#include <occtl/occtl.h>
|
||||
|
||||
static const char* get_pager(void)
|
||||
static const char *get_pager(void)
|
||||
{
|
||||
char* pager;
|
||||
char *pager;
|
||||
|
||||
pager = getenv("OCCTL_PAGER");
|
||||
if (pager == NULL)
|
||||
@@ -40,7 +40,7 @@ static const char* get_pager(void)
|
||||
}
|
||||
|
||||
/* Always succeeds */
|
||||
FILE* pager_start(cmd_params_st *params)
|
||||
FILE *pager_start(cmd_params_st *params)
|
||||
{
|
||||
FILE *fp;
|
||||
const char *pager;
|
||||
@@ -64,14 +64,15 @@ FILE* pager_start(cmd_params_st *params)
|
||||
fp = popen(pager, "w");
|
||||
|
||||
if (fp == NULL) { /* no pager */
|
||||
fprintf(stderr, "unable to start pager; check your $PAGER environment variable\n");
|
||||
fprintf(stderr,
|
||||
"unable to start pager; check your $PAGER environment variable\n");
|
||||
fp = stdout;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
void pager_stop(FILE* fp)
|
||||
void pager_stop(FILE *fp)
|
||||
{
|
||||
if (fp != stdout)
|
||||
pclose(fp);
|
||||
|
||||
@@ -36,28 +36,29 @@
|
||||
|
||||
#define escape_val json_escape_val
|
||||
|
||||
int print_list_entries(FILE* out, cmd_params_st *params, const char* name, char **val, unsigned vsize, unsigned have_more)
|
||||
int print_list_entries(FILE *out, cmd_params_st *params, const char *name,
|
||||
char **val, unsigned int vsize, unsigned int have_more)
|
||||
{
|
||||
const char * tmp;
|
||||
const char *tmp;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
fprintf(out, " \"%s\":\t[", name);
|
||||
for (i=0;i<vsize;i++) {
|
||||
for (i = 0; i < vsize; i++) {
|
||||
tmp = val[i];
|
||||
if (tmp != NULL) {
|
||||
if (i==0)
|
||||
if (i == 0)
|
||||
fprintf(out, "\"%s\"", tmp);
|
||||
else
|
||||
fprintf(out, ", \"%s\"", tmp);
|
||||
}
|
||||
}
|
||||
fprintf(out, "]%s\n", have_more?",":"");
|
||||
fprintf(out, "]%s\n", have_more ? "," : "");
|
||||
} else {
|
||||
for (i=0;i<vsize;i++) {
|
||||
for (i = 0; i < vsize; i++) {
|
||||
tmp = val[i];
|
||||
if (tmp != NULL) {
|
||||
if (i==0)
|
||||
if (i == 0)
|
||||
fprintf(out, "\t%s: %s\n", name, tmp);
|
||||
else
|
||||
fprintf(out, "\t\t%s\n", tmp);
|
||||
@@ -68,32 +69,44 @@ int print_list_entries(FILE* out, cmd_params_st *params, const char* name, char
|
||||
return i;
|
||||
}
|
||||
|
||||
int print_fwport_entries(FILE* out, cmd_params_st *params, const char* name, FwPortSt **val, unsigned vsize, unsigned have_more)
|
||||
int print_fwport_entries(FILE *out, cmd_params_st *params, const char *name,
|
||||
FwPortSt **val, unsigned int vsize,
|
||||
unsigned int have_more)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
char tmp[64];
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
fprintf(out, " \"%s\":\t[", name);
|
||||
for (i=0;i<vsize;i++) {
|
||||
for (i = 0; i < vsize; i++) {
|
||||
if (val[i]->port)
|
||||
snprintf(tmp, sizeof(tmp), "%s%s(%d)", val[i]->negate?"!":"", proto_to_str(val[i]->proto), val[i]->port);
|
||||
snprintf(tmp, sizeof(tmp), "%s%s(%d)",
|
||||
val[i]->negate ? "!" : "",
|
||||
proto_to_str(val[i]->proto),
|
||||
val[i]->port);
|
||||
else
|
||||
snprintf(tmp, sizeof(tmp), "%s%s()", val[i]->negate?"!":"", proto_to_str(val[i]->proto));
|
||||
snprintf(tmp, sizeof(tmp), "%s%s()",
|
||||
val[i]->negate ? "!" : "",
|
||||
proto_to_str(val[i]->proto));
|
||||
|
||||
if (i==0)
|
||||
if (i == 0)
|
||||
fprintf(out, "\"%s\"", tmp);
|
||||
else
|
||||
fprintf(out, ", \"%s\"", tmp);
|
||||
}
|
||||
fprintf(out, "]%s\n", have_more?",":"");
|
||||
fprintf(out, "]%s\n", have_more ? "," : "");
|
||||
} else {
|
||||
for (i=0;i<vsize;i++) {
|
||||
for (i = 0; i < vsize; i++) {
|
||||
if (val[i]->port)
|
||||
snprintf(tmp, sizeof(tmp), "%s%s(%d)", val[i]->negate?"!":"", proto_to_str(val[i]->proto), val[i]->port);
|
||||
snprintf(tmp, sizeof(tmp), "%s%s(%d)",
|
||||
val[i]->negate ? "!" : "",
|
||||
proto_to_str(val[i]->proto),
|
||||
val[i]->port);
|
||||
else
|
||||
snprintf(tmp, sizeof(tmp), "%s%s()", val[i]->negate?"!":"", proto_to_str(val[i]->proto));
|
||||
if (i==0)
|
||||
snprintf(tmp, sizeof(tmp), "%s%s()",
|
||||
val[i]->negate ? "!" : "",
|
||||
proto_to_str(val[i]->proto));
|
||||
if (i == 0)
|
||||
fprintf(out, "\t%s: %s", name, tmp);
|
||||
else
|
||||
fprintf(out, ", %s", tmp);
|
||||
@@ -110,10 +123,10 @@ void print_start_block(FILE *out, cmd_params_st *params)
|
||||
fprintf(out, " {\n");
|
||||
}
|
||||
|
||||
void print_end_block(FILE *out, cmd_params_st *params, unsigned have_more)
|
||||
void print_end_block(FILE *out, cmd_params_st *params, unsigned int have_more)
|
||||
{
|
||||
if (HAVE_JSON(params))
|
||||
fprintf(out, " }%s\n", have_more?",":"");
|
||||
fprintf(out, " }%s\n", have_more ? "," : "");
|
||||
}
|
||||
|
||||
void print_array_block(FILE *out, cmd_params_st *params)
|
||||
@@ -134,53 +147,72 @@ void print_separator(FILE *out, cmd_params_st *params)
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
|
||||
void print_single_value(FILE *out, cmd_params_st *params, const char *name, const char *value, unsigned have_more)
|
||||
void print_single_value(FILE *out, cmd_params_st *params, const char *name,
|
||||
const char *value, unsigned int have_more)
|
||||
{
|
||||
char tmp[MAX_STR_SIZE];
|
||||
|
||||
if (value[0] == 0)
|
||||
return;
|
||||
|
||||
if (HAVE_JSON(params))
|
||||
fprintf(out, " \"%s\": \"%s\"%s\n", name, escape_val(tmp, sizeof(tmp), value), have_more?",":"");
|
||||
fprintf(out, " \"%s\": \"%s\"%s\n", name,
|
||||
escape_val(tmp, sizeof(tmp), value),
|
||||
have_more ? "," : "");
|
||||
else
|
||||
fprintf(out, "\t%s: %s\n", name, value);
|
||||
}
|
||||
|
||||
void print_single_value_int(FILE *out, cmd_params_st *params, const char *name, long i, unsigned have_more)
|
||||
void print_single_value_int(FILE *out, cmd_params_st *params, const char *name,
|
||||
long i, unsigned int have_more)
|
||||
{
|
||||
if (HAVE_JSON(params))
|
||||
fprintf(out, " \"%s\": \%lu%s\n", name, i, have_more?",":"");
|
||||
fprintf(out, " \"%s\": \%lu%s\n", name, i,
|
||||
have_more ? "," : "");
|
||||
else
|
||||
fprintf(out, "\t%s: %lu\n", name, i);
|
||||
}
|
||||
|
||||
void print_single_value_ex(FILE *out, cmd_params_st *params, const char *name, const char *value, const char *ex, unsigned have_more)
|
||||
void print_single_value_ex(FILE *out, cmd_params_st *params, const char *name,
|
||||
const char *value, const char *ex,
|
||||
unsigned int have_more)
|
||||
{
|
||||
char tmp[MAX_STR_SIZE];
|
||||
|
||||
if (value[0] == 0)
|
||||
return;
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
fprintf(out, " \"%s\": \"%s\",\n", name, escape_val(tmp, sizeof(tmp), value));
|
||||
fprintf(out, " \"_%s\": \"%s\"%s\n", name, escape_val(tmp, sizeof(tmp), ex), have_more?",":"");
|
||||
fprintf(out, " \"%s\": \"%s\",\n", name,
|
||||
escape_val(tmp, sizeof(tmp), value));
|
||||
fprintf(out, " \"_%s\": \"%s\"%s\n", name,
|
||||
escape_val(tmp, sizeof(tmp), ex), have_more ? "," : "");
|
||||
} else
|
||||
fprintf(out, "\t%s: %s (%s)\n", name, value, ex);
|
||||
}
|
||||
|
||||
void print_pair_value(FILE *out, cmd_params_st *params, const char *name1, const char *value1, const char *name2, const char *value2, unsigned have_more)
|
||||
void print_pair_value(FILE *out, cmd_params_st *params, const char *name1,
|
||||
const char *value1, const char *name2, const char *value2,
|
||||
unsigned int have_more)
|
||||
{
|
||||
char tmp[MAX_STR_SIZE];
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
if (value1 && value1[0] != 0)
|
||||
fprintf(out, " \"%s\": \"%s\"%s\n", name1, escape_val(tmp, sizeof(tmp), value1), have_more?",":"");
|
||||
fprintf(out, " \"%s\": \"%s\"%s\n", name1,
|
||||
escape_val(tmp, sizeof(tmp), value1),
|
||||
have_more ? "," : "");
|
||||
if (value2 && value2[0] != 0)
|
||||
fprintf(out, " \"%s\": \"%s\"%s\n", name2, escape_val(tmp, sizeof(tmp), value2), have_more?",":"");
|
||||
fprintf(out, " \"%s\": \"%s\"%s\n", name2,
|
||||
escape_val(tmp, sizeof(tmp), value2),
|
||||
have_more ? "," : "");
|
||||
} else {
|
||||
if (value1 && value1[0] != 0)
|
||||
fprintf(out, "\t%s: %s", name1, value1);
|
||||
|
||||
if (value2 && value2[0] != 0) {
|
||||
const char *sep;
|
||||
|
||||
if (name1)
|
||||
sep = " ";
|
||||
else
|
||||
|
||||
@@ -30,35 +30,39 @@ typedef struct session_entries_st {
|
||||
char session[SAFE_ID_SIZE];
|
||||
} session_entries_st;
|
||||
|
||||
static session_entries_st *session_entries = NULL;
|
||||
static unsigned session_entries_size = 0;
|
||||
static unsigned max_session_entries_size = 0;
|
||||
static session_entries_st *session_entries;
|
||||
static unsigned int session_entries_size;
|
||||
static unsigned int max_session_entries_size;
|
||||
|
||||
void session_entries_clear(void)
|
||||
{
|
||||
session_entries_size = 0;
|
||||
}
|
||||
|
||||
void session_entries_add(void *pool, const char* session)
|
||||
void session_entries_add(void *pool, const char *session)
|
||||
{
|
||||
if (session_entries_size+1 > max_session_entries_size) {
|
||||
if (session_entries_size + 1 > max_session_entries_size) {
|
||||
max_session_entries_size += 128;
|
||||
session_entries = talloc_realloc_size(pool, session_entries, sizeof(session_entries_st)*max_session_entries_size);
|
||||
session_entries = talloc_realloc_size(
|
||||
pool, session_entries,
|
||||
sizeof(session_entries_st) * max_session_entries_size);
|
||||
}
|
||||
|
||||
strlcpy(session_entries[session_entries_size].session, session, sizeof(session_entries[session_entries_size].session));
|
||||
strlcpy(session_entries[session_entries_size].session, session,
|
||||
sizeof(session_entries[session_entries_size].session));
|
||||
session_entries_size++;
|
||||
}
|
||||
|
||||
char* search_for_session(unsigned idx, const char* match, int match_size)
|
||||
char *search_for_session(unsigned int idx, const char *match, int match_size)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
if (idx >= session_entries_size)
|
||||
return NULL;
|
||||
|
||||
for (i=idx;i<session_entries_size;i++) {
|
||||
if (strncasecmp(match, session_entries[i].session, MIN(match_size, SAFE_ID_SIZE)) == 0)
|
||||
for (i = idx; i < session_entries_size; i++) {
|
||||
if (strncasecmp(match, session_entries[i].session,
|
||||
MIN(match_size, SAFE_ID_SIZE)) == 0)
|
||||
return strdup(session_entries[i].session);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,17 +44,19 @@ void print_time_ival7(char output[MAX_TMPSTR_SIZE], time_t t1, time_t t2)
|
||||
|
||||
if (t >= 48 * 60 * 60)
|
||||
/* 2 days or more */
|
||||
snprintf(output, MAX_TMPSTR_SIZE, _("%2ludays"), (long)t / (24 * 60 * 60));
|
||||
snprintf(output, MAX_TMPSTR_SIZE, _("%2ludays"),
|
||||
(long)t / (24 * 60 * 60));
|
||||
else if (t >= 60 * 60)
|
||||
/* 1 hour or more */
|
||||
/* Translation Hint: Hours:Minutes */
|
||||
snprintf(output, MAX_TMPSTR_SIZE, _("%2luh:%02um"), (long)t / (60 * 60),
|
||||
(unsigned)((t / 60) % 60));
|
||||
/* Translation Hint: Hours:Minutes */
|
||||
snprintf(output, MAX_TMPSTR_SIZE, _("%2luh:%02um"),
|
||||
(long)t / (60 * 60), (unsigned int)((t / 60) % 60));
|
||||
else if (t > 60)
|
||||
/* 1 minute or more */
|
||||
/* Translation Hint: Minutes:Seconds */
|
||||
snprintf(output, MAX_TMPSTR_SIZE, "%2lum:%02us", (long)t / 60, (unsigned)t % 60);
|
||||
/* Translation Hint: Minutes:Seconds */
|
||||
snprintf(output, MAX_TMPSTR_SIZE, "%2lum:%02us", (long)t / 60,
|
||||
(unsigned int)t % 60);
|
||||
else
|
||||
/* Translation Hint: Seconds:Centiseconds */
|
||||
/* Translation Hint: Seconds:Centiseconds */
|
||||
snprintf(output, MAX_TMPSTR_SIZE, _("%5lus"), (long)t);
|
||||
}
|
||||
|
||||
940
src/occtl/unix.c
940
src/occtl/unix.c
File diff suppressed because it is too large
Load Diff
@@ -25,14 +25,14 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h> /* for random */
|
||||
#include <gnutls/crypto.h> /* for random */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <getopt.h>
|
||||
#ifdef HAVE_CRYPT_H
|
||||
/* libcrypt in Fedora28 does not provide prototype
|
||||
/* libcrypt in Fedora28 does not provide prototype
|
||||
* in unistd.h */
|
||||
# include <crypt.h>
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
#include <locale.h>
|
||||
|
||||
@@ -42,18 +42,17 @@ static const char alphabet[] =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
|
||||
|
||||
#define SALT_SIZE 16
|
||||
static void
|
||||
crypt_int(const char *fpasswd, const char *username, const char *groupname,
|
||||
const char *passwd)
|
||||
static void crypt_int(const char *fpasswd, const char *username,
|
||||
const char *groupname, const char *passwd)
|
||||
{
|
||||
uint8_t _salt[SALT_SIZE];
|
||||
char salt[SALT_SIZE+16];
|
||||
char salt[SALT_SIZE + 16];
|
||||
char *p, *cr_passwd;
|
||||
char *tmp_passwd;
|
||||
unsigned i;
|
||||
unsigned fpasswd_len = strlen(fpasswd);
|
||||
unsigned tmp_passwd_len;
|
||||
unsigned username_len = strlen(username);
|
||||
unsigned int i;
|
||||
unsigned int fpasswd_len = strlen(fpasswd);
|
||||
unsigned int tmp_passwd_len;
|
||||
unsigned int username_len = strlen(username);
|
||||
struct stat st;
|
||||
FILE *fd, *fd2;
|
||||
char *line = NULL;
|
||||
@@ -121,14 +120,17 @@ crypt_int(const char *fpasswd, const char *username, const char *groupname,
|
||||
fprintf(fd2, "%s:%s:%s\n", username, groupname, cr_passwd);
|
||||
} else {
|
||||
int found = 0;
|
||||
|
||||
while ((len = getline(&line, &line_size, fd)) > 0) {
|
||||
p = strchr(line, ':');
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
l = p-line;
|
||||
if (l == username_len && strncmp(line, username, l) == 0) {
|
||||
fprintf(fd2, "%s:%s:%s\n", username, groupname, cr_passwd); /* lgtm[cpp/cleartext-storage-file] */
|
||||
l = p - line;
|
||||
if (l == username_len &&
|
||||
strncmp(line, username, l) == 0) {
|
||||
fprintf(fd2, "%s:%s:%s\n", username, groupname,
|
||||
cr_passwd); /* lgtm[cpp/cleartext-storage-file] */
|
||||
found = 1;
|
||||
} else {
|
||||
fwrite(line, 1, len, fd2);
|
||||
@@ -138,7 +140,8 @@ crypt_int(const char *fpasswd, const char *username, const char *groupname,
|
||||
fclose(fd);
|
||||
|
||||
if (found == 0)
|
||||
fprintf(fd2, "%s:%s:%s\n", username, groupname, cr_passwd); /* lgtm[cpp/cleartext-storage-file] */
|
||||
fprintf(fd2, "%s:%s:%s\n", username, groupname,
|
||||
cr_passwd); /* lgtm[cpp/cleartext-storage-file] */
|
||||
}
|
||||
|
||||
fclose(fd2);
|
||||
@@ -151,15 +154,14 @@ crypt_int(const char *fpasswd, const char *username, const char *groupname,
|
||||
free(tmp_passwd);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_user(const char *fpasswd, const char *username)
|
||||
static void delete_user(const char *fpasswd, const char *username)
|
||||
{
|
||||
FILE * fd, *fd2;
|
||||
FILE *fd, *fd2;
|
||||
char *tmp_passwd;
|
||||
char *line, *p;
|
||||
unsigned fpasswd_len = strlen(fpasswd);
|
||||
unsigned tmp_passwd_len;
|
||||
unsigned username_len = strlen(username);
|
||||
unsigned int fpasswd_len = strlen(fpasswd);
|
||||
unsigned int tmp_passwd_len;
|
||||
unsigned int username_len = strlen(username);
|
||||
int ret;
|
||||
ssize_t len, l;
|
||||
size_t line_size;
|
||||
@@ -196,7 +198,7 @@ delete_user(const char *fpasswd, const char *username)
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
l = p-line;
|
||||
l = p - line;
|
||||
if (l == username_len && strncmp(line, username, l) == 0) {
|
||||
continue;
|
||||
} else {
|
||||
@@ -216,15 +218,14 @@ delete_user(const char *fpasswd, const char *username)
|
||||
free(tmp_passwd);
|
||||
}
|
||||
|
||||
static void
|
||||
lock_user(const char *fpasswd, const char *username)
|
||||
static void lock_user(const char *fpasswd, const char *username)
|
||||
{
|
||||
FILE * fd, *fd2;
|
||||
FILE *fd, *fd2;
|
||||
char *tmp_passwd;
|
||||
char *line, *p;
|
||||
unsigned fpasswd_len = strlen(fpasswd);
|
||||
unsigned tmp_passwd_len;
|
||||
unsigned username_len = strlen(username);
|
||||
unsigned int fpasswd_len = strlen(fpasswd);
|
||||
unsigned int tmp_passwd_len;
|
||||
unsigned int username_len = strlen(username);
|
||||
int ret;
|
||||
ssize_t len, l;
|
||||
size_t line_size;
|
||||
@@ -261,18 +262,18 @@ lock_user(const char *fpasswd, const char *username)
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
l = p-line;
|
||||
l = p - line;
|
||||
if (l == username_len && strncmp(line, username, l) == 0) {
|
||||
p = strchr(p+1, ':');
|
||||
p = strchr(p + 1, ':');
|
||||
if (p == NULL)
|
||||
continue;
|
||||
p++;
|
||||
|
||||
if (*p != '!') {
|
||||
l = p-line;
|
||||
l = p - line;
|
||||
fwrite(line, 1, l, fd2);
|
||||
fputc('!', fd2);
|
||||
fwrite(p, 1, len-l, fd2);
|
||||
fwrite(p, 1, len - l, fd2);
|
||||
} else {
|
||||
fwrite(line, 1, len, fd2);
|
||||
}
|
||||
@@ -293,15 +294,14 @@ lock_user(const char *fpasswd, const char *username)
|
||||
free(tmp_passwd);
|
||||
}
|
||||
|
||||
static void
|
||||
unlock_user(const char *fpasswd, const char *username)
|
||||
static void unlock_user(const char *fpasswd, const char *username)
|
||||
{
|
||||
FILE * fd, *fd2;
|
||||
FILE *fd, *fd2;
|
||||
char *tmp_passwd;
|
||||
char *line, *p;
|
||||
unsigned fpasswd_len = strlen(fpasswd);
|
||||
unsigned tmp_passwd_len;
|
||||
unsigned username_len = strlen(username);
|
||||
unsigned int fpasswd_len = strlen(fpasswd);
|
||||
unsigned int tmp_passwd_len;
|
||||
unsigned int username_len = strlen(username);
|
||||
int ret;
|
||||
ssize_t len, l;
|
||||
size_t line_size;
|
||||
@@ -338,19 +338,20 @@ unlock_user(const char *fpasswd, const char *username)
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
l = p-line;
|
||||
l = p - line;
|
||||
if (l == username_len && strncmp(line, username, l) == 0) {
|
||||
p = strchr(p+1, ':');
|
||||
p = strchr(p + 1, ':');
|
||||
if (p == NULL)
|
||||
continue;
|
||||
p++;
|
||||
|
||||
l = p-line;
|
||||
l = p - line;
|
||||
fwrite(line, 1, l, fd2);
|
||||
|
||||
if (*p=='!') p++;
|
||||
l = p-line;
|
||||
fwrite(p, 1, len-l, fd2);
|
||||
if (*p == '!')
|
||||
p++;
|
||||
l = p - line;
|
||||
fwrite(p, 1, len - l, fd2);
|
||||
} else {
|
||||
fwrite(line, 1, len, fd2);
|
||||
}
|
||||
@@ -369,63 +370,67 @@ unlock_user(const char *fpasswd, const char *username)
|
||||
}
|
||||
|
||||
static const struct option long_options[] = {
|
||||
{"passwd", 1, 0, 'c'},
|
||||
{"groupname", 1, 0, 'g'},
|
||||
{"delete", 0, 0, 'd'},
|
||||
{"lock", 0, 0, 'l'},
|
||||
{"unlock", 0, 0, 'u'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"version", 0, 0, 'v'},
|
||||
{NULL, 0, 0, 0}
|
||||
{ "passwd", 1, 0, 'c' }, { "groupname", 1, 0, 'g' },
|
||||
{ "delete", 0, 0, 'd' }, { "lock", 0, 0, 'l' },
|
||||
{ "unlock", 0, 0, 'u' }, { "help", 0, 0, 'h' },
|
||||
{ "version", 0, 0, 'v' }, { NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static
|
||||
void usage(void)
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "ocpasswd - OpenConnect server password utility\n");
|
||||
fprintf(stderr, "Usage: ocpasswd [ -<flag> [<val>] | --<name>[{=| }<val>] ]... [username]\n");
|
||||
fprintf(stderr,
|
||||
"Usage: ocpasswd [ -<flag> [<val>] | --<name>[{=| }<val>] ]... [username]\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " -c, --passwd=file Password file\n");
|
||||
fprintf(stderr, " -g, --groupname=str User's group name\n");
|
||||
fprintf(stderr, " -d, --delete Delete user\n");
|
||||
fprintf(stderr, " -l, --lock Lock user\n");
|
||||
fprintf(stderr, " -u, --unlock Unlock user\n");
|
||||
fprintf(stderr, " -v, --version output version information and exit\n");
|
||||
fprintf(stderr, " -h, --help display extended usage information and exit\n");
|
||||
fprintf(stderr,
|
||||
" -v, --version output version information and exit\n");
|
||||
fprintf(stderr,
|
||||
" -h, --help display extended usage information and exit\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Options are specified by doubled hyphens and their name or by a single\n");
|
||||
fprintf(stderr,
|
||||
"Options are specified by doubled hyphens and their name or by a single\n");
|
||||
fprintf(stderr, "hyphen and the flag character.\n\n");
|
||||
fprintf(stderr, "This program is openconnect password (ocpasswd) utility. It allows the\n");
|
||||
fprintf(stderr, "generation and handling of a 'plain' password file used by ocserv.\n\n");
|
||||
fprintf(stderr, "Please file bug reports at: "PACKAGE_BUGREPORT"\n");
|
||||
fprintf(stderr,
|
||||
"This program is openconnect password (ocpasswd) utility. It allows the\n");
|
||||
fprintf(stderr,
|
||||
"generation and handling of a 'plain' password file used by ocserv.\n\n");
|
||||
fprintf(stderr, "Please file bug reports at: " PACKAGE_BUGREPORT "\n");
|
||||
}
|
||||
|
||||
static
|
||||
void version(void)
|
||||
static void version(void)
|
||||
{
|
||||
fprintf(stderr, "ocpasswd - "VERSION"\n");
|
||||
fprintf(stderr, "Copyright (C) 2013-2017 Nikos Mavrogiannopoulos, all rights reserved.\n");
|
||||
fprintf(stderr, "This is free software. It is licensed for use, modification and\n");
|
||||
fprintf(stderr, "redistribution under the terms of the GNU General Public License,\n");
|
||||
fprintf(stderr, "ocpasswd - " VERSION "\n");
|
||||
fprintf(stderr,
|
||||
"Copyright (C) 2013-2017 Nikos Mavrogiannopoulos, all rights reserved.\n");
|
||||
fprintf(stderr,
|
||||
"This is free software. It is licensed for use, modification and\n");
|
||||
fprintf(stderr,
|
||||
"redistribution under the terms of the GNU General Public License,\n");
|
||||
fprintf(stderr, "version 2 <http://gnu.org/licenses/gpl.html>\n\n");
|
||||
fprintf(stderr, "Please file bug reports at: "PACKAGE_BUGREPORT"\n");
|
||||
fprintf(stderr, "Please file bug reports at: " PACKAGE_BUGREPORT "\n");
|
||||
}
|
||||
|
||||
#define FLAG_DELETE 1
|
||||
#define FLAG_LOCK (1<<1)
|
||||
#define FLAG_UNLOCK (1<<2)
|
||||
#define FLAG_LOCK (1 << 1)
|
||||
#define FLAG_UNLOCK (1 << 2)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret, c;
|
||||
const char *username = NULL;
|
||||
char *groupname = NULL, *fpasswd = NULL;
|
||||
char* passwd = NULL;
|
||||
unsigned free_passwd = 0;
|
||||
char *passwd = NULL;
|
||||
unsigned int free_passwd = 0;
|
||||
size_t l, i;
|
||||
unsigned flags = 0;
|
||||
unsigned int flags = 0;
|
||||
|
||||
if ((ret = gnutls_global_init()) < 0) {
|
||||
ret = gnutls_global_init();
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -440,14 +445,16 @@ int main(int argc, char **argv)
|
||||
switch (c) {
|
||||
case 'c':
|
||||
if (fpasswd) {
|
||||
fprintf(stderr, "-c option cannot be specified multiple time\n");
|
||||
fprintf(stderr,
|
||||
"-c option cannot be specified multiple time\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fpasswd = strdup(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
if (groupname) {
|
||||
fprintf(stderr, "-g option cannot be specified multiple time\n");
|
||||
fprintf(stderr,
|
||||
"-g option cannot be specified multiple time\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
groupname = strdup(optarg);
|
||||
@@ -482,7 +489,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc && argc-optind == 1) {
|
||||
if (optind < argc && argc - optind == 1) {
|
||||
username = argv[optind++];
|
||||
} else {
|
||||
usage();
|
||||
@@ -511,7 +518,7 @@ int main(int argc, char **argv)
|
||||
} else { /* set password */
|
||||
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
char* p2;
|
||||
char *p2;
|
||||
|
||||
passwd = getpass("Enter password: ");
|
||||
if (passwd == NULL) {
|
||||
@@ -519,7 +526,6 @@ int main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
p2 = strdup(passwd);
|
||||
passwd = getpass("Re-enter password: ");
|
||||
if (passwd == NULL) {
|
||||
@@ -541,8 +547,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
free_passwd = 1;
|
||||
if (passwd[l-1] == '\n')
|
||||
passwd[l-1] = 0;
|
||||
if (passwd[l - 1] == '\n')
|
||||
passwd[l - 1] = 0;
|
||||
}
|
||||
|
||||
crypt_int(fpasswd, username, groupname, passwd);
|
||||
|
||||
@@ -25,48 +25,47 @@
|
||||
|
||||
struct find_ip_st {
|
||||
struct sockaddr_storage *sockaddr;
|
||||
unsigned sockaddr_size;
|
||||
unsigned found_ips;
|
||||
unsigned int sockaddr_size;
|
||||
unsigned int found_ips;
|
||||
};
|
||||
|
||||
struct find_dtls_id_st {
|
||||
const uint8_t *dtls_id;
|
||||
unsigned dtls_id_size;
|
||||
unsigned int dtls_id_size;
|
||||
};
|
||||
|
||||
struct find_sid_st {
|
||||
const uint8_t *sid;
|
||||
};
|
||||
|
||||
|
||||
static size_t rehash_ip(const void* _p, void* unused)
|
||||
static size_t rehash_ip(const void *_p, void *unused)
|
||||
{
|
||||
const struct proc_st * proc = _p;
|
||||
const struct proc_st *proc = _p;
|
||||
|
||||
return hash_any(
|
||||
SA_IN_P_GENERIC(&proc->remote_addr, proc->remote_addr_len),
|
||||
SA_IN_SIZE(proc->remote_addr_len), 0);
|
||||
return hash_any(SA_IN_P_GENERIC(&proc->remote_addr,
|
||||
proc->remote_addr_len),
|
||||
SA_IN_SIZE(proc->remote_addr_len), 0);
|
||||
}
|
||||
|
||||
static size_t rehash_dtls_ip(const void* _p, void* unused)
|
||||
static size_t rehash_dtls_ip(const void *_p, void *unused)
|
||||
{
|
||||
const struct proc_st * proc = _p;
|
||||
const struct proc_st *proc = _p;
|
||||
|
||||
return hash_any(
|
||||
SA_IN_P_GENERIC(&proc->dtls_remote_addr, proc->dtls_remote_addr_len),
|
||||
SA_IN_SIZE(proc->dtls_remote_addr_len), 0);
|
||||
return hash_any(SA_IN_P_GENERIC(&proc->dtls_remote_addr,
|
||||
proc->dtls_remote_addr_len),
|
||||
SA_IN_SIZE(proc->dtls_remote_addr_len), 0);
|
||||
}
|
||||
|
||||
static size_t rehash_dtls_id(const void* _p, void* unused)
|
||||
static size_t rehash_dtls_id(const void *_p, void *unused)
|
||||
{
|
||||
const struct proc_st * proc = _p;
|
||||
const struct proc_st *proc = _p;
|
||||
|
||||
return hash_any(proc->dtls_session_id, proc->dtls_session_id_size, 0);
|
||||
}
|
||||
|
||||
static size_t rehash_sid(const void* _p, void* unused)
|
||||
static size_t rehash_sid(const void *_p, void *unused)
|
||||
{
|
||||
const struct proc_st * proc = _p;
|
||||
const struct proc_st *proc = _p;
|
||||
|
||||
return hash_any(proc->sid, sizeof(proc->sid), 0);
|
||||
}
|
||||
@@ -113,7 +112,8 @@ int proc_table_add(main_server_st *s, struct proc_st *proc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (htable_add(s->proc_table.db_sid, rehash_sid(proc, NULL), proc) == 0) {
|
||||
if (htable_add(s->proc_table.db_sid, rehash_sid(proc, NULL), proc) ==
|
||||
0) {
|
||||
htable_del(s->proc_table.db_ip, ip_hash, proc);
|
||||
htable_del(s->proc_table.db_dtls_id, dtls_id_hash, proc);
|
||||
return -1;
|
||||
@@ -124,19 +124,21 @@ int proc_table_add(main_server_st *s, struct proc_st *proc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int proc_table_update_ip(main_server_st *s, struct proc_st *proc, struct sockaddr_storage *addr,
|
||||
unsigned addr_size)
|
||||
int proc_table_update_ip(main_server_st *s, struct proc_st *proc,
|
||||
struct sockaddr_storage *addr, unsigned int addr_size)
|
||||
{
|
||||
char buf[MAX_IP_STR];
|
||||
unsigned removed;
|
||||
unsigned int removed;
|
||||
|
||||
/* only update if we can remove the old IP */
|
||||
if (addr_size != proc->remote_addr_len ||
|
||||
memcmp(addr, &proc->remote_addr, addr_size) != 0) {
|
||||
mslog(s, proc, LOG_INFO, "updating remote IP to %s",
|
||||
human_addr2((struct sockaddr*)addr, addr_size, buf, sizeof(buf), 0));
|
||||
human_addr2((struct sockaddr *)addr, addr_size, buf,
|
||||
sizeof(buf), 0));
|
||||
|
||||
removed = htable_del(s->proc_table.db_ip, rehash_ip(proc, NULL), proc);
|
||||
removed = htable_del(s->proc_table.db_ip, rehash_ip(proc, NULL),
|
||||
proc);
|
||||
|
||||
memcpy(&proc->remote_addr, addr, addr_size);
|
||||
proc->remote_addr_len = addr_size;
|
||||
@@ -147,8 +149,8 @@ int proc_table_update_ip(main_server_st *s, struct proc_st *proc, struct sockadd
|
||||
memcmp(SA_IN_P_GENERIC(addr, addr_size),
|
||||
SA_IN_P_GENERIC(&proc->dtls_remote_addr, addr_size),
|
||||
SA_IN_SIZE(addr_size)) == 0) {
|
||||
|
||||
if (htable_del(s->proc_table.db_dtls_ip, rehash_dtls_ip(proc, NULL), proc) != 0)
|
||||
if (htable_del(s->proc_table.db_dtls_ip,
|
||||
rehash_dtls_ip(proc, NULL), proc) != 0)
|
||||
proc->dtls_remote_addr_len = 0;
|
||||
}
|
||||
|
||||
@@ -156,7 +158,8 @@ int proc_table_update_ip(main_server_st *s, struct proc_st *proc, struct sockadd
|
||||
* we may be called even before that entry is added, and we don't want
|
||||
* duplicates */
|
||||
if (removed) {
|
||||
if (htable_add(s->proc_table.db_ip, rehash_ip(proc, NULL), proc) == 0)
|
||||
if (htable_add(s->proc_table.db_ip,
|
||||
rehash_ip(proc, NULL), proc) == 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -167,7 +170,9 @@ int proc_table_update_ip(main_server_st *s, struct proc_st *proc, struct sockadd
|
||||
/* Adds the IP of the DTLS channel into the DTLS IP hash table. It
|
||||
* only adds the IP if it is different than the CSTP channel IP.
|
||||
*/
|
||||
int proc_table_update_dtls_ip(main_server_st *s, struct proc_st *proc, struct sockaddr_storage *addr, unsigned addr_size)
|
||||
int proc_table_update_dtls_ip(main_server_st *s, struct proc_st *proc,
|
||||
struct sockaddr_storage *addr,
|
||||
unsigned int addr_size)
|
||||
{
|
||||
if (proc->dtls_remote_addr_len) {
|
||||
if (proc->dtls_remote_addr_len == addr_size &&
|
||||
@@ -176,7 +181,8 @@ int proc_table_update_dtls_ip(main_server_st *s, struct proc_st *proc, struct so
|
||||
SA_IN_SIZE(addr_size)) == 0) {
|
||||
return -1; /* DTLS address is already up to date */
|
||||
}
|
||||
htable_del(s->proc_table.db_dtls_ip, rehash_dtls_ip(proc, NULL), proc);
|
||||
htable_del(s->proc_table.db_dtls_ip, rehash_dtls_ip(proc, NULL),
|
||||
proc);
|
||||
}
|
||||
|
||||
proc->dtls_remote_addr_len = 0;
|
||||
@@ -193,7 +199,8 @@ int proc_table_update_dtls_ip(main_server_st *s, struct proc_st *proc, struct so
|
||||
proc->dtls_remote_addr_len = addr_size;
|
||||
memcpy(&proc->dtls_remote_addr, addr, addr_size);
|
||||
|
||||
if (htable_add(s->proc_table.db_dtls_ip, rehash_dtls_ip(proc, NULL), proc) == 0)
|
||||
if (htable_add(s->proc_table.db_dtls_ip, rehash_dtls_ip(proc, NULL),
|
||||
proc) == 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@@ -202,24 +209,26 @@ int proc_table_update_dtls_ip(main_server_st *s, struct proc_st *proc, struct so
|
||||
void proc_table_del(main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
if (proc->dtls_remote_addr_len > 0)
|
||||
htable_del(s->proc_table.db_dtls_ip, rehash_dtls_ip(proc, NULL), proc);
|
||||
htable_del(s->proc_table.db_dtls_ip, rehash_dtls_ip(proc, NULL),
|
||||
proc);
|
||||
|
||||
htable_del(s->proc_table.db_ip, rehash_ip(proc, NULL), proc);
|
||||
htable_del(s->proc_table.db_dtls_id, rehash_dtls_id(proc, NULL), proc);
|
||||
htable_del(s->proc_table.db_sid, rehash_sid(proc, NULL), proc);
|
||||
}
|
||||
|
||||
static bool local_ip_cmp(const void* _c1, void* _c2)
|
||||
static bool local_ip_cmp(const void *_c1, void *_c2)
|
||||
{
|
||||
const struct proc_st* c1 = _c1;
|
||||
struct find_ip_st* c2 = _c2;
|
||||
const struct proc_st *c1 = _c1;
|
||||
struct find_ip_st *c2 = _c2;
|
||||
|
||||
if (c2->sockaddr_size == 0)
|
||||
return 0;
|
||||
|
||||
/* Test if peer IP matches DTLS IP */
|
||||
if (c1->dtls_remote_addr_len == c2->sockaddr_size &&
|
||||
memcmp(SA_IN_P_GENERIC(&c1->dtls_remote_addr, c1->dtls_remote_addr_len),
|
||||
memcmp(SA_IN_P_GENERIC(&c1->dtls_remote_addr,
|
||||
c1->dtls_remote_addr_len),
|
||||
SA_IN_P_GENERIC(c2->sockaddr, c2->sockaddr_size),
|
||||
SA_IN_SIZE(c1->dtls_remote_addr_len)) == 0) {
|
||||
c2->found_ips++;
|
||||
@@ -242,7 +251,7 @@ static bool local_ip_cmp(const void* _c1, void* _c2)
|
||||
*/
|
||||
struct proc_st *proc_search_single_ip(struct main_server_st *s,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
unsigned sockaddr_size)
|
||||
unsigned int sockaddr_size)
|
||||
{
|
||||
struct proc_st *proc;
|
||||
struct find_ip_st fip;
|
||||
@@ -252,7 +261,7 @@ struct proc_st *proc_search_single_ip(struct main_server_st *s,
|
||||
fip.sockaddr_size = sockaddr_size;
|
||||
|
||||
h = hash_any(SA_IN_P_GENERIC(sockaddr, sockaddr_size),
|
||||
SA_IN_SIZE(sockaddr_size), 0);
|
||||
SA_IN_SIZE(sockaddr_size), 0);
|
||||
|
||||
fip.found_ips = 0;
|
||||
proc = htable_get(s->proc_table.db_dtls_ip, h, local_ip_cmp, &fip);
|
||||
@@ -267,16 +276,15 @@ struct proc_st *proc_search_single_ip(struct main_server_st *s,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool dtls_id_cmp(const void* _c1, void* _c2)
|
||||
static bool dtls_id_cmp(const void *_c1, void *_c2)
|
||||
{
|
||||
const struct proc_st* c1 = _c1;
|
||||
struct find_dtls_id_st* c2 = _c2;
|
||||
const struct proc_st *c1 = _c1;
|
||||
struct find_dtls_id_st *c2 = _c2;
|
||||
|
||||
if (c1->dtls_session_id_size != c2->dtls_id_size)
|
||||
return 0;
|
||||
|
||||
if (memcmp(c1->dtls_session_id,
|
||||
c2->dtls_id,
|
||||
if (memcmp(c1->dtls_session_id, c2->dtls_id,
|
||||
c1->dtls_session_id_size) == 0) {
|
||||
return 1;
|
||||
}
|
||||
@@ -284,25 +292,24 @@ static bool dtls_id_cmp(const void* _c1, void* _c2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct proc_st *proc_search_dtls_id(struct main_server_st *s,
|
||||
const uint8_t *id, unsigned id_size)
|
||||
struct proc_st *proc_search_dtls_id(struct main_server_st *s, const uint8_t *id,
|
||||
unsigned int id_size)
|
||||
{
|
||||
struct find_dtls_id_st fdtls_id;
|
||||
|
||||
fdtls_id.dtls_id = id;
|
||||
fdtls_id.dtls_id_size = id_size;
|
||||
|
||||
return htable_get(s->proc_table.db_dtls_id, hash_any(id, id_size, 0), dtls_id_cmp, &fdtls_id);
|
||||
return htable_get(s->proc_table.db_dtls_id, hash_any(id, id_size, 0),
|
||||
dtls_id_cmp, &fdtls_id);
|
||||
}
|
||||
|
||||
static bool sid_cmp(const void* _c1, void* _c2)
|
||||
static bool sid_cmp(const void *_c1, void *_c2)
|
||||
{
|
||||
const struct proc_st* c1 = _c1;
|
||||
struct find_sid_st* c2 = _c2;
|
||||
const struct proc_st *c1 = _c1;
|
||||
struct find_sid_st *c2 = _c2;
|
||||
|
||||
if (memcmp(c1->sid,
|
||||
c2->sid,
|
||||
sizeof(c1->sid)) == 0) {
|
||||
if (memcmp(c1->sid, c2->sid, sizeof(c1->sid)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -310,10 +317,12 @@ static bool sid_cmp(const void* _c1, void* _c2)
|
||||
}
|
||||
|
||||
struct proc_st *proc_search_sid(struct main_server_st *s,
|
||||
const uint8_t sid[SID_SIZE])
|
||||
const uint8_t sid[SID_SIZE])
|
||||
{
|
||||
struct find_sid_st fsid;
|
||||
|
||||
fsid.sid = sid;
|
||||
|
||||
return htable_get(s->proc_table.db_sid, hash_any(sid, SID_SIZE, 0), sid_cmp, &fsid);
|
||||
return htable_get(s->proc_table.db_sid, hash_any(sid, SID_SIZE, 0),
|
||||
sid_cmp, &fsid);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_PROC_SEARCH_H
|
||||
# define OC_PROC_SEARCH_H
|
||||
#define OC_PROC_SEARCH_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <string.h>
|
||||
@@ -28,17 +28,21 @@
|
||||
#include <main.h>
|
||||
|
||||
struct proc_st *proc_search_single_ip(struct main_server_st *s,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
unsigned sockaddr_size);
|
||||
struct proc_st *proc_search_dtls_id(struct main_server_st *s, const uint8_t *id, unsigned id_size);
|
||||
struct sockaddr_storage *sockaddr,
|
||||
unsigned int sockaddr_size);
|
||||
struct proc_st *proc_search_dtls_id(struct main_server_st *s, const uint8_t *id,
|
||||
unsigned int id_size);
|
||||
struct proc_st *proc_search_sid(struct main_server_st *s,
|
||||
const uint8_t id[SID_SIZE]);
|
||||
const uint8_t id[SID_SIZE]);
|
||||
|
||||
void proc_table_init(main_server_st *s);
|
||||
void proc_table_deinit(main_server_st *s);
|
||||
int proc_table_add(main_server_st *s, struct proc_st *proc);
|
||||
void proc_table_del(main_server_st *s, struct proc_st *proc);
|
||||
int proc_table_update_ip(main_server_st *s, struct proc_st *proc, struct sockaddr_storage *addr, unsigned addr_size);
|
||||
int proc_table_update_dtls_ip(main_server_st *s, struct proc_st *proc, struct sockaddr_storage *addr, unsigned addr_size);
|
||||
int proc_table_update_ip(main_server_st *s, struct proc_st *proc,
|
||||
struct sockaddr_storage *addr, unsigned int addr_size);
|
||||
int proc_table_update_dtls_ip(main_server_st *s, struct proc_st *proc,
|
||||
struct sockaddr_storage *addr,
|
||||
unsigned int addr_size);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,11 +34,10 @@
|
||||
#include <str.h>
|
||||
#include <common.h>
|
||||
|
||||
static
|
||||
int call_script(main_server_st *s, proc_st *proc, const char *cmd)
|
||||
static int call_script(main_server_st *s, proc_st *proc, const char *cmd)
|
||||
{
|
||||
pid_t pid;
|
||||
int ret, status = 0;
|
||||
pid_t pid;
|
||||
int ret, status = 0;
|
||||
|
||||
if (cmd == NULL)
|
||||
return 0;
|
||||
@@ -50,7 +49,8 @@ int ret, status = 0;
|
||||
mslog(s, proc, LOG_DEBUG, "executing route script %s", cmd);
|
||||
ret = execl("/bin/sh", "sh", "-c", cmd, NULL);
|
||||
if (ret == -1) {
|
||||
mslog(s, proc, LOG_ERR, "Could not execute route script %s", cmd);
|
||||
mslog(s, proc, LOG_ERR,
|
||||
"Could not execute route script %s", cmd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@@ -72,17 +72,16 @@ int ret, status = 0;
|
||||
}
|
||||
|
||||
if (WEXITSTATUS(status)) {
|
||||
mslog(s, proc, LOG_INFO, "cmd: %s: exited with error %d", cmd, WEXITSTATUS(ret));
|
||||
mslog(s, proc, LOG_INFO, "cmd: %s: exited with error %d", cmd,
|
||||
WEXITSTATUS(ret));
|
||||
return ERR_EXEC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int replace_cmd(struct main_server_st* s, proc_st *proc,
|
||||
char **cmd, const char* pattern,
|
||||
const char* route, const char* dev)
|
||||
static int replace_cmd(struct main_server_st *s, proc_st *proc, char **cmd,
|
||||
const char *pattern, const char *route, const char *dev)
|
||||
{
|
||||
str_st str;
|
||||
int ret;
|
||||
@@ -106,23 +105,23 @@ int replace_cmd(struct main_server_st* s, proc_st *proc,
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
*cmd = (char*)str.data;
|
||||
*cmd = (char *)str.data;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
fail:
|
||||
str_clear(&str);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
static
|
||||
int route_adddel(struct main_server_st* s, proc_st *proc,
|
||||
const char* pattern, const char* route, const char* dev)
|
||||
static int route_adddel(struct main_server_st *s, proc_st *proc,
|
||||
const char *pattern, const char *route, const char *dev)
|
||||
{
|
||||
int ret;
|
||||
char *cmd = NULL;
|
||||
int ret;
|
||||
char *cmd = NULL;
|
||||
|
||||
if (pattern == 0) {
|
||||
mslog(s, NULL, LOG_WARNING, "route-add-cmd or route-del-cmd are not set.");
|
||||
mslog(s, NULL, LOG_WARNING,
|
||||
"route-add-cmd or route-del-cmd are not set.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -133,25 +132,27 @@ char *cmd = NULL;
|
||||
ret = call_script(s, proc, cmd);
|
||||
if (ret < 0) {
|
||||
int e = errno;
|
||||
mslog(s, NULL, LOG_INFO, "failed to spawn cmd: %s: %s", cmd, strerror(e));
|
||||
|
||||
mslog(s, NULL, LOG_INFO, "failed to spawn cmd: %s: %s", cmd,
|
||||
strerror(e));
|
||||
ret = ERR_EXEC;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int route_add(struct main_server_st* s, proc_st *proc, const char* route, const char* dev)
|
||||
static int route_add(struct main_server_st *s, proc_st *proc, const char *route,
|
||||
const char *dev)
|
||||
{
|
||||
return route_adddel(s, proc, GETCONFIG(s)->route_add_cmd, route, dev);
|
||||
}
|
||||
|
||||
static
|
||||
int route_del(struct main_server_st* s, proc_st *proc, const char* route, const char* dev)
|
||||
static int route_del(struct main_server_st *s, proc_st *proc, const char *route,
|
||||
const char *dev)
|
||||
{
|
||||
return route_adddel(s, proc, GETCONFIG(s)->route_del_cmd, route, dev);
|
||||
}
|
||||
@@ -159,25 +160,27 @@ int route_del(struct main_server_st* s, proc_st *proc, const char* route, const
|
||||
/* Executes the commands required to apply all the configured routes
|
||||
* for this client locally.
|
||||
*/
|
||||
int apply_iroutes(struct main_server_st* s, struct proc_st *proc)
|
||||
int apply_iroutes(struct main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
unsigned i, j;
|
||||
int ret;
|
||||
unsigned int i, j;
|
||||
int ret;
|
||||
|
||||
if (proc->config->n_iroutes == 0)
|
||||
return 0;
|
||||
|
||||
for (i=0;i<proc->config->n_iroutes;i++) {
|
||||
ret = route_add(s, proc, proc->config->iroutes[i], proc->tun_lease.name);
|
||||
for (i = 0; i < proc->config->n_iroutes; i++) {
|
||||
ret = route_add(s, proc, proc->config->iroutes[i],
|
||||
proc->tun_lease.name);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
proc->applied_iroutes = 1;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
for (j=0;j<i;j++)
|
||||
route_del(s, proc, proc->config->iroutes[j], proc->tun_lease.name);
|
||||
fail:
|
||||
for (j = 0; j < i; j++)
|
||||
route_del(s, proc, proc->config->iroutes[j],
|
||||
proc->tun_lease.name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -185,15 +188,17 @@ int ret;
|
||||
/* Executes the commands required to removed all the configured routes
|
||||
* for this client.
|
||||
*/
|
||||
void remove_iroutes(struct main_server_st* s, struct proc_st *proc)
|
||||
void remove_iroutes(struct main_server_st *s, struct proc_st *proc)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
if (proc->config == NULL || proc->config->n_iroutes == 0 || proc->applied_iroutes == 0)
|
||||
if (proc->config == NULL || proc->config->n_iroutes == 0 ||
|
||||
proc->applied_iroutes == 0)
|
||||
return;
|
||||
|
||||
for (i=0;i<proc->config->n_iroutes;i++) {
|
||||
route_del(s, proc, proc->config->iroutes[i], proc->tun_lease.name);
|
||||
for (i = 0; i < proc->config->n_iroutes; i++) {
|
||||
route_del(s, proc, proc->config->iroutes[i],
|
||||
proc->tun_lease.name);
|
||||
}
|
||||
proc->applied_iroutes = 0;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_ROUTE_ADD_H
|
||||
# define OC_ROUTE_ADD_H
|
||||
#define OC_ROUTE_ADD_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <main.h>
|
||||
|
||||
int apply_iroutes(struct main_server_st* s, struct proc_st *proc);
|
||||
void remove_iroutes(struct main_server_st* s, struct proc_st *proc);
|
||||
int apply_iroutes(struct main_server_st *s, struct proc_st *proc);
|
||||
void remove_iroutes(struct main_server_st *s, struct proc_st *proc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_SCRIPT_LIST_H
|
||||
# define OC_SCRIPT_LIST_H
|
||||
#define OC_SCRIPT_LIST_H
|
||||
|
||||
#include <main.h>
|
||||
#include <sys/types.h>
|
||||
@@ -28,10 +28,10 @@
|
||||
|
||||
void script_child_watcher_cb(struct ev_loop *loop, ev_child *w, int revents);
|
||||
|
||||
inline static
|
||||
void add_to_script_list(main_server_st* s, pid_t pid, struct proc_st* proc)
|
||||
inline static void add_to_script_list(main_server_st *s, pid_t pid,
|
||||
struct proc_st *proc)
|
||||
{
|
||||
struct script_wait_st *stmp;
|
||||
struct script_wait_st *stmp;
|
||||
|
||||
stmp = talloc(s, struct script_wait_st);
|
||||
if (stmp == NULL)
|
||||
@@ -49,12 +49,14 @@ struct script_wait_st *stmp;
|
||||
/* Removes the tracked connect script, and kills it. It returns the pid
|
||||
* of the removed script or -1.
|
||||
*/
|
||||
inline static pid_t remove_from_script_list(main_server_st* s, struct proc_st* proc)
|
||||
inline static pid_t remove_from_script_list(main_server_st *s,
|
||||
struct proc_st *proc)
|
||||
{
|
||||
struct script_wait_st *stmp = NULL, *spos;
|
||||
pid_t ret = -1;
|
||||
|
||||
list_for_each_safe(&s->script_list.head, stmp, spos, list) {
|
||||
list_for_each_safe(&s->script_list.head, stmp, spos, list)
|
||||
{
|
||||
if (stmp->proc == proc) {
|
||||
list_del(&stmp->list);
|
||||
ev_child_stop(main_loop, &stmp->ev_child);
|
||||
|
||||
@@ -19,21 +19,30 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_SEC_MOD_ACCT_H
|
||||
# define OC_SEC_MOD_ACCT_H
|
||||
#define OC_SEC_MOD_ACCT_H
|
||||
|
||||
#include <main.h>
|
||||
#include <sec-mod-auth.h>
|
||||
|
||||
typedef struct acct_mod_st {
|
||||
unsigned int type; /* ACCT_TYPE_ */
|
||||
unsigned int auth_types; /* or of the AUTH_TYPEs which are compatible with this */
|
||||
void (*vhost_init)(void **vctx, void *pool, void* additional);
|
||||
unsigned int
|
||||
auth_types; /* or of the AUTH_TYPEs which are compatible with this */
|
||||
void (*vhost_init)(void **vctx, void *pool, void *additional);
|
||||
void (*vhost_deinit)(void *vctx);
|
||||
|
||||
/* The context provided below is of the authentication method */
|
||||
int (*open_session)(void *vctx, unsigned auth_method, const common_acct_info_st *ai, const void *sid, unsigned sid_size); /* optional, may be null */
|
||||
void (*session_stats)(void *vctx, unsigned auth_method, const common_acct_info_st *ai, struct stats_st *stats); /* optional, may be null */
|
||||
void (*close_session)(void *vctx, unsigned auth_method, const common_acct_info_st *ai, struct stats_st *stats, unsigned discon_reason/*REASON_*/); /* optional may be null */
|
||||
int (*open_session)(void *vctx, unsigned int auth_method,
|
||||
const common_acct_info_st *ai, const void *sid,
|
||||
unsigned int sid_size); /* optional, may be null */
|
||||
void (*session_stats)(
|
||||
void *vctx, unsigned int auth_method,
|
||||
const common_acct_info_st *ai,
|
||||
struct stats_st *stats); /* optional, may be null */
|
||||
void (*close_session)(
|
||||
void *vctx, unsigned int 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.
|
||||
|
||||
@@ -54,33 +54,40 @@
|
||||
#include <hmac.h>
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
# include <gssapi/gssapi.h>
|
||||
# include <gssapi/gssapi_ext.h>
|
||||
#include <gssapi/gssapi.h>
|
||||
#include <gssapi/gssapi_ext.h>
|
||||
#endif
|
||||
|
||||
/* initializes vhost acct and auth modules if not already initialized
|
||||
*/
|
||||
void sec_auth_init(struct vhost_cfg_st *vhost)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
void *pool = vhost;
|
||||
|
||||
for (i=0;i<vhost->perm_config.auth_methods;i++) {
|
||||
if (vhost->perm_config.auth[i].enabled && vhost->perm_config.auth[i].amod &&
|
||||
vhost->perm_config.auth[i].amod->vhost_init && vhost->perm_config.auth[i].auth_ctx == NULL) {
|
||||
vhost->perm_config.auth[i].amod->vhost_init(&vhost->perm_config.auth[i].auth_ctx, pool, vhost->perm_config.auth[i].additional);
|
||||
for (i = 0; i < vhost->perm_config.auth_methods; i++) {
|
||||
if (vhost->perm_config.auth[i].enabled &&
|
||||
vhost->perm_config.auth[i].amod &&
|
||||
vhost->perm_config.auth[i].amod->vhost_init &&
|
||||
vhost->perm_config.auth[i].auth_ctx == NULL) {
|
||||
vhost->perm_config.auth[i].amod->vhost_init(
|
||||
&vhost->perm_config.auth[i].auth_ctx, pool,
|
||||
vhost->perm_config.auth[i].additional);
|
||||
}
|
||||
}
|
||||
|
||||
if (vhost->perm_config.acct.amod && vhost->perm_config.acct.amod->vhost_init &&
|
||||
if (vhost->perm_config.acct.amod &&
|
||||
vhost->perm_config.acct.amod->vhost_init &&
|
||||
vhost->perm_config.acct.acct_ctx == NULL)
|
||||
vhost->perm_config.acct.amod->vhost_init(&vhost->perm_config.acct.acct_ctx, pool, vhost->perm_config.acct.additional);
|
||||
vhost->perm_config.acct.amod->vhost_init(
|
||||
&vhost->perm_config.acct.acct_ctx, pool,
|
||||
vhost->perm_config.acct.additional);
|
||||
}
|
||||
|
||||
/* returns a negative number if we have reached the score for this client.
|
||||
*/
|
||||
static
|
||||
void sec_mod_add_score_to_ip(sec_mod_st *sec, client_entry_st *e, const char *ip, unsigned points)
|
||||
static void sec_mod_add_score_to_ip(sec_mod_st *sec, client_entry_st *e,
|
||||
const char *ip, unsigned int points)
|
||||
{
|
||||
void *lpool = talloc_new(e);
|
||||
int ret, err;
|
||||
@@ -90,7 +97,7 @@ void sec_mod_add_score_to_ip(sec_mod_st *sec, client_entry_st *e, const char *ip
|
||||
if (e->vhost->perm_config.config->max_ban_score == 0)
|
||||
return;
|
||||
|
||||
msg.ip = (char*)ip;
|
||||
msg.ip = (char *)ip;
|
||||
msg.score = points;
|
||||
msg.sid.data = e->sid;
|
||||
msg.sid.len = sizeof(e->sid);
|
||||
@@ -101,19 +108,20 @@ void sec_mod_add_score_to_ip(sec_mod_st *sec, client_entry_st *e, const char *ip
|
||||
}
|
||||
|
||||
ret = send_msg(lpool, sec->cmd_fd, CMD_SECM_BAN_IP, &msg,
|
||||
(pack_size_func) ban_ip_msg__get_packed_size,
|
||||
(pack_func) ban_ip_msg__pack);
|
||||
(pack_size_func)ban_ip_msg__get_packed_size,
|
||||
(pack_func)ban_ip_msg__pack);
|
||||
if (ret < 0) {
|
||||
err = errno;
|
||||
seclog(sec, LOG_WARNING, "error in sending BAN IP message: %s", strerror(err));
|
||||
seclog(sec, LOG_WARNING, "error in sending BAN IP message: %s",
|
||||
strerror(err));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(lpool);
|
||||
}
|
||||
|
||||
static void update_auth_time_stats(sec_mod_st * sec, time_t secs)
|
||||
static void update_auth_time_stats(sec_mod_st *sec, time_t secs)
|
||||
{
|
||||
if (secs < 0)
|
||||
return;
|
||||
@@ -127,11 +135,15 @@ static void update_auth_time_stats(sec_mod_st * sec, time_t secs)
|
||||
|
||||
if (secs > sec->max_auth_time)
|
||||
sec->max_auth_time = secs;
|
||||
sec->avg_auth_time = ((uint64_t)sec->avg_auth_time*((uint64_t)(sec->total_authentications-1))+secs) / (uint64_t)sec->total_authentications;
|
||||
sec->avg_auth_time =
|
||||
((uint64_t)sec->avg_auth_time *
|
||||
((uint64_t)(sec->total_authentications - 1)) +
|
||||
secs) /
|
||||
(uint64_t)sec->total_authentications;
|
||||
}
|
||||
|
||||
static
|
||||
int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTHREP r)
|
||||
static int send_sec_auth_reply(int cfd, sec_mod_st *sec, client_entry_st *entry,
|
||||
AUTHREP r)
|
||||
{
|
||||
SecAuthReplyMsg msg = SEC_AUTH_REPLY_MSG__INIT;
|
||||
int ret;
|
||||
@@ -157,25 +169,24 @@ int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTH
|
||||
msg.dtls_session_id.data = entry->dtls_session_id;
|
||||
msg.dtls_session_id.len = sizeof(entry->dtls_session_id);
|
||||
|
||||
ret = send_msg(entry, cfd, CMD_SEC_AUTH_REPLY,
|
||||
&msg,
|
||||
(pack_size_func)
|
||||
sec_auth_reply_msg__get_packed_size,
|
||||
(pack_func) sec_auth_reply_msg__pack);
|
||||
ret = send_msg(
|
||||
entry, cfd, CMD_SEC_AUTH_REPLY, &msg,
|
||||
(pack_size_func)sec_auth_reply_msg__get_packed_size,
|
||||
(pack_func)sec_auth_reply_msg__pack);
|
||||
} else {
|
||||
sec->auth_failures++;
|
||||
|
||||
msg.reply = AUTH__REP__FAILED;
|
||||
|
||||
ret = send_msg(entry, cfd, CMD_SEC_AUTH_REPLY,
|
||||
&msg,
|
||||
(pack_size_func)
|
||||
sec_auth_reply_msg__get_packed_size,
|
||||
(pack_func) sec_auth_reply_msg__pack);
|
||||
ret = send_msg(
|
||||
entry, cfd, CMD_SEC_AUTH_REPLY, &msg,
|
||||
(pack_size_func)sec_auth_reply_msg__get_packed_size,
|
||||
(pack_func)sec_auth_reply_msg__pack);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
int e = errno;
|
||||
|
||||
seclog(sec, LOG_ERR, "send_msg: %s", strerror(e));
|
||||
return ret;
|
||||
}
|
||||
@@ -186,8 +197,7 @@ int send_sec_auth_reply(int cfd, sec_mod_st * sec, client_entry_st * entry, AUTH
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int send_sec_auth_reply_msg(int cfd, sec_mod_st * sec, client_entry_st * e)
|
||||
static int send_sec_auth_reply_msg(int cfd, sec_mod_st *sec, client_entry_st *e)
|
||||
{
|
||||
SecAuthReplyMsg msg = SEC_AUTH_REPLY_MSG__INIT;
|
||||
int ret;
|
||||
@@ -204,8 +214,8 @@ int send_sec_auth_reply_msg(int cfd, sec_mod_st * sec, client_entry_st * e)
|
||||
msg.sid.len = sizeof(e->sid);
|
||||
|
||||
ret = send_msg(e, cfd, CMD_SEC_AUTH_REPLY, &msg,
|
||||
(pack_size_func) sec_auth_reply_msg__get_packed_size,
|
||||
(pack_func) sec_auth_reply_msg__pack);
|
||||
(pack_size_func)sec_auth_reply_msg__get_packed_size,
|
||||
(pack_func)sec_auth_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "send_auth_reply_msg error");
|
||||
}
|
||||
@@ -216,47 +226,69 @@ int send_sec_auth_reply_msg(int cfd, sec_mod_st * sec, client_entry_st * e)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_cert_user_group_status(sec_mod_st * sec, client_entry_st * e)
|
||||
static int check_cert_user_group_status(sec_mod_st *sec, client_entry_st *e)
|
||||
{
|
||||
unsigned found, i;
|
||||
unsigned int found, i;
|
||||
|
||||
if (e->auth_type & AUTH_TYPE_CERTIFICATE) {
|
||||
if (e->tls_auth_ok == 0) {
|
||||
seclog(sec, LOG_INFO, "user %s "SESSION_STR" presented no certificate; rejecting",
|
||||
seclog(sec, LOG_INFO,
|
||||
"user %s " SESSION_STR
|
||||
" presented no certificate; rejecting",
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->acct_info.username[0] == 0 && e->vhost->perm_config.config->cert_user_oid != NULL) {
|
||||
if (e->acct_info.username[0] == 0 &&
|
||||
e->vhost->perm_config.config->cert_user_oid != NULL) {
|
||||
if (e->cert_user_name[0] == 0) {
|
||||
seclog(sec, LOG_INFO, "no username in the certificate; rejecting");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strlcpy(e->acct_info.username, e->cert_user_name, sizeof(e->acct_info.username));
|
||||
if (e->cert_group_names_size > 0 && e->vhost->perm_config.config->cert_group_oid != NULL && e->acct_info.groupname[0] == 0)
|
||||
strlcpy(e->acct_info.groupname, e->cert_group_names[0], sizeof(e->acct_info.groupname));
|
||||
} else {
|
||||
if (e->vhost->perm_config.config->cert_user_oid != NULL && e->cert_user_name[0] && strcmp(e->acct_info.username, e->cert_user_name) != 0) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"user '%s' "SESSION_STR" presented a certificate which is for user '%s'; rejecting",
|
||||
e->acct_info.username, e->acct_info.safe_id, e->cert_user_name);
|
||||
"no username in the certificate; rejecting");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->vhost->perm_config.config->cert_group_oid != NULL) {
|
||||
strlcpy(e->acct_info.username, e->cert_user_name,
|
||||
sizeof(e->acct_info.username));
|
||||
if (e->cert_group_names_size > 0 &&
|
||||
e->vhost->perm_config.config->cert_group_oid !=
|
||||
NULL &&
|
||||
e->acct_info.groupname[0] == 0)
|
||||
strlcpy(e->acct_info.groupname,
|
||||
e->cert_group_names[0],
|
||||
sizeof(e->acct_info.groupname));
|
||||
} else {
|
||||
if (e->vhost->perm_config.config->cert_user_oid !=
|
||||
NULL &&
|
||||
e->cert_user_name[0] &&
|
||||
strcmp(e->acct_info.username, e->cert_user_name) !=
|
||||
0) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"user '%s' " SESSION_STR
|
||||
" presented a certificate which is for user '%s'; rejecting",
|
||||
e->acct_info.username,
|
||||
e->acct_info.safe_id, e->cert_user_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->vhost->perm_config.config->cert_group_oid !=
|
||||
NULL) {
|
||||
found = 0;
|
||||
for (i=0;i<e->cert_group_names_size;i++) {
|
||||
if (strcmp(e->acct_info.groupname, e->cert_group_names[i]) == 0) {
|
||||
for (i = 0; i < e->cert_group_names_size; i++) {
|
||||
if (strcmp(e->acct_info.groupname,
|
||||
e->cert_group_names[i]) ==
|
||||
0) {
|
||||
found++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == 0) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"user '%s' "SESSION_STR" presented a certificate from group '%s' but he isn't a member of it; rejecting",
|
||||
e->acct_info.username, e->acct_info.safe_id, e->acct_info.groupname);
|
||||
return -1;
|
||||
"user '%s' " SESSION_STR
|
||||
" presented a certificate from group '%s' but he isn't a member of it; rejecting",
|
||||
e->acct_info.username,
|
||||
e->acct_info.safe_id,
|
||||
e->acct_info.groupname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,8 +297,7 @@ static int check_cert_user_group_status(sec_mod_st * sec, client_entry_st * e)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int check_group(sec_mod_st * sec, client_entry_st * e)
|
||||
static int check_group(sec_mod_st *sec, client_entry_st *e)
|
||||
{
|
||||
int ret;
|
||||
const char *req_group = NULL;
|
||||
@@ -275,9 +306,9 @@ int check_group(sec_mod_st * sec, client_entry_st * e)
|
||||
req_group = e->req_group_name;
|
||||
|
||||
if (e->module && e->module->auth_group) {
|
||||
ret =
|
||||
e->module->auth_group(e->auth_ctx, req_group, e->acct_info.groupname,
|
||||
sizeof(e->acct_info.groupname));
|
||||
ret = e->module->auth_group(e->auth_ctx, req_group,
|
||||
e->acct_info.groupname,
|
||||
sizeof(e->acct_info.groupname));
|
||||
if (ret != 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -286,27 +317,31 @@ int check_group(sec_mod_st * sec, client_entry_st * e)
|
||||
|
||||
/* set group name using the certificate info */
|
||||
if (e->auth_type & AUTH_TYPE_CERTIFICATE) {
|
||||
if (e->acct_info.groupname[0] == 0 && req_group != NULL && e->vhost->perm_config.config->cert_group_oid != NULL) {
|
||||
unsigned i, found = 0;
|
||||
if (e->acct_info.groupname[0] == 0 && req_group != NULL &&
|
||||
e->vhost->perm_config.config->cert_group_oid != NULL) {
|
||||
unsigned int i, found = 0;
|
||||
|
||||
for (i=0;i<e->cert_group_names_size;i++) {
|
||||
if (strcmp(req_group, e->cert_group_names[i]) == 0) {
|
||||
strlcpy(e->acct_info.groupname, e->cert_group_names[i], sizeof(e->acct_info.groupname));
|
||||
for (i = 0; i < e->cert_group_names_size; i++) {
|
||||
if (strcmp(req_group, e->cert_group_names[i]) ==
|
||||
0) {
|
||||
strlcpy(e->acct_info.groupname,
|
||||
e->cert_group_names[i],
|
||||
sizeof(e->acct_info.groupname));
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
seclog(sec, LOG_NOTICE, "user '%s' requested group '%s' but is not included on his certificate groups",
|
||||
e->acct_info.username, req_group);
|
||||
seclog(sec, LOG_NOTICE,
|
||||
"user '%s' requested group '%s' but is not included on his certificate groups",
|
||||
e->acct_info.username, req_group);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret =
|
||||
check_cert_user_group_status(sec, e);
|
||||
ret = check_cert_user_group_status(sec, e);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -320,8 +355,8 @@ int check_group(sec_mod_st * sec, client_entry_st * e)
|
||||
* @cmd: the command received
|
||||
* @result: the auth result
|
||||
*/
|
||||
static
|
||||
int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int result)
|
||||
static int handle_sec_auth_res(int cfd, sec_mod_st *sec, client_entry_st *e,
|
||||
int result)
|
||||
{
|
||||
int ret;
|
||||
passwd_msg_st pst;
|
||||
@@ -344,8 +379,12 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
|
||||
|
||||
if (result == ERR_AUTH_CONTINUE) {
|
||||
/* if the module allows multiple retries for the password and the password refers to the same stage */
|
||||
if (e->status != PS_AUTH_INIT && e->module && e->module->allows_retries && passwd_retries == 1) {
|
||||
sec_mod_add_score_to_ip(sec, e, e->acct_info.remote_ip, e->vhost->perm_config.config->ban_points_wrong_password);
|
||||
if (e->status != PS_AUTH_INIT && e->module &&
|
||||
e->module->allows_retries && passwd_retries == 1) {
|
||||
sec_mod_add_score_to_ip(
|
||||
sec, e, e->acct_info.remote_ip,
|
||||
e->vhost->perm_config.config
|
||||
->ban_points_wrong_password);
|
||||
}
|
||||
|
||||
ret = send_sec_auth_reply_msg(cfd, sec, e);
|
||||
@@ -354,7 +393,7 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
|
||||
seclog(sec, LOG_ERR, "could not send reply auth cmd.");
|
||||
return ret;
|
||||
}
|
||||
return 0; /* wait for another command */
|
||||
return 0; /* wait for another command */
|
||||
} else if (result == 0 && e->status != PS_AUTH_FAILED) {
|
||||
/* we checked status for PS_AUTH_FAILED, because status may
|
||||
* change async if we receive a message from main that the
|
||||
@@ -374,9 +413,13 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
|
||||
sizeof(e->acct_info.username));
|
||||
}
|
||||
|
||||
seclog(sec, LOG_DEBUG, "auth complete %sfor user '%s' "SESSION_STR" of group: '%s'",
|
||||
(e->auth_type & AUTH_TYPE_CERTIFICATE)?"(with cert)":"",
|
||||
e->acct_info.username, e->acct_info.safe_id, e->acct_info.groupname);
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"auth complete %sfor user '%s' " SESSION_STR
|
||||
" of group: '%s'",
|
||||
(e->auth_type & AUTH_TYPE_CERTIFICATE) ? "(with cert)" :
|
||||
"",
|
||||
e->acct_info.username, e->acct_info.safe_id,
|
||||
e->acct_info.groupname);
|
||||
|
||||
ret = send_sec_auth_reply(cfd, sec, e, AUTH__REP__OK);
|
||||
if (ret < 0) {
|
||||
@@ -389,7 +432,9 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
|
||||
} else {
|
||||
e->status = PS_AUTH_FAILED;
|
||||
|
||||
sec_mod_add_score_to_ip(sec, e, e->acct_info.remote_ip, e->vhost->perm_config.config->ban_points_wrong_password);
|
||||
sec_mod_add_score_to_ip(
|
||||
sec, e, e->acct_info.remote_ip,
|
||||
e->vhost->perm_config.config->ban_points_wrong_password);
|
||||
|
||||
ret = send_sec_auth_reply(cfd, sec, e, AUTH__REP__FAILED);
|
||||
if (ret < 0) {
|
||||
@@ -400,7 +445,8 @@ int handle_sec_auth_res(int cfd, sec_mod_st * sec, client_entry_st * e, int resu
|
||||
if (result < 0) {
|
||||
ret = result;
|
||||
} else {
|
||||
seclog(sec, LOG_ERR, "unexpected auth result: %d\n", result);
|
||||
seclog(sec, LOG_ERR, "unexpected auth result: %d\n",
|
||||
result);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
}
|
||||
}
|
||||
@@ -415,8 +461,7 @@ static void stats_add_to(stats_st *dst, stats_st *src1, stats_st *src2)
|
||||
dst->uptime = src1->uptime + src2->uptime;
|
||||
}
|
||||
|
||||
static
|
||||
int send_failed_session_open_reply(sec_mod_st *sec, int fd)
|
||||
static int send_failed_session_open_reply(sec_mod_st *sec, int fd)
|
||||
{
|
||||
SecmSessionReplyMsg rep = SECM_SESSION_REPLY_MSG__INIT;
|
||||
void *lpool;
|
||||
@@ -430,8 +475,8 @@ int send_failed_session_open_reply(sec_mod_st *sec, int fd)
|
||||
}
|
||||
|
||||
ret = send_msg(lpool, fd, CMD_SECM_SESSION_REPLY, &rep,
|
||||
(pack_size_func) secm_session_reply_msg__get_packed_size,
|
||||
(pack_func) secm_session_reply_msg__pack);
|
||||
(pack_size_func)secm_session_reply_msg__get_packed_size,
|
||||
(pack_func)secm_session_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_WARNING, "error in sending session reply");
|
||||
ret = ERR_BAD_COMMAND; /* we desynced */
|
||||
@@ -441,7 +486,8 @@ int send_failed_session_open_reply(sec_mod_st *sec, int fd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_secm_session_open_cmd(sec_mod_st *sec, int fd, const SecmSessionOpenMsg *req)
|
||||
int handle_secm_session_open_cmd(sec_mod_st *sec, int fd,
|
||||
const SecmSessionOpenMsg *req)
|
||||
{
|
||||
client_entry_st *e;
|
||||
void *lpool;
|
||||
@@ -452,38 +498,53 @@ int handle_secm_session_open_cmd(sec_mod_st *sec, int fd, const SecmSessionOpenM
|
||||
rep.config = &_cfg;
|
||||
|
||||
if (req->sid.len != SID_SIZE) {
|
||||
seclog(sec, LOG_ERR, "auth session open but with illegal sid size (%d)!",
|
||||
seclog(sec, LOG_ERR,
|
||||
"auth session open but with illegal sid size (%d)!",
|
||||
(int)req->sid.len);
|
||||
return send_failed_session_open_reply(sec, fd);
|
||||
}
|
||||
|
||||
e = find_client_entry(sec, req->sid.data);
|
||||
if (e == NULL) {
|
||||
seclog(sec, LOG_INFO, "session open but with non-existing SID!");
|
||||
seclog(sec, LOG_INFO,
|
||||
"session open but with non-existing SID!");
|
||||
return send_failed_session_open_reply(sec, fd);
|
||||
}
|
||||
|
||||
if (e->status != PS_AUTH_COMPLETED) {
|
||||
seclog(sec, LOG_ERR, "session open received in unauthenticated client %s "SESSION_STR"!", e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_ERR,
|
||||
"session open received in unauthenticated client %s " SESSION_STR
|
||||
"!",
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
return send_failed_session_open_reply(sec, fd);
|
||||
}
|
||||
|
||||
if IS_CLIENT_ENTRY_EXPIRED(sec, e, time(NULL)) {
|
||||
seclog(sec, LOG_ERR, "session expired; denied session for user '%s' "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
|
||||
if IS_CLIENT_ENTRY_EXPIRED (sec, e, time(NULL)) {
|
||||
seclog(sec, LOG_ERR,
|
||||
"session expired; denied session for user '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
e->status = PS_AUTH_FAILED;
|
||||
return send_failed_session_open_reply(sec, fd);
|
||||
}
|
||||
|
||||
if (req->ipv4)
|
||||
strlcpy(e->acct_info.ipv4, req->ipv4, sizeof(e->acct_info.ipv4));
|
||||
strlcpy(e->acct_info.ipv4, req->ipv4,
|
||||
sizeof(e->acct_info.ipv4));
|
||||
if (req->ipv6)
|
||||
strlcpy(e->acct_info.ipv6, req->ipv6, sizeof(e->acct_info.ipv6));
|
||||
strlcpy(e->acct_info.ipv6, req->ipv6,
|
||||
sizeof(e->acct_info.ipv6));
|
||||
|
||||
if (e->vhost->perm_config.acct.amod != NULL && e->vhost->perm_config.acct.amod->open_session != NULL && e->session_is_open == 0) {
|
||||
ret = e->vhost->perm_config.acct.amod->open_session(e->vhost_acct_ctx, e->auth_type, &e->acct_info, req->sid.data, req->sid.len);
|
||||
if (e->vhost->perm_config.acct.amod != NULL &&
|
||||
e->vhost->perm_config.acct.amod->open_session != NULL &&
|
||||
e->session_is_open == 0) {
|
||||
ret = e->vhost->perm_config.acct.amod->open_session(
|
||||
e->vhost_acct_ctx, e->auth_type, &e->acct_info,
|
||||
req->sid.data, req->sid.len);
|
||||
if (ret < 0) {
|
||||
e->status = PS_AUTH_FAILED;
|
||||
seclog(sec, LOG_INFO, "denied session for user '%s' "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_INFO,
|
||||
"denied session for user '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
return send_failed_session_open_reply(sec, fd);
|
||||
}
|
||||
}
|
||||
@@ -500,9 +561,11 @@ int handle_secm_session_open_cmd(sec_mod_st *sec, int fd, const SecmSessionOpenM
|
||||
|
||||
/* Fixme: possibly we should allow for completely random seeds */
|
||||
if (e->vhost->perm_config.config->predictable_ips != 0) {
|
||||
rep.ipv4_seed = hash_any(e->acct_info.username, strlen(e->acct_info.username), 0);
|
||||
rep.ipv4_seed = hash_any(e->acct_info.username,
|
||||
strlen(e->acct_info.username), 0);
|
||||
} else {
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, &rep.ipv4_seed, sizeof(rep.ipv4_seed));
|
||||
ret = gnutls_rnd(GNUTLS_RND_NONCE, &rep.ipv4_seed,
|
||||
sizeof(rep.ipv4_seed));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
}
|
||||
@@ -517,68 +580,80 @@ int handle_secm_session_open_cmd(sec_mod_st *sec, int fd, const SecmSessionOpenM
|
||||
return ERR_BAD_COMMAND; /* we desync */
|
||||
}
|
||||
|
||||
if (e->vhost->config_module && e->vhost->config_module->get_sup_config) {
|
||||
ret = e->vhost->config_module->get_sup_config(e->vhost->perm_config.config, e, &rep, lpool);
|
||||
if (e->vhost->config_module &&
|
||||
e->vhost->config_module->get_sup_config) {
|
||||
ret = e->vhost->config_module->get_sup_config(
|
||||
e->vhost->perm_config.config, e, &rep, lpool);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "error reading additional configuration for '%s' "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_ERR,
|
||||
"error reading additional configuration for '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
talloc_free(lpool);
|
||||
return send_failed_session_open_reply(sec, fd);
|
||||
}
|
||||
}
|
||||
|
||||
ret = send_msg(lpool, fd, CMD_SECM_SESSION_REPLY, &rep,
|
||||
(pack_size_func) secm_session_reply_msg__get_packed_size,
|
||||
(pack_func) secm_session_reply_msg__pack);
|
||||
(pack_size_func)secm_session_reply_msg__get_packed_size,
|
||||
(pack_func)secm_session_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "error in sending session reply");
|
||||
return ERR_BAD_COMMAND; /* we desync */
|
||||
}
|
||||
talloc_free(lpool);
|
||||
|
||||
seclog(sec, LOG_INFO, "%sinitiating session for user '%s' "SESSION_STR, PREFIX_VHOST(e->vhost), e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_INFO, "%sinitiating session for user '%s' " SESSION_STR,
|
||||
PREFIX_VHOST(e->vhost), e->acct_info.username,
|
||||
e->acct_info.safe_id);
|
||||
/* refresh cookie validity */
|
||||
e->exptime = time(NULL) + e->vhost->perm_config.config->cookie_timeout + AUTH_SLACK_TIME;
|
||||
e->exptime = time(NULL) + e->vhost->perm_config.config->cookie_timeout +
|
||||
AUTH_SLACK_TIME;
|
||||
e->in_use++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_secm_session_close_cmd(sec_mod_st *sec, int fd, const SecmSessionCloseMsg *req)
|
||||
int handle_secm_session_close_cmd(sec_mod_st *sec, int fd,
|
||||
const SecmSessionCloseMsg *req)
|
||||
{
|
||||
client_entry_st *e;
|
||||
int ret;
|
||||
CliStatsMsg rep = CLI_STATS_MSG__INIT;
|
||||
|
||||
if (req->sid.len != SID_SIZE) {
|
||||
seclog(sec, LOG_ERR, "auth session close but with illegal sid size (%d)!",
|
||||
seclog(sec, LOG_ERR,
|
||||
"auth session close but with illegal sid size (%d)!",
|
||||
(int)req->sid.len);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
e = find_client_entry(sec, req->sid.data);
|
||||
if (e == NULL) {
|
||||
seclog(sec, LOG_INFO, "session close but with non-existing SID");
|
||||
seclog(sec, LOG_INFO,
|
||||
"session close but with non-existing SID");
|
||||
return send_msg(sec, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
(pack_size_func) cli_stats_msg__get_packed_size,
|
||||
(pack_func) cli_stats_msg__pack);
|
||||
(pack_size_func)cli_stats_msg__get_packed_size,
|
||||
(pack_func)cli_stats_msg__pack);
|
||||
}
|
||||
|
||||
if (e->status < PS_AUTH_COMPLETED) {
|
||||
seclog(sec, LOG_DEBUG, "session close received in unauthenticated client %s "SESSION_STR"!", e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"session close received in unauthenticated client %s " SESSION_STR
|
||||
"!",
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
return send_msg(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
(pack_size_func) cli_stats_msg__get_packed_size,
|
||||
(pack_func) cli_stats_msg__pack);
|
||||
(pack_size_func)cli_stats_msg__get_packed_size,
|
||||
(pack_func)cli_stats_msg__pack);
|
||||
}
|
||||
|
||||
|
||||
if (req->has_uptime && req->uptime > e->stats.uptime) {
|
||||
e->stats.uptime = req->uptime;
|
||||
e->stats.uptime = req->uptime;
|
||||
}
|
||||
if (req->has_bytes_in && req->bytes_in > e->stats.bytes_in) {
|
||||
e->stats.bytes_in = req->bytes_in;
|
||||
e->stats.bytes_in = req->bytes_in;
|
||||
}
|
||||
if (req->has_bytes_out && req->bytes_out > e->stats.bytes_out) {
|
||||
e->stats.bytes_out = req->bytes_out;
|
||||
e->stats.bytes_out = req->bytes_out;
|
||||
}
|
||||
|
||||
if (req->server_disconnected) {
|
||||
@@ -592,8 +667,8 @@ int handle_secm_session_close_cmd(sec_mod_st *sec, int fd, const SecmSessionClos
|
||||
rep.discon_reason = e->discon_reason;
|
||||
|
||||
ret = send_msg(e, fd, CMD_SECM_CLI_STATS, &rep,
|
||||
(pack_size_func) cli_stats_msg__get_packed_size,
|
||||
(pack_func) cli_stats_msg__pack);
|
||||
(pack_size_func)cli_stats_msg__get_packed_size,
|
||||
(pack_func)cli_stats_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "error in sending session stats");
|
||||
return ERR_BAD_COMMAND;
|
||||
@@ -612,7 +687,8 @@ void handle_sec_auth_ban_ip_reply(sec_mod_st *sec, const BanIpReplyMsg *msg)
|
||||
client_entry_st *e;
|
||||
|
||||
if (msg->sid.len != SID_SIZE) {
|
||||
seclog(sec, LOG_ERR, "ban IP reply but with illegal sid size (%d)!",
|
||||
seclog(sec, LOG_ERR,
|
||||
"ban IP reply but with illegal sid size (%d)!",
|
||||
(int)msg->sid.len);
|
||||
return;
|
||||
}
|
||||
@@ -627,25 +703,31 @@ void handle_sec_auth_ban_ip_reply(sec_mod_st *sec, const BanIpReplyMsg *msg)
|
||||
}
|
||||
}
|
||||
|
||||
int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req, pid_t pid)
|
||||
int handle_sec_auth_stats_cmd(sec_mod_st *sec, const CliStatsMsg *req,
|
||||
pid_t pid)
|
||||
{
|
||||
client_entry_st *e;
|
||||
stats_st totals;
|
||||
|
||||
if (req->sid.len != SID_SIZE) {
|
||||
seclog(sec, LOG_ERR, "auth session stats but with illegal sid size (%d)!",
|
||||
seclog(sec, LOG_ERR,
|
||||
"auth session stats but with illegal sid size (%d)!",
|
||||
(int)req->sid.len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = find_client_entry(sec, req->sid.data);
|
||||
if (e == NULL) {
|
||||
seclog(sec, LOG_INFO, "session stats but with non-existing SID");
|
||||
seclog(sec, LOG_INFO,
|
||||
"session stats but with non-existing SID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->status != PS_AUTH_COMPLETED) {
|
||||
seclog(sec, LOG_ERR, "session stats received in unauthenticated client %s "SESSION_STR"!", e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_ERR,
|
||||
"session stats received in unauthenticated client %s " SESSION_STR
|
||||
"!",
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -664,29 +746,35 @@ int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req, pid_t p
|
||||
/* update PID */
|
||||
e->acct_info.id = pid;
|
||||
|
||||
if (e->vhost->perm_config.acct.amod == NULL || e->vhost->perm_config.acct.amod->session_stats == NULL)
|
||||
if (e->vhost->perm_config.acct.amod == NULL ||
|
||||
e->vhost->perm_config.acct.amod->session_stats == NULL)
|
||||
return 0;
|
||||
|
||||
stats_add_to(&totals, &e->stats, &e->saved_stats);
|
||||
if (req->remote_ip)
|
||||
strlcpy(e->acct_info.remote_ip, req->remote_ip, sizeof(e->acct_info.remote_ip));
|
||||
strlcpy(e->acct_info.remote_ip, req->remote_ip,
|
||||
sizeof(e->acct_info.remote_ip));
|
||||
if (req->ipv4)
|
||||
strlcpy(e->acct_info.ipv4, req->ipv4, sizeof(e->acct_info.ipv4));
|
||||
strlcpy(e->acct_info.ipv4, req->ipv4,
|
||||
sizeof(e->acct_info.ipv4));
|
||||
if (req->ipv6)
|
||||
strlcpy(e->acct_info.ipv6, req->ipv6, sizeof(e->acct_info.ipv6));
|
||||
strlcpy(e->acct_info.ipv6, req->ipv6,
|
||||
sizeof(e->acct_info.ipv6));
|
||||
|
||||
e->vhost->perm_config.acct.amod->session_stats(e->vhost_acct_ctx, e->auth_type, &e->acct_info, &totals);
|
||||
e->vhost->perm_config.acct.amod->session_stats(
|
||||
e->vhost_acct_ctx, e->auth_type, &e->acct_info, &totals);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_sec_auth_cont(int cfd, sec_mod_st * sec, const SecAuthContMsg * req)
|
||||
int handle_sec_auth_cont(int cfd, sec_mod_st *sec, const SecAuthContMsg *req)
|
||||
{
|
||||
client_entry_st *e;
|
||||
int ret;
|
||||
|
||||
if (req->sid.len != SID_SIZE) {
|
||||
seclog(sec, LOG_ERR, "auth cont but with illegal sid size (%d)!",
|
||||
seclog(sec, LOG_ERR,
|
||||
"auth cont but with illegal sid size (%d)!",
|
||||
(int)req->sid.len);
|
||||
return -1;
|
||||
}
|
||||
@@ -698,17 +786,22 @@ int handle_sec_auth_cont(int cfd, sec_mod_st * sec, const SecAuthContMsg * req)
|
||||
}
|
||||
|
||||
if (e->status != PS_AUTH_INIT && e->status != PS_AUTH_CONT) {
|
||||
seclog(sec, LOG_ERR, "auth cont received for %s "SESSION_STR" but we are on state %s(%u)!",
|
||||
e->acct_info.username, e->acct_info.safe_id, ps_status_to_str(e->status, 0), e->status);
|
||||
seclog(sec, LOG_ERR,
|
||||
"auth cont received for %s " SESSION_STR
|
||||
" but we are on state %s(%u)!",
|
||||
e->acct_info.username, e->acct_info.safe_id,
|
||||
ps_status_to_str(e->status, 0), e->status);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
seclog(sec, LOG_DEBUG, "auth cont for user '%s' "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_DEBUG, "auth cont for user '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
|
||||
if (req->password == NULL) {
|
||||
seclog(sec, LOG_ERR, "no password given in auth cont for user '%s' "SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_ERR,
|
||||
"no password given in auth cont for user '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -721,40 +814,45 @@ int handle_sec_auth_cont(int cfd, sec_mod_st * sec, const SecAuthContMsg * req)
|
||||
|
||||
e->status = PS_AUTH_CONT;
|
||||
|
||||
ret =
|
||||
e->module->auth_pass(e->auth_ctx, req->password,
|
||||
strlen(req->password));
|
||||
ret = e->module->auth_pass(e->auth_ctx, req->password,
|
||||
strlen(req->password));
|
||||
if (ret < 0) {
|
||||
if (ret != ERR_AUTH_CONTINUE) {
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"error in password given in auth cont for user '%s' "SESSION_STR,
|
||||
"error in password given in auth cont for user '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
return handle_sec_auth_res(cfd, sec, e, ret);
|
||||
}
|
||||
|
||||
static
|
||||
int set_module(sec_mod_st * sec, vhost_cfg_st *vhost, client_entry_st *e, unsigned auth_type)
|
||||
static int set_module(sec_mod_st *sec, vhost_cfg_st *vhost, client_entry_st *e,
|
||||
unsigned int auth_type)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
if (auth_type == 0)
|
||||
return -1;
|
||||
|
||||
/* Find the first configured authentication method which contains
|
||||
* the method asked by the worker, and use that. */
|
||||
for (i=0;i<vhost->perm_config.auth_methods;i++) {
|
||||
if (vhost->perm_config.auth[i].enabled && (vhost->perm_config.auth[i].type & auth_type) == auth_type) {
|
||||
for (i = 0; i < vhost->perm_config.auth_methods; i++) {
|
||||
if (vhost->perm_config.auth[i].enabled &&
|
||||
(vhost->perm_config.auth[i].type & auth_type) ==
|
||||
auth_type) {
|
||||
e->module = vhost->perm_config.auth[i].amod;
|
||||
e->auth_type = vhost->perm_config.auth[i].type;
|
||||
e->vhost_auth_ctx = vhost->perm_config.auth[i].auth_ctx;
|
||||
e->vhost_acct_ctx = vhost->perm_config.acct.acct_ctx;
|
||||
|
||||
seclog(sec, LOG_INFO, "%susing '%s' authentication to authenticate user "SESSION_STR, PREFIX_VHOST(vhost), vhost->perm_config.auth[i].name, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_INFO,
|
||||
"%susing '%s' authentication to authenticate user " SESSION_STR,
|
||||
PREFIX_VHOST(vhost),
|
||||
vhost->perm_config.auth[i].name,
|
||||
e->acct_info.safe_id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -762,12 +860,13 @@ int set_module(sec_mod_st * sec, vhost_cfg_st *vhost, client_entry_st *e, unsign
|
||||
return -1;
|
||||
}
|
||||
|
||||
int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pid_t pid)
|
||||
int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req,
|
||||
pid_t pid)
|
||||
{
|
||||
int ret = -1;
|
||||
client_entry_st *e;
|
||||
unsigned i;
|
||||
unsigned need_continue = 0;
|
||||
unsigned int i;
|
||||
unsigned int need_continue = 0;
|
||||
vhost_cfg_st *vhost;
|
||||
hmac_component_st hmac_components[3];
|
||||
uint8_t computed_hmac[HMAC_DIGEST_SIZE];
|
||||
@@ -780,27 +879,33 @@ int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pi
|
||||
}
|
||||
|
||||
/* Authenticate the client parameters */
|
||||
session_start_time = (time_t)req->session_start_time; // avoid time_t size problem
|
||||
session_start_time =
|
||||
(time_t)req->session_start_time; // avoid time_t size problem
|
||||
|
||||
hmac_components[0].data = req->orig_remote_ip;
|
||||
hmac_components[0].data = req->orig_remote_ip;
|
||||
// req->ip is required and protobuf doesn't permit null for required parameters
|
||||
hmac_components[0].length = strlen(req->orig_remote_ip);
|
||||
hmac_components[1].data = req->our_ip;
|
||||
hmac_components[1].length = req->our_ip ? strlen(req->our_ip) : 0;
|
||||
hmac_components[2].data = (void*)&session_start_time;
|
||||
hmac_components[2].data = (void *)&session_start_time;
|
||||
hmac_components[2].length = sizeof(session_start_time);
|
||||
|
||||
generate_hmac(sizeof(sec->hmac_key), sec->hmac_key, ARRAY_SIZE(hmac_components), hmac_components, computed_hmac);
|
||||
generate_hmac(sizeof(sec->hmac_key), sec->hmac_key,
|
||||
ARRAY_SIZE(hmac_components), hmac_components,
|
||||
computed_hmac);
|
||||
|
||||
if (memcmp(computed_hmac, req->hmac.data, req->hmac.len) != 0) {
|
||||
seclog(sec, LOG_NOTICE, "hmac presented by client doesn't match parameters provided - possible replay");
|
||||
seclog(sec, LOG_NOTICE,
|
||||
"hmac presented by client doesn't match parameters provided - possible replay");
|
||||
return -1;
|
||||
}
|
||||
|
||||
vhost = find_vhost(sec->vconfig, req->vhost);
|
||||
|
||||
if ((now - session_start_time) > vhost->perm_config.config->auth_timeout) {
|
||||
seclog(sec, LOG_NOTICE, "hmac presented by client expired - possible replay");
|
||||
if ((now - session_start_time) >
|
||||
vhost->perm_config.config->auth_timeout) {
|
||||
seclog(sec, LOG_NOTICE,
|
||||
"hmac presented by client expired - possible replay");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -812,7 +917,8 @@ int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pi
|
||||
|
||||
ret = set_module(sec, vhost, e, req->auth_type);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "no module found for auth type %u", (unsigned)req->auth_type);
|
||||
seclog(sec, LOG_ERR, "no module found for auth type %u",
|
||||
(unsigned int)req->auth_type);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -825,8 +931,8 @@ int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pi
|
||||
st.user_agent = req->user_agent;
|
||||
st.id = pid;
|
||||
|
||||
ret =
|
||||
e->module->auth_init(&e->auth_ctx, e, e->vhost_auth_ctx, &st);
|
||||
ret = e->module->auth_init(&e->auth_ctx, e, e->vhost_auth_ctx,
|
||||
&st);
|
||||
if (ret == ERR_AUTH_CONTINUE) {
|
||||
need_continue = 1;
|
||||
} else if (ret < 0) {
|
||||
@@ -837,38 +943,46 @@ int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pi
|
||||
e->tls_auth_ok = req->tls_auth_ok;
|
||||
|
||||
if (req->device_platform != NULL) {
|
||||
strlcpy(e->acct_info.device_platform, req->device_platform, sizeof(e->acct_info.device_platform));
|
||||
strlcpy(e->acct_info.device_platform, req->device_platform,
|
||||
sizeof(e->acct_info.device_platform));
|
||||
}
|
||||
|
||||
if (req->device_type != NULL) {
|
||||
strlcpy(e->acct_info.device_type, req->device_type, sizeof(e->acct_info.device_type));
|
||||
strlcpy(e->acct_info.device_type, req->device_type,
|
||||
sizeof(e->acct_info.device_type));
|
||||
}
|
||||
|
||||
if (req->user_agent != NULL)
|
||||
strlcpy(e->acct_info.user_agent, req->user_agent, sizeof(e->acct_info.user_agent));
|
||||
strlcpy(e->acct_info.user_agent, req->user_agent,
|
||||
sizeof(e->acct_info.user_agent));
|
||||
|
||||
// Real user name is retrieved after auth.
|
||||
if (!(req->auth_type & CONFIDENTIAL_USER_NAME_AUTH_TYPES)) {
|
||||
if (req->user_name != NULL) {
|
||||
strlcpy(e->acct_info.username, req->user_name, sizeof(e->acct_info.username));
|
||||
strlcpy(e->acct_info.username, req->user_name,
|
||||
sizeof(e->acct_info.username));
|
||||
}
|
||||
}
|
||||
|
||||
if (req->our_ip != NULL) {
|
||||
strlcpy(e->acct_info.our_ip, req->our_ip, sizeof(e->acct_info.our_ip));
|
||||
strlcpy(e->acct_info.our_ip, req->our_ip,
|
||||
sizeof(e->acct_info.our_ip));
|
||||
}
|
||||
|
||||
if (req->group_name != NULL) {
|
||||
strlcpy(e->req_group_name, req->group_name, sizeof(e->req_group_name));
|
||||
strlcpy(e->req_group_name, req->group_name,
|
||||
sizeof(e->req_group_name));
|
||||
}
|
||||
|
||||
if (req->cert_user_name != NULL) {
|
||||
strlcpy(e->cert_user_name, req->cert_user_name, sizeof(e->cert_user_name));
|
||||
strlcpy(e->cert_user_name, req->cert_user_name,
|
||||
sizeof(e->cert_user_name));
|
||||
}
|
||||
|
||||
e->cert_group_names_size = MIN(MAX_GROUPS,req->n_cert_group_names);
|
||||
for (i=0;i<e->cert_group_names_size;i++) {
|
||||
e->cert_group_names[i] = talloc_strdup(e, req->cert_group_names[i]);
|
||||
e->cert_group_names_size = MIN(MAX_GROUPS, req->n_cert_group_names);
|
||||
for (i = 0; i < e->cert_group_names_size; i++) {
|
||||
e->cert_group_names[i] =
|
||||
talloc_strdup(e, req->cert_group_names[i]);
|
||||
if (e->cert_group_names[i] == NULL) {
|
||||
e->cert_group_names_size = 0;
|
||||
break;
|
||||
@@ -876,9 +990,11 @@ int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pi
|
||||
}
|
||||
|
||||
e->status = PS_AUTH_INIT;
|
||||
seclog(sec, LOG_DEBUG, "auth init %sfor user '%s' "SESSION_STR" of group: '%s' from '%s'",
|
||||
req->tls_auth_ok?"(with cert) ":"",
|
||||
e->acct_info.username, e->acct_info.safe_id, e->acct_info.groupname, req->remote_ip);
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"auth init %sfor user '%s' " SESSION_STR
|
||||
" of group: '%s' from '%s'",
|
||||
req->tls_auth_ok ? "(with cert) " : "", e->acct_info.username,
|
||||
e->acct_info.safe_id, e->acct_info.groupname, req->remote_ip);
|
||||
|
||||
if (need_continue != 0) {
|
||||
ret = ERR_AUTH_CONTINUE;
|
||||
@@ -886,7 +1002,7 @@ int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req, pi
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
cleanup:
|
||||
return handle_sec_auth_res(cfd, sec, e, ret);
|
||||
}
|
||||
|
||||
@@ -896,9 +1012,15 @@ void sec_auth_user_deinit(sec_mod_st *sec, client_entry_st *e)
|
||||
|
||||
vhost = e->vhost;
|
||||
|
||||
seclog(sec, LOG_DEBUG, "permanently closing session of user '%s' "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
|
||||
if (vhost->perm_config.acct.amod != NULL && vhost->perm_config.acct.amod->close_session != NULL && e->session_is_open != 0) {
|
||||
vhost->perm_config.acct.amod->close_session(e->vhost_acct_ctx, e->auth_type, &e->acct_info, &e->saved_stats, e->discon_reason);
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"permanently closing session of user '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
if (vhost->perm_config.acct.amod != NULL &&
|
||||
vhost->perm_config.acct.amod->close_session != NULL &&
|
||||
e->session_is_open != 0) {
|
||||
vhost->perm_config.acct.amod->close_session(
|
||||
e->vhost_acct_ctx, e->auth_type, &e->acct_info,
|
||||
&e->saved_stats, e->discon_reason);
|
||||
}
|
||||
|
||||
if (e->auth_ctx != NULL) {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_SEC_MOD_AUTH_H
|
||||
# define OC_SEC_MOD_AUTH_H
|
||||
#define OC_SEC_MOD_AUTH_H
|
||||
|
||||
#include <main.h>
|
||||
#include <sec-mod.h>
|
||||
@@ -28,26 +28,30 @@
|
||||
|
||||
typedef struct passwd_msg_st {
|
||||
char *msg_str;
|
||||
unsigned counter;
|
||||
unsigned int counter;
|
||||
} passwd_msg_st;
|
||||
|
||||
typedef struct auth_mod_st {
|
||||
unsigned int type;
|
||||
unsigned int allows_retries; /* whether the module allows retries of the same password */
|
||||
void (*vhost_init)(void **vctx, void *pool, void* additional);
|
||||
unsigned int
|
||||
allows_retries; /* whether the module allows retries of the same password */
|
||||
void (*vhost_init)(void **vctx, void *pool, void *additional);
|
||||
void (*vhost_deinit)(void *vctx);
|
||||
int (*auth_init)(void **ctx, void *pool, void *vctx, 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);
|
||||
int (*auth_user)(void* ctx, char *groupname, int groupname_size);
|
||||
int (*auth_init)(void **ctx, void *pool, void *vctx,
|
||||
const common_auth_init_st *);
|
||||
int (*auth_msg)(void *ctx, void *pool, passwd_msg_st *);
|
||||
int (*auth_pass)(void *ctx, const char *pass, unsigned int pass_len);
|
||||
int (*auth_group)(void *ctx, const char *suggested, char *groupname,
|
||||
int groupname_size);
|
||||
int (*auth_user)(void *ctx, char *groupname, int groupname_size);
|
||||
|
||||
void (*auth_deinit)(void* ctx);
|
||||
void (*group_list)(void *pool, void *additional, char ***groupname, unsigned *groupname_size);
|
||||
void (*auth_deinit)(void *ctx);
|
||||
void (*group_list)(void *pool, void *additional, char ***groupname,
|
||||
unsigned int *groupname_size);
|
||||
} auth_mod_st;
|
||||
|
||||
void main_auth_init(main_server_st *s);
|
||||
void proc_auth_deinit(main_server_st* s, struct proc_st* proc);
|
||||
void proc_auth_deinit(main_server_st *s, struct proc_st *proc);
|
||||
|
||||
/* The authentication with the worker thread is shown in ipc.proto.
|
||||
*/
|
||||
|
||||
@@ -32,11 +32,13 @@ static void send_empty_reply(void *pool, int fd, sec_mod_st *sec)
|
||||
SecmListCookiesReplyMsg msg = SECM_LIST_COOKIES_REPLY_MSG__INIT;
|
||||
int ret;
|
||||
|
||||
ret = send_msg(pool, fd, CMD_SECM_LIST_COOKIES_REPLY, &msg,
|
||||
(pack_size_func) secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func) secm_list_cookies_reply_msg__pack);
|
||||
ret = send_msg(
|
||||
pool, fd, CMD_SECM_LIST_COOKIES_REPLY, &msg,
|
||||
(pack_size_func)secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func)secm_list_cookies_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "Error sending empty show cookies reply to main");
|
||||
seclog(sec, LOG_ERR,
|
||||
"Error sending empty show cookies reply to main");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,13 +59,13 @@ void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec)
|
||||
|
||||
seclog(sec, LOG_DEBUG, "sending list cookies reply to main");
|
||||
|
||||
msg.cookies = talloc_size(pool, sizeof(CookieIntMsg*)*db->elems);
|
||||
msg.cookies = talloc_size(pool, sizeof(CookieIntMsg *) * db->elems);
|
||||
if (msg.cookies == NULL) {
|
||||
send_empty_reply(pool, fd, sec);
|
||||
return;
|
||||
}
|
||||
|
||||
cookies = talloc_size(pool, sizeof(CookieIntMsg)*db->elems);
|
||||
cookies = talloc_size(pool, sizeof(CookieIntMsg) * db->elems);
|
||||
if (cookies == NULL) {
|
||||
send_empty_reply(pool, fd, sec);
|
||||
return;
|
||||
@@ -71,15 +73,17 @@ void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec)
|
||||
|
||||
t = htable_first(db, &iter);
|
||||
while (t != NULL) {
|
||||
if IS_CLIENT_ENTRY_EXPIRED(sec, t, now)
|
||||
if IS_CLIENT_ENTRY_EXPIRED (sec, t, now)
|
||||
goto cont;
|
||||
|
||||
if (msg.n_cookies >= db->elems)
|
||||
break;
|
||||
|
||||
cookie_int_msg__init(&cookies[msg.n_cookies]);
|
||||
cookies[msg.n_cookies].safe_id.data = (void*)t->acct_info.safe_id;
|
||||
cookies[msg.n_cookies].safe_id.len = sizeof(t->acct_info.safe_id);
|
||||
cookies[msg.n_cookies].safe_id.data =
|
||||
(void *)t->acct_info.safe_id;
|
||||
cookies[msg.n_cookies].safe_id.len =
|
||||
sizeof(t->acct_info.safe_id);
|
||||
|
||||
cookies[msg.n_cookies].session_is_open = t->session_is_open;
|
||||
cookies[msg.n_cookies].tls_auth_ok = t->tls_auth_ok;
|
||||
@@ -105,15 +109,17 @@ void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec)
|
||||
msg.cookies[msg.n_cookies] = &cookies[msg.n_cookies];
|
||||
msg.n_cookies++;
|
||||
|
||||
cont:
|
||||
cont:
|
||||
t = htable_next(db, &iter);
|
||||
}
|
||||
|
||||
ret = send_msg(pool, fd, CMD_SECM_LIST_COOKIES_REPLY, &msg,
|
||||
(pack_size_func) secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func) secm_list_cookies_reply_msg__pack);
|
||||
ret = send_msg(
|
||||
pool, fd, CMD_SECM_LIST_COOKIES_REPLY, &msg,
|
||||
(pack_size_func)secm_list_cookies_reply_msg__get_packed_size,
|
||||
(pack_func)secm_list_cookies_reply_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "Error sending show cookies reply to main");
|
||||
seclog(sec, LOG_ERR,
|
||||
"Error sending show cookies reply to main");
|
||||
}
|
||||
|
||||
talloc_free(msg.cookies);
|
||||
|
||||
@@ -57,6 +57,7 @@ static size_t rehash(const void *_e, void *unused)
|
||||
void *sec_mod_client_db_init(sec_mod_st *sec)
|
||||
{
|
||||
struct htable *db = talloc(sec, struct htable);
|
||||
|
||||
if (db == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -68,16 +69,16 @@ void *sec_mod_client_db_init(sec_mod_st *sec)
|
||||
|
||||
void sec_mod_client_db_deinit(sec_mod_st *sec)
|
||||
{
|
||||
struct htable *db = sec->client_db;
|
||||
struct htable *db = sec->client_db;
|
||||
|
||||
htable_clear(db);
|
||||
talloc_free(db);
|
||||
}
|
||||
|
||||
/* The number of elements */
|
||||
unsigned sec_mod_client_db_elems(sec_mod_st *sec)
|
||||
unsigned int sec_mod_client_db_elems(sec_mod_st *sec)
|
||||
{
|
||||
struct htable *db = sec->client_db;
|
||||
struct htable *db = sec->client_db;
|
||||
|
||||
if (db)
|
||||
return db->elems;
|
||||
@@ -85,7 +86,8 @@ struct htable *db = sec->client_db;
|
||||
return 0;
|
||||
}
|
||||
|
||||
client_entry_st *new_client_entry(sec_mod_st *sec, struct vhost_cfg_st *vhost, const char *ip, unsigned pid)
|
||||
client_entry_st *new_client_entry(sec_mod_st *sec, struct vhost_cfg_st *vhost,
|
||||
const char *ip, unsigned int pid)
|
||||
{
|
||||
struct htable *db = sec->client_db;
|
||||
client_entry_st *e, *te;
|
||||
@@ -99,7 +101,8 @@ client_entry_st *new_client_entry(sec_mod_st *sec, struct vhost_cfg_st *vhost, c
|
||||
}
|
||||
|
||||
if (ip)
|
||||
strlcpy(e->acct_info.remote_ip, ip, sizeof(e->acct_info.remote_ip));
|
||||
strlcpy(e->acct_info.remote_ip, ip,
|
||||
sizeof(e->acct_info.remote_ip));
|
||||
e->acct_info.id = pid;
|
||||
e->vhost = vhost;
|
||||
|
||||
@@ -111,21 +114,23 @@ client_entry_st *new_client_entry(sec_mod_st *sec, struct vhost_cfg_st *vhost, c
|
||||
}
|
||||
|
||||
e->sid[0] = sec->sec_mod_instance_id;
|
||||
seclog(sec, LOG_INFO, "sec-mod instance %d issue cookie", sec->sec_mod_instance_id);
|
||||
seclog(sec, LOG_INFO, "sec-mod instance %d issue cookie",
|
||||
sec->sec_mod_instance_id);
|
||||
|
||||
/* check if in use */
|
||||
te = find_client_entry(sec, e->sid);
|
||||
} while (te != NULL && retries-- >= 0);
|
||||
|
||||
if (te != NULL) {
|
||||
seclog(sec, LOG_ERR,
|
||||
"could not generate a unique SID!");
|
||||
seclog(sec, LOG_ERR, "could not generate a unique SID!");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
calc_safe_id(e->sid, SID_SIZE, (char *)e->acct_info.safe_id, sizeof(e->acct_info.safe_id));
|
||||
calc_safe_id(e->sid, SID_SIZE, (char *)e->acct_info.safe_id,
|
||||
sizeof(e->acct_info.safe_id));
|
||||
now = time(NULL);
|
||||
e->exptime = now + vhost->perm_config.config->cookie_timeout + AUTH_SLACK_TIME;
|
||||
e->exptime = now + vhost->perm_config.config->cookie_timeout +
|
||||
AUTH_SLACK_TIME;
|
||||
e->created = now;
|
||||
|
||||
if (htable_add(db, rehash(e, NULL), e) == 0) {
|
||||
@@ -136,7 +141,7 @@ client_entry_st *new_client_entry(sec_mod_st *sec, struct vhost_cfg_st *vhost, c
|
||||
|
||||
return e;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
talloc_free(e);
|
||||
return NULL;
|
||||
}
|
||||
@@ -161,7 +166,7 @@ client_entry_st *find_client_entry(sec_mod_st *sec, uint8_t sid[SID_SIZE])
|
||||
return htable_get(db, rehash(&t, NULL), client_entry_cmp, &t);
|
||||
}
|
||||
|
||||
static void clean_entry(sec_mod_st *sec, client_entry_st * e)
|
||||
static void clean_entry(sec_mod_st *sec, client_entry_st *e)
|
||||
{
|
||||
sec_auth_user_deinit(sec, e);
|
||||
talloc_free(e->msg_str);
|
||||
@@ -177,16 +182,15 @@ void cleanup_client_entries(sec_mod_st *sec)
|
||||
|
||||
t = htable_first(db, &iter);
|
||||
while (t != NULL) {
|
||||
if IS_CLIENT_ENTRY_EXPIRED_FULL(sec, t, now, 1) {
|
||||
if IS_CLIENT_ENTRY_EXPIRED_FULL (sec, t, now, 1) {
|
||||
htable_delval(db, &iter);
|
||||
clean_entry(sec, t);
|
||||
}
|
||||
t = htable_next(db, &iter);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void del_client_entry(sec_mod_st *sec, client_entry_st * e)
|
||||
void del_client_entry(sec_mod_st *sec, client_entry_st *e)
|
||||
{
|
||||
struct htable *db = sec->client_db;
|
||||
|
||||
@@ -194,16 +198,20 @@ void del_client_entry(sec_mod_st *sec, client_entry_st * e)
|
||||
clean_entry(sec, e);
|
||||
}
|
||||
|
||||
void expire_client_entry(sec_mod_st *sec, client_entry_st * e)
|
||||
void expire_client_entry(sec_mod_st *sec, client_entry_st *e)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
if (e->in_use > 0)
|
||||
e->in_use--;
|
||||
if (e->in_use == 0) {
|
||||
if (e->vhost->perm_config.config->persistent_cookies == 0 && (e->discon_reason == REASON_SERVER_DISCONNECT ||
|
||||
e->discon_reason == REASON_SESSION_TIMEOUT || (e->session_is_open && e->discon_reason == REASON_USER_DISCONNECT))) {
|
||||
seclog(sec, LOG_INFO, "invalidating session of user '%s' "SESSION_STR,
|
||||
if (e->vhost->perm_config.config->persistent_cookies == 0 &&
|
||||
(e->discon_reason == REASON_SERVER_DISCONNECT ||
|
||||
e->discon_reason == REASON_SESSION_TIMEOUT ||
|
||||
(e->session_is_open &&
|
||||
e->discon_reason == REASON_USER_DISCONNECT))) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"invalidating session of user '%s' " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
/* immediately disconnect the user */
|
||||
del_client_entry(sec, e);
|
||||
@@ -214,12 +222,19 @@ void expire_client_entry(sec_mod_st *sec, client_entry_st * e)
|
||||
* explicitly disconnect with the intention to reconnect
|
||||
* seconds later. */
|
||||
if (e->discon_reason == REASON_USER_DISCONNECT) {
|
||||
if (!e->vhost->perm_config.config->persistent_cookies || (now+AUTH_SLACK_TIME >= e->exptime))
|
||||
if (!e->vhost->perm_config.config
|
||||
->persistent_cookies ||
|
||||
(now + AUTH_SLACK_TIME >= e->exptime))
|
||||
e->exptime = now + AUTH_SLACK_TIME;
|
||||
} else {
|
||||
e->exptime = now + e->vhost->perm_config.config->cookie_timeout + AUTH_SLACK_TIME;
|
||||
e->exptime = now +
|
||||
e->vhost->perm_config.config
|
||||
->cookie_timeout +
|
||||
AUTH_SLACK_TIME;
|
||||
}
|
||||
seclog(sec, LOG_INFO, "temporarily closing session for %s "SESSION_STR, e->acct_info.username, e->acct_info.safe_id);
|
||||
seclog(sec, LOG_INFO,
|
||||
"temporarily closing session for %s " SESSION_STR,
|
||||
e->acct_info.username, e->acct_info.safe_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
#include <ip-util.h>
|
||||
#include <tlslib.h>
|
||||
|
||||
int handle_resume_delete_req(sec_mod_st *sec,
|
||||
const SessionResumeFetchMsg *req)
|
||||
int handle_resume_delete_req(sec_mod_st *sec, const SessionResumeFetchMsg *req)
|
||||
{
|
||||
tls_cache_st *cache;
|
||||
struct htable_iter iter;
|
||||
@@ -53,7 +52,6 @@ int handle_resume_delete_req(sec_mod_st *sec,
|
||||
if (req->session_id.len == cache->session_id_size &&
|
||||
memcmp(req->session_id.data, cache->session_id,
|
||||
req->session_id.len) == 0) {
|
||||
|
||||
cache->session_data_size = 0;
|
||||
cache->session_id_size = 0;
|
||||
|
||||
@@ -69,8 +67,7 @@ int handle_resume_delete_req(sec_mod_st *sec,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_resume_fetch_req(sec_mod_st *sec,
|
||||
const SessionResumeFetchMsg *req,
|
||||
int handle_resume_fetch_req(sec_mod_st *sec, const SessionResumeFetchMsg *req,
|
||||
SessionResumeReplyMsg *rep)
|
||||
{
|
||||
tls_cache_st *cache;
|
||||
@@ -86,28 +83,29 @@ int handle_resume_fetch_req(sec_mod_st *sec,
|
||||
if (req->session_id.len == cache->session_id_size &&
|
||||
memcmp(req->session_id.data, cache->session_id,
|
||||
req->session_id.len) == 0) {
|
||||
|
||||
if (req->vhost && cache->vhostname && strcasecmp(req->vhost, cache->vhostname) != 0)
|
||||
if (req->vhost && cache->vhostname &&
|
||||
strcasecmp(req->vhost, cache->vhostname) != 0)
|
||||
return 0;
|
||||
else if (req->vhost != cache->vhostname)
|
||||
return 0;
|
||||
|
||||
if (req->cli_addr.len == cache->remote_addr_len &&
|
||||
ip_cmp((struct sockaddr_storage *)req->cli_addr.data, &cache->remote_addr) == 0) {
|
||||
|
||||
ip_cmp((struct sockaddr_storage *)req->cli_addr.data,
|
||||
&cache->remote_addr) == 0) {
|
||||
rep->reply =
|
||||
SESSION_RESUME_REPLY_MSG__RESUME__REP__OK;
|
||||
SESSION_RESUME_REPLY_MSG__RESUME__REP__OK;
|
||||
|
||||
rep->has_session_data = 1;
|
||||
|
||||
rep->session_data.data =
|
||||
(void *)cache->session_data;
|
||||
(void *)cache->session_data;
|
||||
rep->session_data.len =
|
||||
cache->session_data_size;
|
||||
cache->session_data_size;
|
||||
|
||||
seclog_hex(sec, LOG_DEBUG, "TLS session DB resuming",
|
||||
req->session_id.data,
|
||||
req->session_id.len, 0);
|
||||
seclog_hex(sec, LOG_DEBUG,
|
||||
"TLS session DB resuming",
|
||||
req->session_id.data,
|
||||
req->session_id.len, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -117,7 +115,6 @@ int handle_resume_fetch_req(sec_mod_st *sec,
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int handle_resume_store_req(sec_mod_st *sec,
|
||||
@@ -132,17 +129,17 @@ int handle_resume_store_req(sec_mod_st *sec,
|
||||
if (req->session_data.len > MAX_SESSION_DATA_SIZE)
|
||||
return -1;
|
||||
|
||||
max = MAX(2 * GETCONFIG(sec)->max_clients, DEFAULT_MAX_CACHED_TLS_SESSIONS);
|
||||
max = MAX(2 * GETCONFIG(sec)->max_clients,
|
||||
DEFAULT_MAX_CACHED_TLS_SESSIONS);
|
||||
if (sec->tls_db.entries >= max) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"maximum number of stored TLS sessions reached (%u)",
|
||||
max);
|
||||
"maximum number of stored TLS sessions reached (%u)",
|
||||
max);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (req->cli_addr.len == 0) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"invalid address length");
|
||||
seclog(sec, LOG_INFO, "invalid address length");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -167,14 +164,13 @@ int handle_resume_store_req(sec_mod_st *sec,
|
||||
|
||||
if (htable_add(sec->tls_db.ht, key, cache) == 0) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"could not add TLS session to hash table");
|
||||
"could not add TLS session to hash table");
|
||||
talloc_free(cache);
|
||||
} else {
|
||||
sec->tls_db.entries++;
|
||||
|
||||
seclog_hex(sec, LOG_DEBUG, "TLS session DB storing",
|
||||
req->session_id.data,
|
||||
req->session_id.len, 0);
|
||||
req->session_id.data, req->session_id.len, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -202,7 +198,8 @@ void expire_tls_sessions(sec_mod_st *sec)
|
||||
|
||||
htable_delval(sec->tls_db.ht, &iter);
|
||||
|
||||
safe_memset(cache->session_data, 0, cache->session_data_size);
|
||||
safe_memset(cache->session_data, 0,
|
||||
cache->session_data_size);
|
||||
talloc_free(cache);
|
||||
sec->tls_db.entries--;
|
||||
}
|
||||
|
||||
@@ -19,19 +19,16 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_SEC_MOD_RESUME_H
|
||||
# define OC_SEC_MOD_RESUME_H
|
||||
#define OC_SEC_MOD_RESUME_H
|
||||
|
||||
#include <sec-mod.h>
|
||||
|
||||
int handle_resume_delete_req(sec_mod_st* sec,
|
||||
const SessionResumeFetchMsg * req);
|
||||
int handle_resume_delete_req(sec_mod_st *sec, const SessionResumeFetchMsg *req);
|
||||
|
||||
int handle_resume_fetch_req(sec_mod_st* sec,
|
||||
const SessionResumeFetchMsg * req,
|
||||
SessionResumeReplyMsg* rep);
|
||||
int handle_resume_fetch_req(sec_mod_st *sec, const SessionResumeFetchMsg *req,
|
||||
SessionResumeReplyMsg *rep);
|
||||
|
||||
int handle_resume_store_req(sec_mod_st* sec,
|
||||
const SessionResumeStoreReqMsg *);
|
||||
int handle_resume_store_req(sec_mod_st *sec, const SessionResumeStoreReqMsg *);
|
||||
|
||||
void expire_tls_sessions(sec_mod_st *sec);
|
||||
|
||||
|
||||
@@ -34,13 +34,19 @@ void sup_config_init(sec_mod_st *sec)
|
||||
{
|
||||
vhost_cfg_st *vhost = NULL;
|
||||
|
||||
list_for_each(sec->vconfig, vhost, list) {
|
||||
list_for_each(sec->vconfig, vhost, list)
|
||||
{
|
||||
if (vhost->perm_config.sup_config_type == SUP_CONFIG_FILE) {
|
||||
seclog(sec, LOG_INFO, "%sreading supplemental config from files", PREFIX_VHOST(vhost));
|
||||
seclog(sec, LOG_INFO,
|
||||
"%sreading supplemental config from files",
|
||||
PREFIX_VHOST(vhost));
|
||||
vhost->config_module = &file_sup_config;
|
||||
#ifdef HAVE_RADIUS
|
||||
} else if (vhost->perm_config.sup_config_type == SUP_CONFIG_RADIUS) {
|
||||
seclog(sec, LOG_INFO, "%sreading supplemental config from radius", PREFIX_VHOST(vhost));
|
||||
} else if (vhost->perm_config.sup_config_type ==
|
||||
SUP_CONFIG_RADIUS) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"%sreading supplemental config from radius",
|
||||
PREFIX_VHOST(vhost));
|
||||
vhost->config_module = &radius_sup_config;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -19,15 +19,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_SEC_MOD_SUP_CONFIG_H
|
||||
# define OC_SEC_MOD_SUP_CONFIG_H
|
||||
#define OC_SEC_MOD_SUP_CONFIG_H
|
||||
|
||||
#include <sec-mod.h>
|
||||
|
||||
#define SUP_CONFIG_FILE 1
|
||||
#define SUP_CONFIG_RADIUS 2
|
||||
|
||||
inline static
|
||||
const char *sup_config_name(unsigned s)
|
||||
inline static const char *sup_config_name(unsigned int s)
|
||||
{
|
||||
switch (s) {
|
||||
case SUP_CONFIG_FILE:
|
||||
@@ -43,8 +42,9 @@ const char *sup_config_name(unsigned s)
|
||||
* proc->username/proc->groupname and save it in proc->config.
|
||||
*/
|
||||
struct config_mod_st {
|
||||
int (*get_sup_config)(struct cfg_st *perm_config, client_entry_st *entry,
|
||||
SecmSessionReplyMsg *msg, void *pool);
|
||||
int (*get_sup_config)(struct cfg_st *perm_config,
|
||||
client_entry_st *entry, SecmSessionReplyMsg *msg,
|
||||
void *pool);
|
||||
};
|
||||
|
||||
void sup_config_init(sec_mod_st *sec);
|
||||
|
||||
590
src/sec-mod.c
590
src/sec-mod.c
@@ -51,41 +51,41 @@
|
||||
|
||||
#define MAINTAINANCE_TIME 310
|
||||
|
||||
static int need_maintainance = 0;
|
||||
static int need_reload = 0;
|
||||
static int need_exit = 0;
|
||||
static int need_maintainance;
|
||||
static int need_reload;
|
||||
static int need_exit;
|
||||
|
||||
static void reload_server(sec_mod_st *sec);
|
||||
|
||||
static int load_keys(sec_mod_st *sec, unsigned force);
|
||||
static int load_keys(sec_mod_st *sec, unsigned int force);
|
||||
|
||||
static
|
||||
int pin_callback(void *user, int attempt, const char *token_url,
|
||||
const char *token_label, unsigned int flags, char *pin,
|
||||
size_t pin_max)
|
||||
static int pin_callback(void *user, int attempt, const char *token_url,
|
||||
const char *token_label, unsigned int flags, char *pin,
|
||||
size_t pin_max)
|
||||
{
|
||||
struct pin_st *ps = user;
|
||||
int srk = 0;
|
||||
const char *p;
|
||||
unsigned len;
|
||||
unsigned int len;
|
||||
|
||||
if (flags & GNUTLS_PIN_FINAL_TRY) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"PIN callback: final try before locking; not attempting to unlock");
|
||||
oc_syslog(
|
||||
LOG_ERR,
|
||||
"PIN callback: final try before locking; not attempting to unlock");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & GNUTLS_PIN_WRONG) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"PIN callback: wrong PIN was entered for '%s' (%s)",
|
||||
token_label, token_url);
|
||||
"PIN callback: wrong PIN was entered for '%s' (%s)",
|
||||
token_label, token_url);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ps->pin[0] == 0) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"PIN required for '%s' but pin-file was not set",
|
||||
token_label);
|
||||
"PIN required for '%s' but pin-file was not set",
|
||||
token_label);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ int pin_callback(void *user, int attempt, const char *token_url,
|
||||
|
||||
if (srk != 0 && ps->srk_pin[0] == 0) {
|
||||
oc_syslog(LOG_ERR,
|
||||
"PIN required for '%s' but srk-pin-file was not set",
|
||||
token_label);
|
||||
"PIN required for '%s' but srk-pin-file was not set",
|
||||
token_label);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -115,8 +115,7 @@ int pin_callback(void *user, int attempt, const char *token_url,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int load_pins(struct perm_cfg_st *config, struct pin_st *s)
|
||||
static int load_pins(struct perm_cfg_st *config, struct pin_st *s)
|
||||
{
|
||||
int fd, ret;
|
||||
|
||||
@@ -127,7 +126,7 @@ int load_pins(struct perm_cfg_st *config, struct pin_st *s)
|
||||
fd = open(config->srk_pin_file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
oc_syslog(LOG_ERR, "could not open SRK PIN file '%s'",
|
||||
config->srk_pin_file);
|
||||
config->srk_pin_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -135,7 +134,7 @@ int load_pins(struct perm_cfg_st *config, struct pin_st *s)
|
||||
close(fd);
|
||||
if (ret <= 1) {
|
||||
oc_syslog(LOG_ERR, "could not read from PIN file '%s'",
|
||||
config->srk_pin_file);
|
||||
config->srk_pin_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -148,7 +147,7 @@ int load_pins(struct perm_cfg_st *config, struct pin_st *s)
|
||||
fd = open(config->pin_file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
oc_syslog(LOG_ERR, "could not open PIN file '%s'",
|
||||
config->pin_file);
|
||||
config->pin_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -156,7 +155,7 @@ int load_pins(struct perm_cfg_st *config, struct pin_st *s)
|
||||
close(fd);
|
||||
if (ret <= 1) {
|
||||
oc_syslog(LOG_ERR, "could not read from PIN file '%s'",
|
||||
config->pin_file);
|
||||
config->pin_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -176,8 +175,8 @@ int load_pins(struct perm_cfg_st *config, struct pin_st *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_op(void *pool, int cfd, sec_mod_st * sec, uint8_t type, uint8_t * rep,
|
||||
size_t rep_size)
|
||||
static int handle_op(void *pool, int cfd, sec_mod_st *sec, uint8_t type,
|
||||
uint8_t *rep, size_t rep_size)
|
||||
{
|
||||
SecOpMsg msg = SEC_OP_MSG__INIT;
|
||||
int ret;
|
||||
@@ -186,8 +185,8 @@ static int handle_op(void *pool, int cfd, sec_mod_st * sec, uint8_t type, uint8_
|
||||
msg.data.len = rep_size;
|
||||
|
||||
ret = send_msg(pool, cfd, type, &msg,
|
||||
(pack_size_func) sec_op_msg__get_packed_size,
|
||||
(pack_func) sec_op_msg__pack);
|
||||
(pack_size_func)sec_op_msg__get_packed_size,
|
||||
(pack_func)sec_op_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_WARNING, "sec-mod error in sending reply");
|
||||
}
|
||||
@@ -195,17 +194,17 @@ static int handle_op(void *pool, int cfd, sec_mod_st * sec, uint8_t type, uint8_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_request_t cmd,
|
||||
uint8_t * buffer, size_t buffer_size)
|
||||
static int process_worker_packet(void *pool, int cfd, pid_t pid,
|
||||
sec_mod_st *sec, cmd_request_t cmd,
|
||||
uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
gnutls_datum_t data, out;
|
||||
int ret;
|
||||
SecOpMsg *op;
|
||||
vhost_cfg_st *vhost;
|
||||
#if GNUTLS_VERSION_NUMBER >= 0x030600
|
||||
unsigned bits;
|
||||
unsigned int bits;
|
||||
SecGetPkMsg *pkm;
|
||||
#endif
|
||||
PROTOBUF_ALLOCATOR(pa, pool);
|
||||
@@ -231,7 +230,8 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
i = pkm->key_idx;
|
||||
if (i >= vhost->key_size) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"%sreceived out-of-bounds key index (%d); have %d keys", PREFIX_VHOST(vhost), i, vhost->key_size);
|
||||
"%sreceived out-of-bounds key index (%d); have %d keys",
|
||||
PREFIX_VHOST(vhost), i, vhost->key_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -239,8 +239,8 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
pkm->bits = bits;
|
||||
|
||||
ret = send_msg(pool, cfd, CMD_SEC_GET_PK, pkm,
|
||||
(pack_size_func) sec_get_pk_msg__get_packed_size,
|
||||
(pack_func) sec_get_pk_msg__pack);
|
||||
(pack_size_func)sec_get_pk_msg__get_packed_size,
|
||||
(pack_func)sec_get_pk_msg__pack);
|
||||
|
||||
sec_get_pk_msg__free_unpacked(pkm, &pa);
|
||||
|
||||
@@ -266,7 +266,8 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
i = op->key_idx;
|
||||
if (op->has_key_idx == 0 || i >= vhost->key_size) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"%sreceived out-of-bounds key index (%d); have %d keys", PREFIX_VHOST(vhost), i, vhost->key_size);
|
||||
"%sreceived out-of-bounds key index (%d); have %d keys",
|
||||
PREFIX_VHOST(vhost), i, vhost->key_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -274,9 +275,11 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
data.size = op->data.len;
|
||||
|
||||
if (cmd == CMD_SEC_SIGN_DATA) {
|
||||
ret = gnutls_privkey_sign_data2(vhost->key[i], op->sig, 0, &data, &out);
|
||||
ret = gnutls_privkey_sign_data2(vhost->key[i], op->sig,
|
||||
0, &data, &out);
|
||||
} else {
|
||||
ret = gnutls_privkey_sign_hash2(vhost->key[i], op->sig, 0, &data, &out);
|
||||
ret = gnutls_privkey_sign_hash2(vhost->key[i], op->sig,
|
||||
0, &data, &out);
|
||||
}
|
||||
sec_op_msg__free_unpacked(op, &pa);
|
||||
|
||||
@@ -305,7 +308,8 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
i = op->key_idx;
|
||||
if (op->has_key_idx == 0 || i >= vhost->key_size) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"%sreceived out-of-bounds key index (%d); have %d keys", PREFIX_VHOST(vhost), i, vhost->key_size);
|
||||
"%sreceived out-of-bounds key index (%d); have %d keys",
|
||||
PREFIX_VHOST(vhost), i, vhost->key_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -313,14 +317,12 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
data.size = op->data.len;
|
||||
|
||||
if (cmd == CMD_SEC_DECRYPT) {
|
||||
ret =
|
||||
gnutls_privkey_decrypt_data(vhost->key[i], 0, &data,
|
||||
&out);
|
||||
ret = gnutls_privkey_decrypt_data(vhost->key[i], 0,
|
||||
&data, &out);
|
||||
} else {
|
||||
ret =
|
||||
gnutls_privkey_sign_hash(vhost->key[i], 0,
|
||||
GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
|
||||
&data, &out);
|
||||
ret = gnutls_privkey_sign_hash(
|
||||
vhost->key[i], 0,
|
||||
GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, &data, &out);
|
||||
}
|
||||
sec_op_msg__free_unpacked(op, &pa);
|
||||
|
||||
@@ -335,144 +337,134 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
|
||||
return ret;
|
||||
|
||||
case CMD_SEC_CLI_STATS:{
|
||||
CliStatsMsg *tmsg;
|
||||
case CMD_SEC_CLI_STATS: {
|
||||
CliStatsMsg *tmsg;
|
||||
|
||||
tmsg = cli_stats_msg__unpack(&pa, data.size, data.data);
|
||||
if (tmsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_sec_auth_stats_cmd(sec, tmsg, pid);
|
||||
cli_stats_msg__free_unpacked(tmsg, &pa);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_SEC_AUTH_INIT:{
|
||||
SecAuthInitMsg *auth_init;
|
||||
|
||||
auth_init =
|
||||
sec_auth_init_msg__unpack(&pa, data.size,
|
||||
data.data);
|
||||
if (auth_init == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking auth init\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_sec_auth_init(cfd, sec, auth_init, pid);
|
||||
sec_auth_init_msg__free_unpacked(auth_init, &pa);
|
||||
return ret;
|
||||
}
|
||||
case CMD_SEC_AUTH_CONT:{
|
||||
SecAuthContMsg *auth_cont;
|
||||
|
||||
auth_cont =
|
||||
sec_auth_cont_msg__unpack(&pa, data.size,
|
||||
data.data);
|
||||
if (auth_cont == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking auth cont\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = handle_sec_auth_cont(cfd, sec, auth_cont);
|
||||
sec_auth_cont_msg__free_unpacked(auth_cont, &pa);
|
||||
return ret;
|
||||
}
|
||||
case RESUME_STORE_REQ:{
|
||||
SessionResumeStoreReqMsg *smsg;
|
||||
|
||||
smsg =
|
||||
session_resume_store_req_msg__unpack(&pa, buffer_size,
|
||||
buffer);
|
||||
if (smsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_resume_store_req(sec, smsg);
|
||||
|
||||
/* zeroize the data */
|
||||
safe_memset(buffer, 0, buffer_size);
|
||||
safe_memset(smsg->session_data.data, 0, smsg->session_data.len);
|
||||
|
||||
session_resume_store_req_msg__free_unpacked(smsg, &pa);
|
||||
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"could not store resumption data");
|
||||
}
|
||||
tmsg = cli_stats_msg__unpack(&pa, data.size, data.data);
|
||||
if (tmsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
ret = handle_sec_auth_stats_cmd(sec, tmsg, pid);
|
||||
cli_stats_msg__free_unpacked(tmsg, &pa);
|
||||
return ret;
|
||||
} break;
|
||||
|
||||
case RESUME_DELETE_REQ:{
|
||||
SessionResumeFetchMsg *fmsg;
|
||||
case CMD_SEC_AUTH_INIT: {
|
||||
SecAuthInitMsg *auth_init;
|
||||
|
||||
fmsg =
|
||||
session_resume_fetch_msg__unpack(&pa, buffer_size,
|
||||
buffer);
|
||||
if (fmsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_resume_delete_req(sec, fmsg);
|
||||
|
||||
session_resume_fetch_msg__free_unpacked(fmsg, &pa);
|
||||
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"could not delete resumption data.");
|
||||
}
|
||||
auth_init =
|
||||
sec_auth_init_msg__unpack(&pa, data.size, data.data);
|
||||
if (auth_init == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking auth init\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case RESUME_FETCH_REQ:{
|
||||
SessionResumeReplyMsg msg =
|
||||
SESSION_RESUME_REPLY_MSG__INIT;
|
||||
SessionResumeFetchMsg *fmsg;
|
||||
|
||||
fmsg =
|
||||
session_resume_fetch_msg__unpack(&pa, buffer_size,
|
||||
buffer);
|
||||
if (fmsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_resume_fetch_req(sec, fmsg, &msg);
|
||||
|
||||
session_resume_fetch_msg__free_unpacked(fmsg, &pa);
|
||||
|
||||
if (ret < 0) {
|
||||
msg.reply =
|
||||
SESSION_RESUME_REPLY_MSG__RESUME__REP__FAILED;
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"could not fetch resumption data.");
|
||||
} else {
|
||||
msg.reply =
|
||||
SESSION_RESUME_REPLY_MSG__RESUME__REP__OK;
|
||||
}
|
||||
|
||||
ret =
|
||||
send_msg(pool, cfd, RESUME_FETCH_REP, &msg,
|
||||
(pack_size_func)
|
||||
session_resume_reply_msg__get_packed_size,
|
||||
(pack_func)
|
||||
session_resume_reply_msg__pack);
|
||||
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR,
|
||||
"could not send reply cmd %d.",
|
||||
(unsigned)cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
ret = handle_sec_auth_init(cfd, sec, auth_init, pid);
|
||||
sec_auth_init_msg__free_unpacked(auth_init, &pa);
|
||||
return ret;
|
||||
}
|
||||
case CMD_SEC_AUTH_CONT: {
|
||||
SecAuthContMsg *auth_cont;
|
||||
|
||||
auth_cont =
|
||||
sec_auth_cont_msg__unpack(&pa, data.size, data.data);
|
||||
if (auth_cont == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking auth cont\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
ret = handle_sec_auth_cont(cfd, sec, auth_cont);
|
||||
sec_auth_cont_msg__free_unpacked(auth_cont, &pa);
|
||||
return ret;
|
||||
}
|
||||
case RESUME_STORE_REQ: {
|
||||
SessionResumeStoreReqMsg *smsg;
|
||||
|
||||
smsg = session_resume_store_req_msg__unpack(&pa, buffer_size,
|
||||
buffer);
|
||||
if (smsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_resume_store_req(sec, smsg);
|
||||
|
||||
/* zeroize the data */
|
||||
safe_memset(buffer, 0, buffer_size);
|
||||
safe_memset(smsg->session_data.data, 0, smsg->session_data.len);
|
||||
|
||||
session_resume_store_req_msg__free_unpacked(smsg, &pa);
|
||||
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"could not store resumption data");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RESUME_DELETE_REQ: {
|
||||
SessionResumeFetchMsg *fmsg;
|
||||
|
||||
fmsg = session_resume_fetch_msg__unpack(&pa, buffer_size,
|
||||
buffer);
|
||||
if (fmsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_resume_delete_req(sec, fmsg);
|
||||
|
||||
session_resume_fetch_msg__free_unpacked(fmsg, &pa);
|
||||
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"could not delete resumption data.");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case RESUME_FETCH_REQ: {
|
||||
SessionResumeReplyMsg msg = SESSION_RESUME_REPLY_MSG__INIT;
|
||||
SessionResumeFetchMsg *fmsg;
|
||||
|
||||
fmsg = session_resume_fetch_msg__unpack(&pa, buffer_size,
|
||||
buffer);
|
||||
if (fmsg == NULL) {
|
||||
seclog(sec, LOG_ERR, "error unpacking data");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_resume_fetch_req(sec, fmsg, &msg);
|
||||
|
||||
session_resume_fetch_msg__free_unpacked(fmsg, &pa);
|
||||
|
||||
if (ret < 0) {
|
||||
msg.reply =
|
||||
SESSION_RESUME_REPLY_MSG__RESUME__REP__FAILED;
|
||||
seclog(sec, LOG_DEBUG,
|
||||
"could not fetch resumption data.");
|
||||
} else {
|
||||
msg.reply = SESSION_RESUME_REPLY_MSG__RESUME__REP__OK;
|
||||
}
|
||||
|
||||
ret = send_msg(
|
||||
pool, cfd, RESUME_FETCH_REP, &msg,
|
||||
(pack_size_func)
|
||||
session_resume_reply_msg__get_packed_size,
|
||||
(pack_func)session_resume_reply_msg__pack);
|
||||
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "could not send reply cmd %d.",
|
||||
(unsigned int)cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
seclog(sec, LOG_WARNING, "unknown type 0x%.2x", cmd);
|
||||
@@ -482,12 +474,13 @@ int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st *sec, cmd_r
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t cmd,
|
||||
uint8_t * buffer, size_t buffer_size)
|
||||
static int process_packet_from_main(void *pool, int fd, sec_mod_st *sec,
|
||||
cmd_request_t cmd, uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
gnutls_datum_t data;
|
||||
int ret;
|
||||
|
||||
PROTOBUF_ALLOCATOR(pa, pool);
|
||||
|
||||
seclog(sec, LOG_DEBUG, "cmd [size=%d] %s\n", (int)buffer_size,
|
||||
@@ -499,10 +492,11 @@ int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t
|
||||
case CMD_SECM_RELOAD:
|
||||
reload_server(sec);
|
||||
|
||||
ret = send_msg(pool, fd, CMD_SECM_RELOAD_REPLY, NULL,
|
||||
NULL, NULL);
|
||||
ret = send_msg(pool, fd, CMD_SECM_RELOAD_REPLY, NULL, NULL,
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "could not send reload reply to main!\n");
|
||||
seclog(sec, LOG_ERR,
|
||||
"could not send reload reply to main!\n");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
break;
|
||||
@@ -510,14 +504,13 @@ int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t
|
||||
handle_secm_list_cookies_reply(pool, fd, sec);
|
||||
|
||||
return 0;
|
||||
case CMD_SECM_BAN_IP_REPLY:{
|
||||
case CMD_SECM_BAN_IP_REPLY: {
|
||||
BanIpReplyMsg *msg = NULL;
|
||||
|
||||
msg =
|
||||
ban_ip_reply_msg__unpack(&pa, data.size,
|
||||
data.data);
|
||||
msg = ban_ip_reply_msg__unpack(&pa, data.size, data.data);
|
||||
if (msg == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking auth ban ip reply\n");
|
||||
seclog(sec, LOG_INFO,
|
||||
"error unpacking auth ban ip reply\n");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
@@ -526,38 +519,35 @@ int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t
|
||||
|
||||
return 0;
|
||||
}
|
||||
case CMD_SECM_SESSION_OPEN:{
|
||||
SecmSessionOpenMsg *msg;
|
||||
case CMD_SECM_SESSION_OPEN: {
|
||||
SecmSessionOpenMsg *msg;
|
||||
|
||||
msg =
|
||||
secm_session_open_msg__unpack(&pa, data.size,
|
||||
data.data);
|
||||
if (msg == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking session open\n");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_secm_session_open_cmd(sec, fd, msg);
|
||||
secm_session_open_msg__free_unpacked(msg, &pa);
|
||||
|
||||
return ret;
|
||||
msg = secm_session_open_msg__unpack(&pa, data.size, data.data);
|
||||
if (msg == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking session open\n");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
case CMD_SECM_SESSION_CLOSE:{
|
||||
SecmSessionCloseMsg *msg;
|
||||
|
||||
msg =
|
||||
secm_session_close_msg__unpack(&pa, data.size,
|
||||
data.data);
|
||||
if (msg == NULL) {
|
||||
seclog(sec, LOG_INFO, "error unpacking session close\n");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
ret = handle_secm_session_open_cmd(sec, fd, msg);
|
||||
secm_session_open_msg__free_unpacked(msg, &pa);
|
||||
|
||||
ret = handle_secm_session_close_cmd(sec, fd, msg);
|
||||
secm_session_close_msg__free_unpacked(msg, &pa);
|
||||
return ret;
|
||||
}
|
||||
case CMD_SECM_SESSION_CLOSE: {
|
||||
SecmSessionCloseMsg *msg;
|
||||
|
||||
return ret;
|
||||
msg = secm_session_close_msg__unpack(&pa, data.size, data.data);
|
||||
if (msg == NULL) {
|
||||
seclog(sec, LOG_INFO,
|
||||
"error unpacking session close\n");
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
ret = handle_secm_session_close_cmd(sec, fd, msg);
|
||||
secm_session_close_msg__free_unpacked(msg, &pa);
|
||||
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
seclog(sec, LOG_WARNING, "unknown type 0x%.2x", cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
@@ -603,8 +593,8 @@ static void send_stats_to_main(sec_mod_st *sec)
|
||||
msg.secmod_tlsdb_entries = sec->tls_db.entries;
|
||||
|
||||
ret = send_msg(sec, sec->cmd_fd, CMD_SECM_STATS, &msg,
|
||||
(pack_size_func) secm_stats_msg__get_packed_size,
|
||||
(pack_func) secm_stats_msg__pack);
|
||||
(pack_size_func)secm_stats_msg__get_packed_size,
|
||||
(pack_func)secm_stats_msg__pack);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "error in sending statistics to main");
|
||||
return;
|
||||
@@ -619,7 +609,8 @@ static void reload_server(sec_mod_st *sec)
|
||||
reload_cfg_file(sec, sec->vconfig, 1);
|
||||
load_keys(sec, 0);
|
||||
|
||||
list_for_each(sec->vconfig, vhost, list) {
|
||||
list_for_each(sec->vconfig, vhost, list)
|
||||
{
|
||||
sec_auth_init(vhost);
|
||||
}
|
||||
sup_config_init(sec);
|
||||
@@ -632,9 +623,10 @@ static void check_other_work(sec_mod_st *sec)
|
||||
vhost_cfg_st *vhost = NULL;
|
||||
|
||||
if (need_exit) {
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
list_for_each(sec->vconfig, vhost, list) {
|
||||
list_for_each(sec->vconfig, vhost, list)
|
||||
{
|
||||
for (i = 0; i < vhost->key_size; i++) {
|
||||
gnutls_privkey_deinit(vhost->key[i]);
|
||||
vhost->key[i] = NULL;
|
||||
@@ -659,14 +651,14 @@ static void check_other_work(sec_mod_st *sec)
|
||||
expire_tls_sessions(sec);
|
||||
send_stats_to_main(sec);
|
||||
seclog(sec, LOG_DEBUG, "active sessions %d",
|
||||
sec_mod_client_db_elems(sec));
|
||||
sec_mod_client_db_elems(sec));
|
||||
alarm(MAINTAINANCE_TIME);
|
||||
need_maintainance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int serve_request_main(sec_mod_st *sec, int fd, uint8_t *buffer, unsigned buffer_size)
|
||||
static int serve_request_main(sec_mod_st *sec, int fd, uint8_t *buffer,
|
||||
unsigned int buffer_size)
|
||||
{
|
||||
int ret, e;
|
||||
uint8_t cmd;
|
||||
@@ -685,13 +677,15 @@ int serve_request_main(sec_mod_st *sec, int fd, uint8_t *buffer, unsigned buffer
|
||||
|
||||
seclog(sec, LOG_DEBUG, "received request %s", cmd_request_to_str(cmd));
|
||||
if (cmd <= MIN_SECM_CMD || cmd >= MAX_SECM_CMD) {
|
||||
seclog(sec, LOG_ERR, "received invalid message from main of %u bytes (cmd: %u)\n",
|
||||
(unsigned)length, (unsigned)cmd);
|
||||
seclog(sec, LOG_ERR,
|
||||
"received invalid message from main of %u bytes (cmd: %u)\n",
|
||||
(unsigned int)length, (unsigned int)cmd);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (length > buffer_size) {
|
||||
seclog(sec, LOG_ERR, "received too big message (%d)", (int)length);
|
||||
seclog(sec, LOG_ERR, "received too big message (%d)",
|
||||
(int)length);
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto leave;
|
||||
}
|
||||
@@ -700,23 +694,26 @@ int serve_request_main(sec_mod_st *sec, int fd, uint8_t *buffer, unsigned buffer
|
||||
ret = force_read_timeout(fd, buffer, length, MAIN_SEC_MOD_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_ERR, "error receiving msg body of cmd %u with length %u: %s",
|
||||
cmd, (unsigned)length, strerror(e));
|
||||
seclog(sec, LOG_ERR,
|
||||
"error receiving msg body of cmd %u with length %u: %s",
|
||||
cmd, (unsigned int)length, strerror(e));
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
ret = process_packet_from_main(pool, fd, sec, cmd, buffer, ret);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "error processing data for '%s' command (%d)", cmd_request_to_str(cmd), ret);
|
||||
seclog(sec, LOG_ERR,
|
||||
"error processing data for '%s' command (%d)",
|
||||
cmd_request_to_str(cmd), ret);
|
||||
}
|
||||
|
||||
leave:
|
||||
leave:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int serve_request_worker(sec_mod_st *sec, int cfd, pid_t pid, uint8_t *buffer, unsigned buffer_size)
|
||||
static int serve_request_worker(sec_mod_st *sec, int cfd, pid_t pid,
|
||||
uint8_t *buffer, unsigned int buffer_size)
|
||||
{
|
||||
int ret, e;
|
||||
uint8_t cmd;
|
||||
@@ -750,24 +747,33 @@ int serve_request_worker(sec_mod_st *sec, int cfd, pid_t pid, uint8_t *buffer, u
|
||||
|
||||
ret = process_worker_packet(pool, cfd, pid, sec, cmd, buffer, ret);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_DEBUG, "error processing '%s' command (%d)", cmd_request_to_str(cmd), ret);
|
||||
seclog(sec, LOG_DEBUG, "error processing '%s' command (%d)",
|
||||
cmd_request_to_str(cmd), ret);
|
||||
}
|
||||
|
||||
leave:
|
||||
leave:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define CHECK_LOOP_ERR(x) { \
|
||||
if (force != 0) { GNUTLS_FATAL_ERR(x); } \
|
||||
else { if (ret < 0) { \
|
||||
seclog(sec, LOG_ERR, "could not reload key %s", vhost->perm_config.key[i]); \
|
||||
continue; } \
|
||||
}}
|
||||
#define CHECK_LOOP_ERR(x) \
|
||||
{ \
|
||||
if (force != 0) { \
|
||||
GNUTLS_FATAL_ERR(x); \
|
||||
} else { \
|
||||
if (ret < 0) { \
|
||||
seclog(sec, LOG_ERR, \
|
||||
"could not reload key %s", \
|
||||
vhost->perm_config.key[i]); \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
static void read_private_key(sec_mod_st *sec, vhost_cfg_st *vhost, unsigned force)
|
||||
static void read_private_key(sec_mod_st *sec, vhost_cfg_st *vhost,
|
||||
unsigned int force)
|
||||
{
|
||||
int ret;
|
||||
unsigned i;
|
||||
unsigned int i;
|
||||
|
||||
/* read private keys */
|
||||
for (i = 0; i < vhost->key_size; i++) {
|
||||
@@ -778,33 +784,33 @@ static void read_private_key(sec_mod_st *sec, vhost_cfg_st *vhost, unsigned forc
|
||||
|
||||
/* load the private key */
|
||||
if (gnutls_url_is_supported(vhost->perm_config.key[i]) != 0) {
|
||||
gnutls_privkey_set_pin_function(p,
|
||||
pin_callback, &vhost->pins);
|
||||
ret =
|
||||
gnutls_privkey_import_url(p,
|
||||
vhost->perm_config.key[i], 0);
|
||||
gnutls_privkey_set_pin_function(p, pin_callback,
|
||||
&vhost->pins);
|
||||
ret = gnutls_privkey_import_url(
|
||||
p, vhost->perm_config.key[i], 0);
|
||||
CHECK_LOOP_ERR(ret);
|
||||
} else {
|
||||
gnutls_datum_t data;
|
||||
ret = gnutls_load_file(vhost->perm_config.key[i], &data);
|
||||
|
||||
ret = gnutls_load_file(vhost->perm_config.key[i],
|
||||
&data);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_ERR, "error loading file '%s'",
|
||||
vhost->perm_config.key[i]);
|
||||
CHECK_LOOP_ERR(ret);
|
||||
}
|
||||
|
||||
ret =
|
||||
gnutls_privkey_import_x509_raw(p, &data,
|
||||
GNUTLS_X509_FMT_PEM,
|
||||
NULL, 0);
|
||||
ret = gnutls_privkey_import_x509_raw(
|
||||
p, &data, GNUTLS_X509_FMT_PEM, NULL, 0);
|
||||
/* GnuTLS 3.7.3 introduces a backwards incompatible change and
|
||||
* GNUTLS_E_PKCS11_PIN_ERROR is returned when an encrypted
|
||||
* file is loaded https://gitlab.com/gnutls/gnutls/-/issues/1321 */
|
||||
if ((ret == GNUTLS_E_DECRYPTION_FAILED || ret == GNUTLS_E_PKCS11_PIN_ERROR) && vhost->pins.pin[0]) {
|
||||
ret =
|
||||
gnutls_privkey_import_x509_raw(p, &data,
|
||||
GNUTLS_X509_FMT_PEM,
|
||||
vhost->pins.pin, 0);
|
||||
if ((ret == GNUTLS_E_DECRYPTION_FAILED ||
|
||||
ret == GNUTLS_E_PKCS11_PIN_ERROR) &&
|
||||
vhost->pins.pin[0]) {
|
||||
ret = gnutls_privkey_import_x509_raw(
|
||||
p, &data, GNUTLS_X509_FMT_PEM,
|
||||
vhost->pins.pin, 0);
|
||||
}
|
||||
CHECK_LOOP_ERR(ret);
|
||||
gnutls_free(data.data);
|
||||
@@ -815,21 +821,25 @@ static void read_private_key(sec_mod_st *sec, vhost_cfg_st *vhost, unsigned forc
|
||||
}
|
||||
vhost->key[i] = p;
|
||||
}
|
||||
seclog(sec, LOG_DEBUG, "%sloaded %d keys\n", PREFIX_VHOST(vhost), vhost->key_size);
|
||||
seclog(sec, LOG_DEBUG, "%sloaded %d keys\n", PREFIX_VHOST(vhost),
|
||||
vhost->key_size);
|
||||
}
|
||||
|
||||
static int load_keys(sec_mod_st *sec, unsigned force)
|
||||
static int load_keys(sec_mod_st *sec, unsigned int force)
|
||||
{
|
||||
unsigned i, reload_file;
|
||||
unsigned int i, reload_file;
|
||||
int ret;
|
||||
vhost_cfg_st *vhost = NULL;
|
||||
|
||||
list_for_each_rev(sec->vconfig, vhost, list) {
|
||||
list_for_each_rev(sec->vconfig, vhost, list)
|
||||
{
|
||||
if (force == 0) {
|
||||
reload_file = 0;
|
||||
|
||||
for (i = 0; i < vhost->perm_config.key_size; i++) {
|
||||
if (need_file_reload(vhost->perm_config.key[i], vhost->cert_last_access) != 0) {
|
||||
if (need_file_reload(vhost->perm_config.key[i],
|
||||
vhost->cert_last_access) !=
|
||||
0) {
|
||||
reload_file = 1;
|
||||
break;
|
||||
}
|
||||
@@ -851,9 +861,12 @@ static int load_keys(sec_mod_st *sec, unsigned force)
|
||||
*/
|
||||
if (vhost->key == NULL) {
|
||||
vhost->key_size = vhost->perm_config.key_size;
|
||||
vhost->key = talloc_zero_size(sec, sizeof(*vhost->key) * vhost->perm_config.key_size);
|
||||
vhost->key = talloc_zero_size(
|
||||
sec, sizeof(*vhost->key) *
|
||||
vhost->perm_config.key_size);
|
||||
if (vhost->key == NULL) {
|
||||
seclog(sec, LOG_ERR, "error in memory allocation");
|
||||
seclog(sec, LOG_ERR,
|
||||
"error in memory allocation");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -892,15 +905,15 @@ static int load_keys(sec_mod_st *sec, unsigned force)
|
||||
* clients fast without becoming a bottleneck due to private
|
||||
* key operations.
|
||||
*/
|
||||
void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfig,
|
||||
const char *socket_file, int cmd_fd, int cmd_fd_sync,
|
||||
size_t hmac_key_length, const uint8_t * hmac_key,
|
||||
const uint8_t instance_id)
|
||||
void sec_mod_server(void *main_pool, void *config_pool,
|
||||
struct list_head *vconfig, const char *socket_file,
|
||||
int cmd_fd, int cmd_fd_sync, size_t hmac_key_length,
|
||||
const uint8_t *hmac_key, const uint8_t instance_id)
|
||||
{
|
||||
struct sockaddr_un sa;
|
||||
socklen_t sa_len;
|
||||
int cfd, ret, e, n;
|
||||
unsigned buffer_size;
|
||||
unsigned int buffer_size;
|
||||
uid_t uid;
|
||||
uint8_t *buffer;
|
||||
int sd;
|
||||
@@ -941,7 +954,7 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
|
||||
sec->vconfig = vconfig;
|
||||
sec->config_pool = config_pool;
|
||||
sec->sec_mod_pool = sec_mod_pool;
|
||||
memcpy((uint8_t*)sec->hmac_key, hmac_key, hmac_key_length);
|
||||
memcpy((uint8_t *)sec->hmac_key, hmac_key, hmac_key_length);
|
||||
sec->sec_mod_instance_id = instance_id;
|
||||
|
||||
tls_cache_init(sec, &sec->tls_db);
|
||||
@@ -962,7 +975,8 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
|
||||
ocsignal(SIGTERM, handle_sigterm);
|
||||
ocsignal(SIGALRM, handle_alarm);
|
||||
|
||||
list_for_each(sec->vconfig, vhost, list) {
|
||||
list_for_each(sec->vconfig, vhost, list)
|
||||
{
|
||||
sec_auth_init(vhost);
|
||||
}
|
||||
|
||||
@@ -977,8 +991,8 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
|
||||
sd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sd == -1) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_ERR, "could not create socket '%s': %s", SOCKET_FILE,
|
||||
strerror(e));
|
||||
seclog(sec, LOG_ERR, "could not create socket '%s': %s",
|
||||
SOCKET_FILE, strerror(e));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
set_cloexec_flag(sd, 1);
|
||||
@@ -987,16 +1001,16 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
|
||||
ret = bind(sd, (struct sockaddr *)&sa, SUN_LEN(&sa));
|
||||
if (ret == -1) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_ERR, "could not bind socket '%s': %s", SOCKET_FILE,
|
||||
strerror(e));
|
||||
seclog(sec, LOG_ERR, "could not bind socket '%s': %s",
|
||||
SOCKET_FILE, strerror(e));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = chown(SOCKET_FILE, GETPCONFIG(sec)->uid, GETPCONFIG(sec)->gid);
|
||||
if (ret == -1) {
|
||||
e = errno;
|
||||
seclog(sec, LOG_INFO, "could not chown socket '%s': %s", SOCKET_FILE,
|
||||
strerror(e));
|
||||
seclog(sec, LOG_INFO, "could not chown socket '%s': %s",
|
||||
SOCKET_FILE, strerror(e));
|
||||
}
|
||||
|
||||
ret = listen(sd, 1024);
|
||||
@@ -1017,7 +1031,6 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
|
||||
alarm(MAINTAINANCE_TIME);
|
||||
seclog(sec, LOG_INFO, "sec-mod initialized (socket: %s)", SOCKET_FILE);
|
||||
|
||||
|
||||
for (;;) {
|
||||
check_other_work(sec);
|
||||
|
||||
@@ -1067,17 +1080,21 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
|
||||
* ping-pong communication where each request is answered immediately. The
|
||||
* async is for messages sent back and forth in no particular order */
|
||||
if (FD_ISSET(cmd_fd_sync, &rd_set)) {
|
||||
ret = serve_request_main(sec, cmd_fd_sync, buffer, buffer_size);
|
||||
ret = serve_request_main(sec, cmd_fd_sync, buffer,
|
||||
buffer_size);
|
||||
if (ret < 0 && ret == ERR_BAD_COMMAND) {
|
||||
seclog(sec, LOG_ERR, "error processing sync command from main");
|
||||
seclog(sec, LOG_ERR,
|
||||
"error processing sync command from main");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(cmd_fd, &rd_set)) {
|
||||
ret = serve_request_main(sec, cmd_fd, buffer, buffer_size);
|
||||
ret = serve_request_main(sec, cmd_fd, buffer,
|
||||
buffer_size);
|
||||
if (ret < 0 && ret == ERR_BAD_COMMAND) {
|
||||
seclog(sec, LOG_ERR, "error processing async command from main");
|
||||
seclog(sec, LOG_ERR,
|
||||
"error processing async command from main");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -1094,22 +1111,25 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
|
||||
goto cont;
|
||||
}
|
||||
}
|
||||
set_cloexec_flag (cfd, 1);
|
||||
set_cloexec_flag(cfd, 1);
|
||||
|
||||
/* do not allow unauthorized processes to issue commands
|
||||
*/
|
||||
ret = check_upeer_id("sec-mod", GETPCONFIG(sec)->log_level, cfd,
|
||||
GETPCONFIG(sec)->uid, GETPCONFIG(sec)->gid,
|
||||
&uid, &pid);
|
||||
ret = check_upeer_id("sec-mod",
|
||||
GETPCONFIG(sec)->log_level, cfd,
|
||||
GETPCONFIG(sec)->uid,
|
||||
GETPCONFIG(sec)->gid, &uid, &pid);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_INFO, "rejected unauthorized connection");
|
||||
seclog(sec, LOG_INFO,
|
||||
"rejected unauthorized connection");
|
||||
} else {
|
||||
memset(buffer, 0, buffer_size);
|
||||
serve_request_worker(sec, cfd, pid, buffer, buffer_size);
|
||||
serve_request_worker(sec, cfd, pid, buffer,
|
||||
buffer_size);
|
||||
}
|
||||
close(cfd);
|
||||
}
|
||||
cont:
|
||||
cont:
|
||||
talloc_free(buffer);
|
||||
#ifdef DEBUG_LEAKS
|
||||
talloc_report_full(sec, stderr);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_SEC_MOD_H
|
||||
# define OC_SEC_MOD_H
|
||||
#define OC_SEC_MOD_H
|
||||
|
||||
#include <gnutls/abstract.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
@@ -64,11 +64,11 @@ typedef struct common_auth_init_st {
|
||||
const char *ip;
|
||||
const char *our_ip;
|
||||
const char *user_agent;
|
||||
unsigned id;
|
||||
unsigned int id;
|
||||
} common_auth_init_st;
|
||||
|
||||
typedef struct common_acct_info_st {
|
||||
char username[MAX_USERNAME_SIZE*2];
|
||||
char username[MAX_USERNAME_SIZE * 2];
|
||||
char groupname[MAX_GROUPNAME_SIZE]; /* the owner's group */
|
||||
char safe_id[SAFE_ID_SIZE]; /* an ID to be sent to external apps - printable */
|
||||
char remote_ip[MAX_IP_STR];
|
||||
@@ -78,11 +78,13 @@ typedef struct common_acct_info_st {
|
||||
char our_ip[MAX_IP_STR];
|
||||
char ipv4[MAX_IP_STR];
|
||||
char ipv6[MAX_IP_STR];
|
||||
unsigned id;
|
||||
unsigned int id;
|
||||
} common_acct_info_st;
|
||||
|
||||
#define IS_CLIENT_ENTRY_EXPIRED_FULL(sec, e, now, clean) (e->exptime != -1 && now >= e->exptime && e->in_use == 0)
|
||||
#define IS_CLIENT_ENTRY_EXPIRED(sec, e, now) IS_CLIENT_ENTRY_EXPIRED_FULL(sec, e, now, 0)
|
||||
#define IS_CLIENT_ENTRY_EXPIRED_FULL(sec, e, now, clean) \
|
||||
(e->exptime != -1 && now >= e->exptime && e->in_use == 0)
|
||||
#define IS_CLIENT_ENTRY_EXPIRED(sec, e, now) \
|
||||
IS_CLIENT_ENTRY_EXPIRED_FULL(sec, e, now, 0)
|
||||
|
||||
typedef struct client_entry_st {
|
||||
/* A unique session identifier used to distinguish sessions
|
||||
@@ -93,17 +95,18 @@ typedef struct client_entry_st {
|
||||
uint8_t sid[SID_SIZE];
|
||||
|
||||
void *auth_ctx; /* the context of authentication */
|
||||
unsigned session_is_open; /* whether open_session was done */
|
||||
unsigned in_use; /* counter of users of this structure */
|
||||
unsigned tls_auth_ok;
|
||||
unsigned int session_is_open; /* whether open_session was done */
|
||||
unsigned int in_use; /* counter of users of this structure */
|
||||
unsigned int tls_auth_ok;
|
||||
|
||||
char *msg_str;
|
||||
unsigned passwd_counter; /* if msg_str is for a password this indicates the passwrd number (0,1,2) */
|
||||
unsigned int
|
||||
passwd_counter; /* if msg_str is for a password this indicates the passwrd number (0,1,2) */
|
||||
|
||||
stats_st saved_stats; /* saved from previous cookie usage */
|
||||
stats_st stats; /* current */
|
||||
|
||||
unsigned status; /* PS_AUTH_ */
|
||||
unsigned int status; /* PS_AUTH_ */
|
||||
|
||||
uint8_t dtls_session_id[GNUTLS_MAX_SESSION_ID];
|
||||
|
||||
@@ -113,15 +116,16 @@ typedef struct client_entry_st {
|
||||
time_t exptime;
|
||||
|
||||
/* the auth type associated with the user */
|
||||
unsigned auth_type;
|
||||
unsigned discon_reason; /* reason for disconnection */
|
||||
unsigned int auth_type;
|
||||
unsigned int discon_reason; /* reason for disconnection */
|
||||
|
||||
struct common_acct_info_st acct_info;
|
||||
|
||||
/* saved during authentication; used after successful auth */
|
||||
char req_group_name[MAX_GROUPNAME_SIZE]; /* the requested by the user group */
|
||||
char req_group_name
|
||||
[MAX_GROUPNAME_SIZE]; /* the requested by the user group */
|
||||
char *cert_group_names[MAX_GROUPS];
|
||||
unsigned cert_group_names_size;
|
||||
unsigned int cert_group_names_size;
|
||||
char cert_user_name[MAX_USERNAME_SIZE];
|
||||
|
||||
/* the module this entry is using */
|
||||
@@ -135,28 +139,32 @@ typedef struct client_entry_st {
|
||||
|
||||
void *sec_mod_client_db_init(sec_mod_st *sec);
|
||||
void sec_mod_client_db_deinit(sec_mod_st *sec);
|
||||
unsigned sec_mod_client_db_elems(sec_mod_st *sec);
|
||||
client_entry_st * new_client_entry(sec_mod_st *sec, struct vhost_cfg_st *, const char *ip, unsigned pid);
|
||||
client_entry_st * find_client_entry(sec_mod_st *sec, uint8_t sid[SID_SIZE]);
|
||||
void del_client_entry(sec_mod_st *sec, client_entry_st * e);
|
||||
void expire_client_entry(sec_mod_st *sec, client_entry_st * e);
|
||||
unsigned int sec_mod_client_db_elems(sec_mod_st *sec);
|
||||
client_entry_st *new_client_entry(sec_mod_st *sec, struct vhost_cfg_st *,
|
||||
const char *ip, unsigned int pid);
|
||||
client_entry_st *find_client_entry(sec_mod_st *sec, uint8_t sid[SID_SIZE]);
|
||||
void del_client_entry(sec_mod_st *sec, client_entry_st *e);
|
||||
void expire_client_entry(sec_mod_st *sec, client_entry_st *e);
|
||||
void cleanup_client_entries(sec_mod_st *sec);
|
||||
|
||||
void sec_auth_init(struct vhost_cfg_st *vhost);
|
||||
|
||||
void handle_secm_list_cookies_reply(void *pool, int fd, sec_mod_st *sec);
|
||||
void handle_sec_auth_ban_ip_reply(sec_mod_st *sec, const BanIpReplyMsg *msg);
|
||||
int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg * req, pid_t pid);
|
||||
int handle_sec_auth_cont(int cfd, sec_mod_st *sec, const SecAuthContMsg * req);
|
||||
int handle_secm_session_open_cmd(sec_mod_st *sec, int fd, const SecmSessionOpenMsg *req);
|
||||
int handle_secm_session_close_cmd(sec_mod_st *sec, int fd, const SecmSessionCloseMsg *req);
|
||||
int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req, pid_t pid);
|
||||
int handle_sec_auth_init(int cfd, sec_mod_st *sec, const SecAuthInitMsg *req,
|
||||
pid_t pid);
|
||||
int handle_sec_auth_cont(int cfd, sec_mod_st *sec, const SecAuthContMsg *req);
|
||||
int handle_secm_session_open_cmd(sec_mod_st *sec, int fd,
|
||||
const SecmSessionOpenMsg *req);
|
||||
int handle_secm_session_close_cmd(sec_mod_st *sec, int fd,
|
||||
const SecmSessionCloseMsg *req);
|
||||
int handle_sec_auth_stats_cmd(sec_mod_st *sec, const CliStatsMsg *req,
|
||||
pid_t pid);
|
||||
void sec_auth_user_deinit(sec_mod_st *sec, client_entry_st *e);
|
||||
|
||||
void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfig,
|
||||
const char *socket_file,
|
||||
int cmd_fd, int cmd_fd_sync,
|
||||
size_t hmac_key_length, const uint8_t * hmac_key,
|
||||
const uint8_t instance_id);
|
||||
void sec_mod_server(void *main_pool, void *config_pool,
|
||||
struct list_head *vconfig, const char *socket_file,
|
||||
int cmd_fd, int cmd_fd_sync, size_t hmac_key_length,
|
||||
const uint8_t *hmac_key, const uint8_t instance_id);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,25 +24,25 @@
|
||||
|
||||
#if !defined(HAVE_SETPROCTITLE)
|
||||
|
||||
# if defined(__linux__)
|
||||
# include <sys/prctl.h>
|
||||
#if defined(__linux__)
|
||||
#include <sys/prctl.h>
|
||||
|
||||
/* This sets the process title as shown in top, but not in ps (*@#%@).
|
||||
* To change the ps name in Linux, one needs to do master black magic
|
||||
* trickery (see util-linux setproctitle).
|
||||
*/
|
||||
void setproctitle (const char *fmt, ...)
|
||||
void setproctitle(const char *fmt, ...)
|
||||
{
|
||||
char name[16];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(name, sizeof(name)-1, fmt, args);
|
||||
vsnprintf(name, sizeof(name) - 1, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
# ifdef PR_SET_NAME
|
||||
prctl (PR_SET_NAME, name);
|
||||
# endif
|
||||
#ifdef PR_SET_NAME
|
||||
prctl(PR_SET_NAME, name);
|
||||
#endif
|
||||
/* Copied systemd's implementation under LGPL by Lennart Poettering */
|
||||
if (saved_argc > 0) {
|
||||
int i;
|
||||
@@ -56,12 +56,12 @@ void setproctitle (const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
}
|
||||
# else /* not linux */
|
||||
#else /* not linux */
|
||||
|
||||
void setproctitle (const char *fmt, ...)
|
||||
void setproctitle(const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
|
||||
# endif /* __linux__ */
|
||||
#endif /* __linux__ */
|
||||
|
||||
#endif /* HAVE_SETPROCTITLE */
|
||||
|
||||
@@ -19,20 +19,19 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef OC_SETPROCTITLE_H
|
||||
# define OC_SETPROCTITLE_H
|
||||
#define OC_SETPROCTITLE_H
|
||||
|
||||
# include <config.h>
|
||||
#include <config.h>
|
||||
|
||||
# ifndef HAVE_SETPROCTILE
|
||||
#ifndef HAVE_SETPROCTILE
|
||||
|
||||
void __attribute__ ((format(printf, 1, 2)))
|
||||
setproctitle(const char *fmt, ...);
|
||||
void __attribute__((format(printf, 1, 2))) setproctitle(const char *fmt, ...);
|
||||
|
||||
# else
|
||||
#else
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
|
||||
# endif
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
57
src/str.c
57
src/str.c
@@ -31,11 +31,11 @@
|
||||
|
||||
void trim_trailing_whitespace(char *str)
|
||||
{
|
||||
unsigned len = strlen(str);
|
||||
unsigned int len = strlen(str);
|
||||
char *p;
|
||||
|
||||
if (len > 0) {
|
||||
p = str+len-1;
|
||||
p = str + len - 1;
|
||||
while (p >= str && isspace(*p)) {
|
||||
*p = 0;
|
||||
p--;
|
||||
@@ -43,9 +43,9 @@ void trim_trailing_whitespace(char *str)
|
||||
}
|
||||
}
|
||||
|
||||
#define MEMSUB(x,y) ((ssize_t)((ptrdiff_t)x-(ptrdiff_t)y))
|
||||
#define MEMSUB(x, y) ((ssize_t)((ptrdiff_t)x - (ptrdiff_t)y))
|
||||
|
||||
void str_clear(str_st * str)
|
||||
void str_clear(str_st *str)
|
||||
{
|
||||
if (str == NULL || str->allocd == NULL)
|
||||
return;
|
||||
@@ -59,20 +59,19 @@ void str_clear(str_st * str)
|
||||
#define MIN_CHUNK 64
|
||||
/* This function makes sure there is an additional byte in dest;
|
||||
*/
|
||||
int str_append_size(str_st * dest, size_t data_size)
|
||||
int str_append_size(str_st *dest, size_t data_size)
|
||||
{
|
||||
size_t tot_len = data_size + dest->length;
|
||||
|
||||
if (data_size == 0)
|
||||
return 0;
|
||||
|
||||
if (dest->max_length >= tot_len+1) {
|
||||
if (dest->max_length >= tot_len + 1) {
|
||||
size_t unused = MEMSUB(dest->data, dest->allocd);
|
||||
|
||||
if (dest->max_length - unused <= tot_len) {
|
||||
if (dest->length && dest->data)
|
||||
memmove(dest->allocd, dest->data,
|
||||
dest->length);
|
||||
memmove(dest->allocd, dest->data, dest->length);
|
||||
|
||||
dest->data = dest->allocd;
|
||||
}
|
||||
@@ -80,11 +79,11 @@ int str_append_size(str_st * dest, size_t data_size)
|
||||
return tot_len;
|
||||
} else {
|
||||
size_t unused = MEMSUB(dest->data, dest->allocd);
|
||||
size_t new_len =
|
||||
MAX(data_size, MIN_CHUNK) + MAX(dest->max_length,
|
||||
MIN_CHUNK);
|
||||
size_t new_len = MAX(data_size, MIN_CHUNK) +
|
||||
MAX(dest->max_length, MIN_CHUNK);
|
||||
|
||||
dest->allocd = talloc_realloc_size(dest->pool, dest->allocd, new_len+1);
|
||||
dest->allocd = talloc_realloc_size(dest->pool, dest->allocd,
|
||||
new_len + 1);
|
||||
if (dest->allocd == NULL)
|
||||
return ERR_MEM;
|
||||
dest->max_length = new_len;
|
||||
@@ -100,11 +99,11 @@ int str_append_size(str_st * dest, size_t data_size)
|
||||
|
||||
/* This function always null terminates the string in dest.
|
||||
*/
|
||||
int str_append_data(str_st * dest, const void *data, size_t data_size)
|
||||
int str_append_data(str_st *dest, const void *data, size_t data_size)
|
||||
{
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
ret = str_append_size(dest, data_size+1);
|
||||
ret = str_append_size(dest, data_size + 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -115,7 +114,7 @@ int str_append_data(str_st * dest, const void *data, size_t data_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int str_append_data_prefix1(str_st * dest, const void *data, size_t data_size)
|
||||
int str_append_data_prefix1(str_st *dest, const void *data, size_t data_size)
|
||||
{
|
||||
int ret;
|
||||
uint8_t prefix = data_size;
|
||||
@@ -131,7 +130,7 @@ int str_append_data_prefix1(str_st * dest, const void *data, size_t data_size)
|
||||
/* Appends the provided string. The null termination byte is appended
|
||||
* but not included in length.
|
||||
*/
|
||||
int str_append_str(str_st * dest, const char *src)
|
||||
int str_append_str(str_st *dest, const char *src)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -145,8 +144,7 @@ int str_append_str(str_st * dest, const char *src)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
str_append_printf(str_st *dest, const char *fmt, ...)
|
||||
int str_append_printf(str_st *dest, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int len;
|
||||
@@ -170,9 +168,9 @@ int str_replace_str(str_st *str, const str_rep_tab *tab)
|
||||
{
|
||||
uint8_t *p;
|
||||
const str_rep_tab *ptab;
|
||||
unsigned length;
|
||||
unsigned int length;
|
||||
char *final;
|
||||
unsigned final_len;
|
||||
unsigned int final_len;
|
||||
int ret;
|
||||
size_t pos;
|
||||
|
||||
@@ -183,25 +181,32 @@ int str_replace_str(str_st *str, const str_rep_tab *tab)
|
||||
if (p == NULL)
|
||||
break;
|
||||
|
||||
pos = (ptrdiff_t)(p-str->data);
|
||||
pos = (ptrdiff_t)(p - str->data);
|
||||
|
||||
length = str->length - pos;
|
||||
|
||||
ptab = tab;
|
||||
do {
|
||||
if (length >= ptab->pattern_length &&
|
||||
memcmp(ptab->pattern, p, ptab->pattern_length) == 0) {
|
||||
memcmp(ptab->pattern, p, ptab->pattern_length) ==
|
||||
0) {
|
||||
/* replace */
|
||||
final_len = length - ptab->pattern_length;
|
||||
final = talloc_memdup(str->allocd, p+ptab->pattern_length, final_len);
|
||||
final = talloc_memdup(str->allocd,
|
||||
p + ptab->pattern_length,
|
||||
final_len);
|
||||
if (final == NULL)
|
||||
return -1;
|
||||
|
||||
str->length -= final_len + ptab->pattern_length;
|
||||
if (ptab->rep_val)
|
||||
ret = str_append_str(str, ptab->rep_val);
|
||||
ret = str_append_str(str,
|
||||
ptab->rep_val);
|
||||
else {
|
||||
char *t = ptab->rep_func(str->pool, ptab->rep_func_input);
|
||||
char *t = ptab->rep_func(
|
||||
str->pool,
|
||||
ptab->rep_func_input);
|
||||
|
||||
ret = str_append_str(str, t);
|
||||
talloc_free(t);
|
||||
}
|
||||
|
||||
38
src/str.h
38
src/str.h
@@ -27,17 +27,19 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define STR_TAB_INIT(t, s_t) memset(t, 0, s_t)
|
||||
#define STR_TAB_SET(i,pat,val) { \
|
||||
tab[i].pattern = pat; \
|
||||
tab[i].pattern_length = sizeof(pat)-1; \
|
||||
tab[i].rep_val = val; \
|
||||
#define STR_TAB_SET(i, pat, val) \
|
||||
{ \
|
||||
tab[i].pattern = pat; \
|
||||
tab[i].pattern_length = sizeof(pat) - 1; \
|
||||
tab[i].rep_val = val; \
|
||||
}
|
||||
#define STR_TAB_SET_FUNC(i,pat,func,funcinput) { \
|
||||
tab[i].pattern = pat; \
|
||||
tab[i].pattern_length = sizeof(pat)-1; \
|
||||
tab[i].rep_val = NULL; \
|
||||
tab[i].rep_func = func; \
|
||||
tab[i].rep_func_input = funcinput; \
|
||||
#define STR_TAB_SET_FUNC(i, pat, func, funcinput) \
|
||||
{ \
|
||||
tab[i].pattern = pat; \
|
||||
tab[i].pattern_length = sizeof(pat) - 1; \
|
||||
tab[i].rep_val = NULL; \
|
||||
tab[i].rep_func = func; \
|
||||
tab[i].rep_func_input = funcinput; \
|
||||
}
|
||||
#define STR_TAB_TERM(i) tab[i].pattern = NULL
|
||||
|
||||
@@ -45,22 +47,22 @@ typedef char *(*str_get_func)(void *pool, const char *input);
|
||||
|
||||
typedef struct {
|
||||
const char *pattern;
|
||||
unsigned pattern_length;
|
||||
unsigned int pattern_length;
|
||||
const char *rep_val;
|
||||
str_get_func rep_func;
|
||||
const void *rep_func_input;
|
||||
} str_rep_tab;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *allocd; /* pointer to allocated data */
|
||||
uint8_t *data; /* API: pointer to data to copy from */
|
||||
uint8_t *allocd; /* pointer to allocated data */
|
||||
uint8_t *data; /* API: pointer to data to copy from */
|
||||
size_t max_length;
|
||||
size_t length; /* API: current length */
|
||||
size_t length; /* API: current length */
|
||||
void *pool;
|
||||
} str_st;
|
||||
|
||||
/* Initialize a buffer */
|
||||
inline static void str_init(str_st * str, void *pool)
|
||||
inline static void str_init(str_st *str, void *pool)
|
||||
{
|
||||
str->data = str->allocd = NULL;
|
||||
str->max_length = 0;
|
||||
@@ -72,7 +74,7 @@ inline static void str_init(str_st * str, void *pool)
|
||||
void str_clear(str_st *);
|
||||
|
||||
/* Set the buffer data to be of zero length */
|
||||
inline static void str_reset(str_st * buf)
|
||||
inline static void str_reset(str_st *buf)
|
||||
{
|
||||
buf->data = buf->allocd;
|
||||
buf->length = 0;
|
||||
@@ -87,6 +89,8 @@ int str_append_data(str_st *, const void *data, size_t data_size);
|
||||
int str_append_size(str_st *, size_t data_size);
|
||||
int str_append_data_prefix1(str_st *, const void *data, size_t data_size);
|
||||
|
||||
#define str_append_str_prefix1(s, str) (((str)==NULL)?str_append_data_prefix1(s, NULL, 0):str_append_data_prefix1(s, str, strlen(str)))
|
||||
#define str_append_str_prefix1(s, str) \
|
||||
(((str) == NULL) ? str_append_data_prefix1(s, NULL, 0) : \
|
||||
str_append_data_prefix1(s, str, strlen(str)))
|
||||
|
||||
#endif
|
||||
|
||||
111
src/subconfig.c
111
src/subconfig.c
@@ -29,10 +29,12 @@
|
||||
#include <vpn.h>
|
||||
#include "common-config.h"
|
||||
|
||||
static void free_expanded_brackets_string(subcfg_val_st out[MAX_SUBOPTIONS], unsigned size)
|
||||
static void free_expanded_brackets_string(subcfg_val_st out[MAX_SUBOPTIONS],
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned i;
|
||||
for (i=0;i<size;i++) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
talloc_free(out[i].name);
|
||||
talloc_free(out[i].value);
|
||||
}
|
||||
@@ -40,12 +42,12 @@ static void free_expanded_brackets_string(subcfg_val_st out[MAX_SUBOPTIONS], uns
|
||||
|
||||
/* Returns the number of suboptions processed.
|
||||
*/
|
||||
static
|
||||
unsigned expand_brackets_string(void *pool, const char *str, subcfg_val_st out[MAX_SUBOPTIONS])
|
||||
static unsigned int expand_brackets_string(void *pool, const char *str,
|
||||
subcfg_val_st out[MAX_SUBOPTIONS])
|
||||
{
|
||||
char *p, *p2, *p3;
|
||||
unsigned len, len2;
|
||||
unsigned pos = 0, finish = 0;
|
||||
unsigned int len, len2;
|
||||
unsigned int pos = 0, finish = 0;
|
||||
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
@@ -82,19 +84,19 @@ unsigned expand_brackets_string(void *pool, const char *str, subcfg_val_st out[M
|
||||
len2 = p3 - p2;
|
||||
|
||||
if (len > 0) {
|
||||
while (isspace(p[len-1]))
|
||||
while (isspace(p[len - 1]))
|
||||
len--;
|
||||
}
|
||||
if (len2 > 0) {
|
||||
while (isspace(p2[len2-1]))
|
||||
while (isspace(p2[len2 - 1]))
|
||||
len2--;
|
||||
}
|
||||
|
||||
out[pos].name = talloc_strndup(pool, p, len);
|
||||
out[pos].value = talloc_strndup(pool, p2, len2);
|
||||
pos++;
|
||||
p = p2+len2;
|
||||
while (isspace(*p)||*p==',')
|
||||
p = p2 + len2;
|
||||
while (isspace(*p) || *p == ',')
|
||||
p++;
|
||||
} while (finish == 0 && pos < MAX_SUBOPTIONS);
|
||||
|
||||
@@ -102,10 +104,11 @@ unsigned expand_brackets_string(void *pool, const char *str, subcfg_val_st out[M
|
||||
}
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
void *gssapi_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str)
|
||||
void *gssapi_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str)
|
||||
{
|
||||
subcfg_val_st vals[MAX_SUBOPTIONS];
|
||||
unsigned vals_size, i;
|
||||
unsigned int vals_size, i;
|
||||
gssapi_cfg_st *additional;
|
||||
|
||||
additional = talloc_zero(pool, gssapi_cfg_st);
|
||||
@@ -114,22 +117,27 @@ void *gssapi_get_brackets_string(void *pool, struct perm_cfg_st *config, const c
|
||||
}
|
||||
|
||||
vals_size = expand_brackets_string(pool, str, vals);
|
||||
for (i=0;i<vals_size;i++) {
|
||||
for (i = 0; i < vals_size; i++) {
|
||||
if (strcasecmp(vals[i].name, "keytab") == 0) {
|
||||
additional->keytab = vals[i].value;
|
||||
vals[i].value = NULL;
|
||||
} else if (strcasecmp(vals[i].name, "require-local-user-map") == 0) {
|
||||
additional->no_local_map = 1-CHECK_TRUE(vals[i].value);
|
||||
} else if (strcasecmp(vals[i].name, "tgt-freshness-time") == 0) {
|
||||
} else if (strcasecmp(vals[i].name, "require-local-user-map") ==
|
||||
0) {
|
||||
additional->no_local_map =
|
||||
1 - CHECK_TRUE(vals[i].value);
|
||||
} else if (strcasecmp(vals[i].name, "tgt-freshness-time") ==
|
||||
0) {
|
||||
additional->ticket_freshness_secs = atoi(vals[i].value);
|
||||
if (additional->ticket_freshness_secs == 0) {
|
||||
fprintf(stderr, "Invalid value for '%s': %s\n", vals[i].name, vals[i].value);
|
||||
fprintf(stderr, "Invalid value for '%s': %s\n",
|
||||
vals[i].name, vals[i].value);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (strcasecmp(vals[i].name, "gid-min") == 0) {
|
||||
additional->gid_min = atoi(vals[i].value);
|
||||
if (additional->gid_min < 0) {
|
||||
fprintf(stderr, "error in gid-min value: %d\n", additional->gid_min);
|
||||
fprintf(stderr, "error in gid-min value: %d\n",
|
||||
additional->gid_min);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
@@ -145,7 +153,7 @@ void *gssapi_get_brackets_string(void *pool, struct perm_cfg_st *config, const c
|
||||
void *get_brackets_string1(void *pool, const char *str)
|
||||
{
|
||||
char *p, *p2;
|
||||
unsigned len;
|
||||
unsigned int len;
|
||||
|
||||
p = strchr(str, '[');
|
||||
if (p == NULL) {
|
||||
@@ -173,7 +181,7 @@ void *get_brackets_string1(void *pool, const char *str)
|
||||
static void *get_brackets_string2(void *pool, const char *str)
|
||||
{
|
||||
char *p, *p2;
|
||||
unsigned len;
|
||||
unsigned int len;
|
||||
|
||||
p = strchr(str, '[');
|
||||
if (p == NULL) {
|
||||
@@ -204,11 +212,12 @@ static void *get_brackets_string2(void *pool, const char *str)
|
||||
return talloc_strndup(pool, p, len);
|
||||
}
|
||||
|
||||
void *radius_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str)
|
||||
void *radius_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str)
|
||||
{
|
||||
char *p;
|
||||
subcfg_val_st vals[MAX_SUBOPTIONS];
|
||||
unsigned vals_size, i;
|
||||
unsigned int vals_size, i;
|
||||
radius_cfg_st *additional;
|
||||
|
||||
additional = talloc_zero(pool, radius_cfg_st);
|
||||
@@ -216,13 +225,16 @@ void *radius_get_brackets_string(void *pool, struct perm_cfg_st *config, const c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (str && str[0] == '[' && (str[1] == '/' || str[1] == '.')) { /* legacy format */
|
||||
if (str && str[0] == '[' &&
|
||||
(str[1] == '/' || str[1] == '.')) { /* legacy format */
|
||||
additional->config = get_brackets_string1(pool, str);
|
||||
|
||||
p = get_brackets_string2(config, str);
|
||||
if (p != NULL) {
|
||||
if (strcasecmp(p, "groupconfig") != 0) {
|
||||
fprintf(stderr, "No known configuration option: %s\n", p);
|
||||
fprintf(stderr,
|
||||
"No known configuration option: %s\n",
|
||||
p);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
config->sup_config_type = SUP_CONFIG_RADIUS;
|
||||
@@ -230,18 +242,22 @@ void *radius_get_brackets_string(void *pool, struct perm_cfg_st *config, const c
|
||||
} else {
|
||||
/* new format */
|
||||
vals_size = expand_brackets_string(pool, str, vals);
|
||||
for (i=0;i<vals_size;i++) {
|
||||
for (i = 0; i < vals_size; i++) {
|
||||
if (strcasecmp(vals[i].name, "config") == 0) {
|
||||
additional->config = vals[i].value;
|
||||
vals[i].value = NULL;
|
||||
} else if (strcasecmp(vals[i].name, "nas-identifier") == 0) {
|
||||
} else if (strcasecmp(vals[i].name, "nas-identifier") ==
|
||||
0) {
|
||||
additional->nas_identifier = vals[i].value;
|
||||
vals[i].value = NULL;
|
||||
} else if (strcasecmp(vals[i].name, "groupconfig") == 0) {
|
||||
} else if (strcasecmp(vals[i].name, "groupconfig") ==
|
||||
0) {
|
||||
if (CHECK_TRUE(vals[i].value))
|
||||
config->sup_config_type = SUP_CONFIG_RADIUS;
|
||||
config->sup_config_type =
|
||||
SUP_CONFIG_RADIUS;
|
||||
} else {
|
||||
fprintf(stderr, "unknown option '%s'\n", vals[i].name);
|
||||
fprintf(stderr, "unknown option '%s'\n",
|
||||
vals[i].name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -258,10 +274,11 @@ void *radius_get_brackets_string(void *pool, struct perm_cfg_st *config, const c
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PAM
|
||||
void *pam_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str)
|
||||
void *pam_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str)
|
||||
{
|
||||
subcfg_val_st vals[MAX_SUBOPTIONS];
|
||||
unsigned vals_size, i;
|
||||
unsigned int vals_size, i;
|
||||
pam_cfg_st *additional;
|
||||
|
||||
additional = talloc_zero(pool, pam_cfg_st);
|
||||
@@ -271,11 +288,12 @@ void *pam_get_brackets_string(void *pool, struct perm_cfg_st *config, const char
|
||||
|
||||
/* new format */
|
||||
vals_size = expand_brackets_string(pool, str, vals);
|
||||
for (i=0;i<vals_size;i++) {
|
||||
for (i = 0; i < vals_size; i++) {
|
||||
if (strcasecmp(vals[i].name, "gid-min") == 0) {
|
||||
additional->gid_min = atoi(vals[i].value);
|
||||
if (additional->gid_min < 0) {
|
||||
fprintf(stderr, "error in gid-min value: %d\n", additional->gid_min);
|
||||
fprintf(stderr, "error in gid-min value: %d\n",
|
||||
additional->gid_min);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
@@ -289,10 +307,11 @@ void *pam_get_brackets_string(void *pool, struct perm_cfg_st *config, const char
|
||||
}
|
||||
#endif
|
||||
|
||||
void *plain_get_brackets_string(void *pool, struct perm_cfg_st *config, const char *str)
|
||||
void *plain_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str)
|
||||
{
|
||||
subcfg_val_st vals[MAX_SUBOPTIONS];
|
||||
unsigned vals_size, i;
|
||||
unsigned int vals_size, i;
|
||||
plain_cfg_st *additional;
|
||||
|
||||
additional = talloc_zero(pool, plain_cfg_st);
|
||||
@@ -300,11 +319,12 @@ void *plain_get_brackets_string(void *pool, struct perm_cfg_st *config, const ch
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (str && str[0] == '[' && (str[1] == '/' || str[1] == '.')) { /* legacy format */
|
||||
if (str && str[0] == '[' &&
|
||||
(str[1] == '/' || str[1] == '.')) { /* legacy format */
|
||||
additional->passwd = get_brackets_string1(pool, str);
|
||||
} else {
|
||||
vals_size = expand_brackets_string(pool, str, vals);
|
||||
for (i=0;i<vals_size;i++) {
|
||||
for (i = 0; i < vals_size; i++) {
|
||||
if (strcasecmp(vals[i].name, "passwd") == 0) {
|
||||
additional->passwd = vals[i].value;
|
||||
vals[i].value = NULL;
|
||||
@@ -314,7 +334,8 @@ void *plain_get_brackets_string(void *pool, struct perm_cfg_st *config, const ch
|
||||
vals[i].value = NULL;
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr, "unknown option '%s'\n", vals[i].name);
|
||||
fprintf(stderr, "unknown option '%s'\n",
|
||||
vals[i].name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -329,17 +350,17 @@ void *plain_get_brackets_string(void *pool, struct perm_cfg_st *config, const ch
|
||||
return additional;
|
||||
}
|
||||
|
||||
|
||||
void *oidc_get_brackets_string(void * pool, struct perm_cfg_st *config, const char *str)
|
||||
void *oidc_get_brackets_string(void *pool, struct perm_cfg_st *config,
|
||||
const char *str)
|
||||
{
|
||||
subcfg_val_st vals[MAX_SUBOPTIONS];
|
||||
char * additional = NULL;
|
||||
char *additional = NULL;
|
||||
|
||||
unsigned vals_size, i;
|
||||
unsigned int vals_size, i;
|
||||
|
||||
vals_size = expand_brackets_string(pool, str, vals);
|
||||
vals_size = expand_brackets_string(pool, str, vals);
|
||||
|
||||
for (i = 0; i < vals_size; i ++) {
|
||||
for (i = 0; i < vals_size; i++) {
|
||||
if (strcasecmp(vals[i].name, "config") == 0) {
|
||||
additional = talloc_strdup(pool, vals[i].value);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user