mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-14 02:22:03 +08:00
Added the select-group and auto-select-group config options.
These options allow to prompt the user for a group prior to login. That in addition enhances the password file format and multiple groups can be specified on a comma separated list, as: user:group1,group2,group3:$5$encodedpassword
This commit is contained in:
committed by
Nikos Mavrogiannopoulos
parent
6bc625df81
commit
4755ee48c5
@@ -271,6 +271,19 @@ route = 192.168.5.0/255.255.255.0
|
|||||||
#default-user-config = /etc/ocserv/defaults/user.conf
|
#default-user-config = /etc/ocserv/defaults/user.conf
|
||||||
#default-group-config = /etc/ocserv/defaults/group.conf
|
#default-group-config = /etc/ocserv/defaults/group.conf
|
||||||
|
|
||||||
|
# Groups that a client is allowed to select from.
|
||||||
|
# A client may belong in multiple groups, and in certain use-cases
|
||||||
|
# it is needed to switch between them. For these cases the client can
|
||||||
|
# select prior to authentication. Add multiple entries for multiple groups.
|
||||||
|
#select-group = group1
|
||||||
|
#select-group = group2
|
||||||
|
#select-group = tost
|
||||||
|
|
||||||
|
# Instead of specifying manually all the allowed groups, you may instruct
|
||||||
|
# ocserv to scan all available groups and include the full list. That
|
||||||
|
# option is only functional on plain authentication.
|
||||||
|
#auto-select-group = true
|
||||||
|
|
||||||
# The system command to use to setup a route. %R will be replaced with the
|
# The system command to use to setup a route. %R will be replaced with the
|
||||||
# route/mask and %D with the (tun) device.
|
# route/mask and %D with the (tun) device.
|
||||||
#
|
#
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
test:tost:$5$i6SNmLDCgBNjyJ7q$SZ4bVJb7I/DLgXo3txHBVohRFBjOtdbxGQZp.DOnrA.
|
test:tost , group1 , group2:$5$i6SNmLDCgBNjyJ7q$SZ4bVJb7I/DLgXo3txHBVohRFBjOtdbxGQZp.DOnrA.
|
||||||
tost:*:$5$qc1CKWjcmlrFREe2$h9zQJcD3AeuQmwMncdIqqls47TDOUvu2r2nXQ7aDfcD
|
tost:*:$5$qc1CKWjcmlrFREe2$h9zQJcD3AeuQmwMncdIqqls47TDOUvu2r2nXQ7aDfcD
|
||||||
|
|||||||
+29
-5
@@ -264,17 +264,40 @@ struct pam_ctx_st * pctx = ctx;
|
|||||||
|
|
||||||
/* Returns 0 if the user is successfully authenticated
|
/* Returns 0 if the user is successfully authenticated
|
||||||
*/
|
*/
|
||||||
static int pam_auth_group(void* ctx, char *groupname, int groupname_size)
|
static int pam_auth_group(void* ctx, const char *suggested, char *groupname, int groupname_size)
|
||||||
{
|
{
|
||||||
struct passwd * pwd;
|
struct passwd * pwd;
|
||||||
struct pam_ctx_st * pctx = ctx;
|
struct pam_ctx_st * pctx = ctx;
|
||||||
|
struct group *grp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
groupname[0] = 0;
|
groupname[0] = 0;
|
||||||
|
|
||||||
pwd = getpwnam(pctx->username);
|
pwd = getpwnam(pctx->username);
|
||||||
if (pwd != NULL) {
|
if (pwd != NULL) {
|
||||||
struct group* grp = getgrgid(pwd->pw_gid);
|
if (suggested != NULL) {
|
||||||
if (grp != NULL)
|
gid_t groups[MAX_GROUPS];
|
||||||
snprintf(groupname, groupname_size, "%s", grp->gr_name);
|
int ngroups = sizeof(groups)/sizeof(groups[0]);
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
ret = getgrouplist(pctx->username, pwd->pw_gid, groups, &ngroups);
|
||||||
|
if (ret <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<ngroups;i++) {
|
||||||
|
grp = getgrgid(groups[i]);
|
||||||
|
if (grp != NULL && strcmp(suggested, grp->gr_name) == 0) {
|
||||||
|
snprintf(groupname, groupname_size, "%s", grp->gr_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
struct group* grp = getgrgid(pwd->pw_gid);
|
||||||
|
if (grp != NULL)
|
||||||
|
snprintf(groupname, groupname_size, "%s", grp->gr_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -322,7 +345,8 @@ const struct auth_mod_st pam_auth_funcs = {
|
|||||||
.auth_msg = pam_auth_msg,
|
.auth_msg = pam_auth_msg,
|
||||||
.auth_pass = pam_auth_pass,
|
.auth_pass = pam_auth_pass,
|
||||||
.auth_group = pam_auth_group,
|
.auth_group = pam_auth_group,
|
||||||
.auth_user = pam_auth_user
|
.auth_user = pam_auth_user,
|
||||||
|
.group_list = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+167
-14
@@ -24,7 +24,10 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vpn.h>
|
#include <vpn.h>
|
||||||
|
#include <c-ctype.h>
|
||||||
#include "plain.h"
|
#include "plain.h"
|
||||||
|
#include <ccan/htable/htable.h>
|
||||||
|
#include <ccan/hash/hash.h>
|
||||||
|
|
||||||
#define MAX_CPASS_SIZE 128
|
#define MAX_CPASS_SIZE 128
|
||||||
#define MAX_TRIES 3
|
#define MAX_TRIES 3
|
||||||
@@ -35,17 +38,66 @@ const char* pass_msg_failed = "Login failed.\nPlease enter your password.";
|
|||||||
struct plain_ctx_st {
|
struct plain_ctx_st {
|
||||||
char username[MAX_USERNAME_SIZE];
|
char username[MAX_USERNAME_SIZE];
|
||||||
char cpass[MAX_CPASS_SIZE]; /* crypt() passwd */
|
char cpass[MAX_CPASS_SIZE]; /* crypt() passwd */
|
||||||
char groupname[MAX_GROUPNAME_SIZE];
|
|
||||||
|
char *groupnames[MAX_GROUPS];
|
||||||
|
unsigned groupnames_size;
|
||||||
|
|
||||||
const char *passwd; /* password file */
|
const char *passwd; /* password file */
|
||||||
const char *pass_msg;
|
const char *pass_msg;
|
||||||
unsigned retries;
|
unsigned retries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
char *p = talloc_strdup(pool, text);
|
||||||
|
char *p2;
|
||||||
|
unsigned len;
|
||||||
|
|
||||||
|
*elements = 0;
|
||||||
|
|
||||||
|
if (p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
broken_text[*elements] = p;
|
||||||
|
(*elements)++;
|
||||||
|
|
||||||
|
p = strchr(p, ',');
|
||||||
|
if (p) {
|
||||||
|
*p = 0;
|
||||||
|
len = p - broken_text[*elements-1];
|
||||||
|
|
||||||
|
/* remove any trailing space */
|
||||||
|
p2 = p-1;
|
||||||
|
while (c_isspace(*p2)) {
|
||||||
|
*p2 = 0;
|
||||||
|
p2--;
|
||||||
|
}
|
||||||
|
|
||||||
|
p++; /* move to next entry and skip white
|
||||||
|
* space.
|
||||||
|
*/
|
||||||
|
while (c_isspace(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (len == 1) {
|
||||||
|
/* skip the group */
|
||||||
|
(*elements)--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (p != NULL && *elements < MAX_GROUPS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name.
|
/* Returns 0 if the user is successfully authenticated, and sets the appropriate group name.
|
||||||
*/
|
*/
|
||||||
static int read_auth_pass(struct plain_ctx_st *pctx)
|
static int read_auth_pass(struct plain_ctx_st *pctx)
|
||||||
{
|
{
|
||||||
unsigned groupname_size;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char line[512];
|
char line[512];
|
||||||
ssize_t ll;
|
ssize_t ll;
|
||||||
@@ -81,12 +133,7 @@ static int read_auth_pass(struct plain_ctx_st *pctx)
|
|||||||
if (p != NULL && strcmp(pctx->username, p) == 0) {
|
if (p != NULL && strcmp(pctx->username, p) == 0) {
|
||||||
p = strtok_r(NULL, ":", &sp);
|
p = strtok_r(NULL, ":", &sp);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
groupname_size = sizeof(pctx->groupname);
|
break_group_list(pctx, p, pctx->groupnames, &pctx->groupnames_size);
|
||||||
groupname_size =
|
|
||||||
snprintf(pctx->groupname, groupname_size,
|
|
||||||
"%s", p);
|
|
||||||
if (groupname_size == 1) /* values like '*' or 'x' indicate empty group */
|
|
||||||
pctx->groupname[0] = 0;
|
|
||||||
|
|
||||||
p = strtok_r(NULL, ":", &sp);
|
p = strtok_r(NULL, ":", &sp);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
@@ -118,10 +165,7 @@ static int plain_auth_init(void **ctx, void *pool, const char *username, const c
|
|||||||
return ERR_AUTH_FAIL;
|
return ERR_AUTH_FAIL;
|
||||||
|
|
||||||
snprintf(pctx->username, sizeof(pctx->username), "%s", username);
|
snprintf(pctx->username, sizeof(pctx->username), "%s", username);
|
||||||
pctx->groupname[0] = 0;
|
|
||||||
pctx->cpass[0] = 0;
|
|
||||||
pctx->passwd = additional;
|
pctx->passwd = additional;
|
||||||
pctx->retries = 0;
|
|
||||||
pctx->pass_msg = pass_msg_first;
|
pctx->pass_msg = pass_msg_first;
|
||||||
|
|
||||||
ret = read_auth_pass(pctx);
|
ret = read_auth_pass(pctx);
|
||||||
@@ -135,12 +179,25 @@ static int plain_auth_init(void **ctx, void *pool, const char *username, const c
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int plain_auth_group(void *ctx, 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;
|
struct plain_ctx_st *pctx = ctx;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
snprintf(groupname, groupname_size, "%s", pctx->groupname);
|
groupname[0] = 0;
|
||||||
|
|
||||||
|
if (suggested != NULL) {
|
||||||
|
for (i=0;i<pctx->groupnames_size;i++) {
|
||||||
|
if (strcmp(suggested, pctx->groupnames[i]) == 0) {
|
||||||
|
snprintf(groupname, groupname_size, "%s", pctx->groupnames[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pctx->groupnames_size > 0 && groupname[0] == 0) {
|
||||||
|
snprintf(groupname, groupname_size, "%s", pctx->groupnames[0]);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,6 +242,101 @@ static void plain_auth_deinit(void *ctx)
|
|||||||
talloc_free(ctx);
|
talloc_free(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)
|
||||||
|
{
|
||||||
|
const char *c1 = _c1, *c2 = c2;
|
||||||
|
|
||||||
|
if (strcmp(c1, c2) == 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plain_group_list(void *pool, void *additional, char ***groupname, unsigned *groupname_size)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char line[512];
|
||||||
|
ssize_t ll;
|
||||||
|
char *p, *sp;
|
||||||
|
unsigned i;
|
||||||
|
size_t hval;
|
||||||
|
struct htable_iter iter;
|
||||||
|
char *tgroup[MAX_GROUPS];
|
||||||
|
unsigned tgroup_size;
|
||||||
|
struct htable hash;
|
||||||
|
|
||||||
|
htable_init(&hash, rehash, NULL);
|
||||||
|
|
||||||
|
pool = talloc_init("plain");
|
||||||
|
fp = fopen(additional, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
syslog(LOG_AUTH,
|
||||||
|
"error in plain authentication; cannot open: %s",
|
||||||
|
(char*)additional);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line[sizeof(line)-1] = 0;
|
||||||
|
while ((p=fgets(line, sizeof(line)-1, fp)) != NULL) {
|
||||||
|
ll = strlen(p);
|
||||||
|
|
||||||
|
if (ll <= 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (line[ll - 1] == '\n') {
|
||||||
|
ll--;
|
||||||
|
line[ll] = 0;
|
||||||
|
}
|
||||||
|
if (line[ll - 1] == '\r') {
|
||||||
|
ll--;
|
||||||
|
line[ll] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strtok_r(line, ":", &sp);
|
||||||
|
|
||||||
|
if (p != NULL) {
|
||||||
|
p = strtok_r(NULL, ":", &sp);
|
||||||
|
if (p != NULL) {
|
||||||
|
break_group_list(pool, p, tgroup, &tgroup_size);
|
||||||
|
|
||||||
|
for (i=0;i<tgroup_size;i++) {
|
||||||
|
hval = rehash(tgroup[i], NULL);
|
||||||
|
|
||||||
|
if (htable_get(&hash, hval, str_cmp, tgroup[i]) == NULL) {
|
||||||
|
if (strlen(tgroup[i]) > 1)
|
||||||
|
htable_add(&hash, hval, tgroup[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*groupname_size = 0;
|
||||||
|
*groupname = talloc_size(pool, sizeof(char*)*MAX_GROUPS);
|
||||||
|
if (*groupname == NULL) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = htable_first(&hash, &iter);
|
||||||
|
while (p != NULL) {
|
||||||
|
(*groupname)[(*groupname_size)] = talloc_strdup(*groupname, p);
|
||||||
|
p = htable_next(&hash, &iter);
|
||||||
|
(*groupname_size)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* always succeed */
|
||||||
|
exit:
|
||||||
|
htable_clear(&hash);
|
||||||
|
safe_memset(line, 0, sizeof(line));
|
||||||
|
fclose(fp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const struct auth_mod_st plain_auth_funcs = {
|
const struct auth_mod_st plain_auth_funcs = {
|
||||||
.type = AUTH_TYPE_PLAIN | AUTH_TYPE_USERNAME_PASS,
|
.type = AUTH_TYPE_PLAIN | AUTH_TYPE_USERNAME_PASS,
|
||||||
.auth_init = plain_auth_init,
|
.auth_init = plain_auth_init,
|
||||||
@@ -192,5 +344,6 @@ const struct auth_mod_st plain_auth_funcs = {
|
|||||||
.auth_msg = plain_auth_msg,
|
.auth_msg = plain_auth_msg,
|
||||||
.auth_pass = plain_auth_pass,
|
.auth_pass = plain_auth_pass,
|
||||||
.auth_user = plain_auth_user,
|
.auth_user = plain_auth_user,
|
||||||
.auth_group = plain_auth_group
|
.auth_group = plain_auth_group,
|
||||||
|
.group_list = plain_group_list
|
||||||
};
|
};
|
||||||
|
|||||||
+19
-1
@@ -30,8 +30,11 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <c-strcase.h>
|
#include <c-strcase.h>
|
||||||
|
#include <auth/pam.h>
|
||||||
|
#include <auth/plain.h>
|
||||||
|
|
||||||
#include <vpn.h>
|
#include <vpn.h>
|
||||||
|
#include <main.h>
|
||||||
#include <ctl.h>
|
#include <ctl.h>
|
||||||
#include <tlslib.h>
|
#include <tlslib.h>
|
||||||
|
|
||||||
@@ -51,6 +54,7 @@ struct cfg_options {
|
|||||||
static struct cfg_options available_options[] = {
|
static struct cfg_options available_options[] = {
|
||||||
{ .name = "auth", .type = OPTION_MULTI_LINE, .mandatory = 1 },
|
{ .name = "auth", .type = OPTION_MULTI_LINE, .mandatory = 1 },
|
||||||
{ .name = "route", .type = OPTION_MULTI_LINE, .mandatory = 0 },
|
{ .name = "route", .type = OPTION_MULTI_LINE, .mandatory = 0 },
|
||||||
|
{ .name = "select-group", .type = OPTION_MULTI_LINE, .mandatory = 0 },
|
||||||
{ .name = "custom-header", .type = OPTION_MULTI_LINE, .mandatory = 0 },
|
{ .name = "custom-header", .type = OPTION_MULTI_LINE, .mandatory = 0 },
|
||||||
{ .name = "split-dns", .type = OPTION_MULTI_LINE, .mandatory = 0 },
|
{ .name = "split-dns", .type = OPTION_MULTI_LINE, .mandatory = 0 },
|
||||||
{ .name = "listen-host", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "listen-host", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
@@ -79,6 +83,7 @@ static struct cfg_options available_options[] = {
|
|||||||
{ .name = "occtl-socket-file", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "occtl-socket-file", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
{ .name = "banner", .type = OPTION_STRING, .mandatory = 0 },
|
{ .name = "banner", .type = OPTION_STRING, .mandatory = 0 },
|
||||||
{ .name = "predictable-ips", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
{ .name = "predictable-ips", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
||||||
|
{ .name = "auto-select-group", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
||||||
/* this is alias for cisco-client-compat */
|
/* this is alias for cisco-client-compat */
|
||||||
{ .name = "always-require-cert", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
{ .name = "always-require-cert", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
||||||
{ .name = "cisco-client-compat", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
{ .name = "cisco-client-compat", .type = OPTION_BOOLEAN, .mandatory = 0 },
|
||||||
@@ -257,7 +262,8 @@ const tOptionValue* val, *prev;
|
|||||||
unsigned j, i, mand;
|
unsigned j, i, mand;
|
||||||
char** auth = NULL;
|
char** auth = NULL;
|
||||||
unsigned auth_size = 0;
|
unsigned auth_size = 0;
|
||||||
unsigned prefix = 0;
|
unsigned prefix = 0, auto_select_group = 0;
|
||||||
|
const struct auth_mod_st *amod = NULL;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
unsigned force_cert_auth;
|
unsigned force_cert_auth;
|
||||||
|
|
||||||
@@ -294,6 +300,7 @@ unsigned force_cert_auth;
|
|||||||
}
|
}
|
||||||
#ifdef HAVE_PAM
|
#ifdef HAVE_PAM
|
||||||
config->auth_types |= AUTH_TYPE_PAM;
|
config->auth_types |= AUTH_TYPE_PAM;
|
||||||
|
amod = &pam_auth_funcs;
|
||||||
#else
|
#else
|
||||||
fprintf(stderr, "PAM support is disabled\n");
|
fprintf(stderr, "PAM support is disabled\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -313,6 +320,7 @@ unsigned force_cert_auth;
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
amod = &plain_auth_funcs;
|
||||||
config->auth_types |= AUTH_TYPE_PLAIN;
|
config->auth_types |= AUTH_TYPE_PLAIN;
|
||||||
} else if (c_strcasecmp(auth[j], "certificate") == 0) {
|
} else if (c_strcasecmp(auth[j], "certificate") == 0) {
|
||||||
config->auth_types |= AUTH_TYPE_CERTIFICATE;
|
config->auth_types |= AUTH_TYPE_CERTIFICATE;
|
||||||
@@ -492,6 +500,13 @@ unsigned force_cert_auth;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
READ_TF("auto-select-group", auto_select_group, 0);
|
||||||
|
if (auto_select_group != 0 && amod != NULL && amod->group_list != NULL) {
|
||||||
|
amod->group_list(config, config->plain_passwd, &config->group_list, &config->group_list_size);
|
||||||
|
} else {
|
||||||
|
READ_MULTI_LINE("select-group", config->group_list, config->group_list_size);
|
||||||
|
}
|
||||||
|
|
||||||
READ_MULTI_LINE("dns", config->network.dns, config->network.dns_size);
|
READ_MULTI_LINE("dns", config->network.dns, config->network.dns_size);
|
||||||
if (config->network.dns_size == 0) {
|
if (config->network.dns_size == 0) {
|
||||||
/* try the aliases */
|
/* try the aliases */
|
||||||
@@ -691,6 +706,9 @@ unsigned i;
|
|||||||
for (i=0;i<config->split_dns_size;i++)
|
for (i=0;i<config->split_dns_size;i++)
|
||||||
DEL(config->split_dns[i]);
|
DEL(config->split_dns[i]);
|
||||||
DEL(config->split_dns);
|
DEL(config->split_dns);
|
||||||
|
for (i=0;i<config->group_list_size;i++)
|
||||||
|
DEL(config->group_list[i]);
|
||||||
|
DEL(config->group_list);
|
||||||
#ifdef HAVE_LIBTALLOC
|
#ifdef HAVE_LIBTALLOC
|
||||||
/* our included talloc don't include that */
|
/* our included talloc don't include that */
|
||||||
talloc_free_children(config);
|
talloc_free_children(config);
|
||||||
|
|||||||
+5
-4
@@ -129,10 +129,11 @@ message sec_auth_init_msg
|
|||||||
required bool user_present = 1;
|
required bool user_present = 1;
|
||||||
required bool tls_auth_ok = 2 [default = false];
|
required bool tls_auth_ok = 2 [default = false];
|
||||||
required string user_name = 3;
|
required string user_name = 3;
|
||||||
optional string cert_user_name = 4;
|
optional string group_name = 4; /* selected group name */
|
||||||
optional string cert_group_name = 5;
|
optional string cert_user_name = 5;
|
||||||
optional string hostname = 6;
|
optional string cert_group_name = 6;
|
||||||
required string ip = 7;
|
optional string hostname = 7;
|
||||||
|
required string ip = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SEC_AUTH_CONT */
|
/* SEC_AUTH_CONT */
|
||||||
|
|||||||
+1
-1
@@ -754,7 +754,7 @@ unsigned total = 10;
|
|||||||
|
|
||||||
if (reload_conf != 0) {
|
if (reload_conf != 0) {
|
||||||
mslog(s, NULL, LOG_INFO, "reloading configuration");
|
mslog(s, NULL, LOG_INFO, "reloading configuration");
|
||||||
reload_cfg_file(s->main_pool, &s->config);
|
reload_cfg_file(s->main_pool, s->config);
|
||||||
tls_reload_crl(s, s->creds);
|
tls_reload_crl(s, s->creds);
|
||||||
reload_conf = 0;
|
reload_conf = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@
|
|||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
|
||||||
int cmd_parser (void *pool, int argc, char **argv, struct cfg_st** config);
|
int cmd_parser (void *pool, int argc, char **argv, struct cfg_st** config);
|
||||||
void reload_cfg_file(void *pool, struct cfg_st** config);
|
void reload_cfg_file(void *pool, struct cfg_st* config);
|
||||||
void clear_cfg_file(struct cfg_st* config);
|
void clear_cfg_file(struct cfg_st* config);
|
||||||
void write_pid_file(void);
|
void write_pid_file(void);
|
||||||
void remove_pid_file(void);
|
void remove_pid_file(void);
|
||||||
|
|||||||
@@ -345,6 +345,18 @@ route = 192.168.1.0/255.255.255.0
|
|||||||
route = 192.168.5.0/255.255.255.0
|
route = 192.168.5.0/255.255.255.0
|
||||||
#route = fef4:db8:1000:1001::/64
|
#route = fef4:db8:1000:1001::/64
|
||||||
|
|
||||||
|
# Groups that a client is allowed to select from.
|
||||||
|
# A client may belong in multiple groups, and in certain use-cases
|
||||||
|
# it is needed to switch between them. For these cases the client can
|
||||||
|
# select prior to authentication. Add multiple entries for multiple groups.
|
||||||
|
#select-group = group1
|
||||||
|
#select-group = group2
|
||||||
|
|
||||||
|
# Instead of specifying manually all the allowed groups, you may instruct
|
||||||
|
# ocserv to scan all available groups and include the full list. That
|
||||||
|
# option is only functional on plain authentication.
|
||||||
|
#auto-select-group = true
|
||||||
|
|
||||||
# Configuration files that will be applied per user connection or
|
# Configuration files that will be applied per user connection or
|
||||||
# per group. Each file name on these directories must match the username
|
# per group. Each file name on these directories must match the username
|
||||||
# or the groupname.
|
# or the groupname.
|
||||||
|
|||||||
+1
-2
@@ -353,7 +353,6 @@ int handle_sec_auth_init(sec_mod_st * sec, const SecAuthInitMsg * req)
|
|||||||
snprintf(e->hostname, sizeof(e->hostname), "%s", req->hostname);
|
snprintf(e->hostname, sizeof(e->hostname), "%s", req->hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (sec->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
if (sec->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
||||||
/* req->username is non-null at this point */
|
/* req->username is non-null at this point */
|
||||||
ret =
|
ret =
|
||||||
@@ -364,7 +363,7 @@ int handle_sec_auth_init(sec_mod_st * sec, const SecAuthInitMsg * req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
module->auth_group(e->auth_ctx, e->groupname,
|
module->auth_group(e->auth_ctx, req->group_name, e->groupname,
|
||||||
sizeof(e->groupname));
|
sizeof(e->groupname));
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
+3
-1
@@ -24,15 +24,17 @@
|
|||||||
#include <main.h>
|
#include <main.h>
|
||||||
|
|
||||||
#define MAX_AUTH_REQS 8
|
#define MAX_AUTH_REQS 8
|
||||||
|
#define MAX_GROUPS 32
|
||||||
|
|
||||||
struct auth_mod_st {
|
struct auth_mod_st {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
int (*auth_init)(void** ctx, void *pool, const char* username, const char* ip, void* additional);
|
int (*auth_init)(void** ctx, void *pool, const char* username, const char* ip, void* additional);
|
||||||
int (*auth_msg)(void* ctx, char* msg, size_t msg_size);
|
int (*auth_msg)(void* ctx, char* msg, size_t msg_size);
|
||||||
int (*auth_pass)(void* ctx, const char* pass, unsigned pass_len);
|
int (*auth_pass)(void* ctx, const char* pass, unsigned pass_len);
|
||||||
int (*auth_group)(void* ctx, char *groupname, int groupname_size);
|
int (*auth_group)(void* ctx, const char *suggested, char *groupname, int groupname_size);
|
||||||
int (*auth_user)(void* ctx, char *groupname, int groupname_size);
|
int (*auth_user)(void* ctx, char *groupname, int groupname_size);
|
||||||
void (*auth_deinit)(void* ctx);
|
void (*auth_deinit)(void* ctx);
|
||||||
|
void (*group_list)(void *pool, void *additional, char ***groupname, unsigned *groupname_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
void main_auth_init(main_server_st *s);
|
void main_auth_init(main_server_st *s);
|
||||||
|
|||||||
@@ -199,6 +199,9 @@ struct cfg_st {
|
|||||||
char *ocsp_response; /* file with the OCSP response */
|
char *ocsp_response; /* file with the OCSP response */
|
||||||
char *default_domain; /* domain to be advertised */
|
char *default_domain; /* domain to be advertised */
|
||||||
|
|
||||||
|
char **group_list; /* select_group */
|
||||||
|
unsigned int group_list_size;
|
||||||
|
|
||||||
char **custom_header;
|
char **custom_header;
|
||||||
unsigned custom_header_size;;
|
unsigned custom_header_size;;
|
||||||
|
|
||||||
|
|||||||
+186
-208
@@ -54,22 +54,27 @@
|
|||||||
|
|
||||||
#define SUCCESS_MSG_FOOT "</auth></config-auth>\n"
|
#define SUCCESS_MSG_FOOT "</auth></config-auth>\n"
|
||||||
|
|
||||||
static const char login_msg_user[] =
|
static const char login_msg_user_start[] =
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<config-auth client=\"vpn\" type=\"auth-request\">\n"
|
"<config-auth client=\"vpn\" type=\"auth-request\">\n"
|
||||||
VERSION_MSG
|
VERSION_MSG
|
||||||
"<auth id=\"main\">\n"
|
"<auth id=\"main\">\n"
|
||||||
"<message>Please enter your username</message>\n"
|
"<message>Please enter your username</message>\n"
|
||||||
"<form method=\"post\" action=\"/auth\">\n"
|
"<form method=\"post\" action=\"/auth\">\n"
|
||||||
"<input type=\"text\" name=\"username\" label=\"Username:\" />\n"
|
"<input type=\"text\" name=\"username\" label=\"Username:\" />\n";
|
||||||
|
|
||||||
|
static const char login_msg_user_end[] =
|
||||||
"</form></auth>\n" "</config-auth>";
|
"</form></auth>\n" "</config-auth>";
|
||||||
|
|
||||||
static const char login_msg_no_user[] =
|
static const char login_msg_no_user_start[] =
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<config-auth client=\"vpn\" type=\"auth-request\">\n"
|
"<config-auth client=\"vpn\" type=\"auth-request\">\n"
|
||||||
VERSION_MSG
|
VERSION_MSG
|
||||||
"<auth id=\"main\">\n"
|
"<auth id=\"main\">\n"
|
||||||
"<message>%s</message>\n"
|
"<message>";
|
||||||
|
|
||||||
|
static const char login_msg_no_user_end[] =
|
||||||
|
"</message>\n"
|
||||||
"<form method=\"post\" action=\"/auth\">\n"
|
"<form method=\"post\" action=\"/auth\">\n"
|
||||||
"<input type=\"password\" name=\"password\" label=\"Password:\" />\n"
|
"<input type=\"password\" name=\"password\" label=\"Password:\" />\n"
|
||||||
"</form></auth></config-auth>\n";
|
"</form></auth></config-auth>\n";
|
||||||
@@ -77,9 +82,12 @@ static const char login_msg_no_user[] =
|
|||||||
int get_auth_handler2(worker_st * ws, unsigned http_ver, const char *pmsg)
|
int get_auth_handler2(worker_st * ws, unsigned http_ver, const char *pmsg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char login_msg[MAX_MSG_SIZE + sizeof(login_msg_user)];
|
|
||||||
char context[BASE64_LENGTH(SID_SIZE) + 1];
|
char context[BASE64_LENGTH(SID_SIZE) + 1];
|
||||||
unsigned int lsize;
|
char temp[128];
|
||||||
|
unsigned int i;
|
||||||
|
str_st str;
|
||||||
|
|
||||||
|
str_init(&str, ws);
|
||||||
|
|
||||||
tls_cork(ws->session);
|
tls_cork(ws->session);
|
||||||
ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver);
|
ret = tls_printf(ws->session, "HTTP/1.%u 200 OK\r\n", http_ver);
|
||||||
@@ -105,46 +113,111 @@ int get_auth_handler2(worker_st * ws, unsigned http_ver, const char *pmsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "Content-Type: text/xml\r\n");
|
ret = tls_puts(ws->session, "Content-Type: text/xml\r\n");
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (ws->auth_state == S_AUTH_REQ) {
|
if (ws->auth_state == S_AUTH_REQ) {
|
||||||
/* only ask password */
|
/* only ask password */
|
||||||
if (pmsg == NULL)
|
if (pmsg == NULL)
|
||||||
pmsg = "Please enter your password.";
|
pmsg = "Please enter your password.";
|
||||||
lsize =
|
|
||||||
snprintf(login_msg, sizeof(login_msg), login_msg_no_user,
|
ret = str_append_str(&str, login_msg_no_user_start);
|
||||||
pmsg);
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = str_append_str(&str, pmsg);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = str_append_str(&str, login_msg_no_user_end);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* ask for username only */
|
/* ask for username and group */
|
||||||
lsize =
|
ret = str_append_str(&str, login_msg_user_start);
|
||||||
snprintf(login_msg, sizeof(login_msg), "%s",
|
if (ret < 0) {
|
||||||
login_msg_user);
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send groups */
|
||||||
|
if (ws->groupname[0] == 0 && ws->config->group_list_size > 0) {
|
||||||
|
ret = str_append_str(&str, "<select name=\"group_list\" label=\"GROUP:\">\n");
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0;i<ws->config->group_list_size;i++) {
|
||||||
|
snprintf(temp, sizeof(temp), "<option>%s</option>\n", ws->config->group_list[i]);
|
||||||
|
ret = str_append_str(&str, temp);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = str_append_str(&str, "</select>\n");
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = str_append_str(&str, login_msg_user_end);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
tls_printf(ws->session, "Content-Length: %u\r\n",
|
tls_printf(ws->session, "Content-Length: %u\r\n",
|
||||||
(unsigned int)lsize);
|
(unsigned int)str.length);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
ret = tls_puts(ws->session, "X-Transcend-Version: 1\r\n");
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
ret = tls_puts(ws->session, "\r\n");
|
ret = tls_puts(ws->session, "\r\n");
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = tls_send(ws->session, str.data, str.length);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
ret = tls_send(ws->session, login_msg, lsize);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = tls_uncork(ws->session);
|
ret = tls_uncork(ws->session);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
str_clear(&str);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_auth_handler(worker_st * ws, unsigned http_ver)
|
int get_auth_handler(worker_st * ws, unsigned http_ver)
|
||||||
@@ -670,151 +743,93 @@ int post_common_handler(worker_st * ws, unsigned http_ver)
|
|||||||
* buffers.
|
* buffers.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
int read_user_pass(worker_st * ws, char *body, unsigned body_length,
|
int parse_reply(worker_st * ws, char *body, unsigned body_length,
|
||||||
char **username, char **password)
|
const char *field, unsigned field_size,
|
||||||
|
const char *xml_field, unsigned xml_field_size,
|
||||||
|
char **value)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
char temp1[64];
|
||||||
|
char temp2[64];
|
||||||
|
unsigned temp2_len, temp1_len;
|
||||||
|
unsigned len;
|
||||||
|
|
||||||
if (memmem(body, body_length, "<?xml", 5) != 0) {
|
if (memmem(body, body_length, "<?xml", 5) != 0) {
|
||||||
|
if (xml_field) {
|
||||||
if (username != NULL) {
|
field = xml_field;
|
||||||
/* body should contain <username>test</username><password>test</password> */
|
field_size = xml_field_size;
|
||||||
*username =
|
|
||||||
memmem(body, body_length, XMLUSER,
|
|
||||||
sizeof(XMLUSER) - 1);
|
|
||||||
if (*username == NULL) {
|
|
||||||
oclog(ws, LOG_DEBUG,
|
|
||||||
"cannot find username in client XML message");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*username += sizeof(XMLUSER) - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password != NULL) {
|
temp1_len = snprintf(temp1, sizeof(temp1), "<%s>", field);
|
||||||
*password =
|
temp2_len = snprintf(temp2, sizeof(temp2), "</%s>", field);
|
||||||
memmem(body, body_length, XMLPASS,
|
|
||||||
sizeof(XMLPASS) - 1);
|
/* body should contain <username>test</username><password>test</password> */
|
||||||
if (*password == NULL) {
|
*value =
|
||||||
oclog(ws, LOG_DEBUG,
|
memmem(body, body_length, temp1, temp1_len);
|
||||||
"cannot find password in client XML message");
|
if (*value == NULL) {
|
||||||
return -1;
|
oclog(ws, LOG_DEBUG,
|
||||||
}
|
"cannot find '%s' in client XML message", field);
|
||||||
*password += sizeof(XMLPASS) - 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*value += temp1_len;
|
||||||
|
|
||||||
/* modify body */
|
p = *value;
|
||||||
if (username != NULL) {
|
len = 0;
|
||||||
p = *username;
|
while (*p != 0) {
|
||||||
while (*p != 0) {
|
if (*p == '<'
|
||||||
if (*p == '<'
|
&& (strncmp(p, temp2, temp2_len) == 0)) {
|
||||||
&&
|
break;
|
||||||
(strncmp
|
|
||||||
(p, XMLUSER_END,
|
|
||||||
sizeof(XMLUSER_END) - 1) == 0)) {
|
|
||||||
*p = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
|
p++;
|
||||||
*username =
|
len++;
|
||||||
unescape_html(ws, *username, strlen(*username),
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password != NULL) {
|
|
||||||
p = *password;
|
|
||||||
while (*p != 0) {
|
|
||||||
if (*p == '<'
|
|
||||||
&&
|
|
||||||
(strncmp
|
|
||||||
(p, XMLPASS_END,
|
|
||||||
sizeof(XMLPASS_END) - 1) == 0)) {
|
|
||||||
*p = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
*password =
|
|
||||||
unescape_html(ws, *password, strlen(*password),
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { /* non-xml version */
|
} else { /* non-xml version */
|
||||||
|
temp1_len = snprintf(temp1, sizeof(temp1), "%s=", field);
|
||||||
|
|
||||||
/* body should be "username=test&password=test" */
|
/* body should be "username=test&password=test" */
|
||||||
if (username != NULL) {
|
*value =
|
||||||
*username =
|
memmem(body, body_length, temp1, temp1_len);
|
||||||
memmem(body, body_length, "username=",
|
if (*value == NULL) {
|
||||||
sizeof("username=") - 1);
|
oclog(ws, LOG_DEBUG,
|
||||||
if (*username == NULL) {
|
"cannot find '%s' in client message", field);
|
||||||
oclog(ws, LOG_DEBUG,
|
return -1;
|
||||||
"cannot find username in client message");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*username += sizeof("username=") - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password != NULL) {
|
*value += temp1_len;
|
||||||
*password =
|
|
||||||
memmem(body, body_length, "password=",
|
p = *value;
|
||||||
sizeof("password=") - 1);
|
len = 0;
|
||||||
if (*password == NULL) {
|
while (*p != 0) {
|
||||||
oclog(ws, LOG_DEBUG,
|
if (*p == '&') {
|
||||||
"cannot find password in client message");
|
break;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
*password += sizeof("password=") - 1;
|
p++;
|
||||||
}
|
len++;
|
||||||
|
|
||||||
/* modify body */
|
|
||||||
if (username != NULL) {
|
|
||||||
p = *username;
|
|
||||||
while (*p != 0) {
|
|
||||||
if (*p == '&') {
|
|
||||||
*p = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*username =
|
|
||||||
unescape_url(ws, *username, strlen(*username),
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (password != NULL) {
|
|
||||||
p = *password;
|
|
||||||
while (*p != 0) {
|
|
||||||
if (*p == '&') {
|
|
||||||
*p = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*password =
|
|
||||||
unescape_url(ws, *password, strlen(*password),
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username != NULL && *username == NULL) {
|
if (len == 0) {
|
||||||
oclog(ws, LOG_ERR,
|
oclog(ws, LOG_DEBUG,
|
||||||
"username requested but no username in client message");
|
"cannot parse '%s' in client XML message", field);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*value =
|
||||||
|
unescape_url(ws->req.body, *value, len, NULL);
|
||||||
|
|
||||||
if (password != NULL && *password == NULL) {
|
if (*value == NULL) {
|
||||||
oclog(ws, LOG_ERR,
|
oclog(ws, LOG_ERR,
|
||||||
"password requested but no password in client message");
|
"%s requested but no such field in client message", field);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define USERNAME_FIELD "username"
|
||||||
|
#define PASSWORD_FIELD "password"
|
||||||
|
#define GROUPNAME_FIELD "group%5flist"
|
||||||
|
#define GROUPNAME_FIELD_XML "group-select"
|
||||||
|
|
||||||
int post_auth_handler(worker_st * ws, unsigned http_ver)
|
int post_auth_handler(worker_st * ws, unsigned http_ver)
|
||||||
{
|
{
|
||||||
int ret, sd = -1;
|
int ret, sd = -1;
|
||||||
@@ -822,6 +837,7 @@ int post_auth_handler(worker_st * ws, unsigned http_ver)
|
|||||||
const char *reason = "Authentication failed";
|
const char *reason = "Authentication failed";
|
||||||
char *username = NULL;
|
char *username = NULL;
|
||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
|
char *groupname = NULL;
|
||||||
char tmp_user[MAX_USERNAME_SIZE];
|
char tmp_user[MAX_USERNAME_SIZE];
|
||||||
char tmp_group[MAX_USERNAME_SIZE];
|
char tmp_group[MAX_USERNAME_SIZE];
|
||||||
char ipbuf[128];
|
char ipbuf[128];
|
||||||
@@ -830,71 +846,31 @@ int post_auth_handler(worker_st * ws, unsigned http_ver)
|
|||||||
oclog(ws, LOG_HTTP_DEBUG, "POST body: '%.*s'", (int)req->body_length,
|
oclog(ws, LOG_HTTP_DEBUG, "POST body: '%.*s'", (int)req->body_length,
|
||||||
req->body);
|
req->body);
|
||||||
|
|
||||||
|
if (ws->sid_set && ws->auth_state == S_AUTH_INACTIVE)
|
||||||
|
ws->auth_state = S_AUTH_INIT;
|
||||||
|
|
||||||
if (ws->auth_state == S_AUTH_INACTIVE) {
|
if (ws->auth_state == S_AUTH_INACTIVE) {
|
||||||
SecAuthInitMsg ireq = SEC_AUTH_INIT_MSG__INIT;
|
SecAuthInitMsg ireq = SEC_AUTH_INIT_MSG__INIT;
|
||||||
|
|
||||||
if (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
if (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
||||||
ret =
|
ret = parse_reply(ws, req->body, req->body_length,
|
||||||
read_user_pass(ws, req->body, req->body_length,
|
GROUPNAME_FIELD, sizeof(GROUPNAME_FIELD)-1,
|
||||||
&username, NULL);
|
GROUPNAME_FIELD_XML, sizeof(GROUPNAME_FIELD_XML)-1,
|
||||||
|
&groupname);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* No username, see if we are continuing a previous session */
|
oclog(ws, LOG_DEBUG, "failed reading groupname");
|
||||||
if (ws->config->cisco_client_compat != 0 &&
|
} else {
|
||||||
gnutls_session_is_resumed(ws->session) !=
|
snprintf(ws->groupname, sizeof(ws->groupname), "%s",
|
||||||
0) {
|
groupname);
|
||||||
SecAuthContMsg rreq =
|
ireq.group_name = ws->groupname;
|
||||||
SEC_AUTH_CONT_MSG__INIT;
|
talloc_free(groupname);
|
||||||
|
}
|
||||||
/* could it be a client reconnecting and sending
|
|
||||||
* his password? */
|
|
||||||
ret =
|
|
||||||
read_user_pass(ws, req->body,
|
|
||||||
req->body_length,
|
|
||||||
NULL, &password);
|
|
||||||
if (ret < 0) {
|
|
||||||
oclog(ws, LOG_INFO,
|
|
||||||
"failed reading password as well");
|
|
||||||
goto ask_auth;
|
|
||||||
}
|
|
||||||
|
|
||||||
rreq.tls_auth_ok = ws->cert_auth_ok;
|
|
||||||
rreq.password = password;
|
|
||||||
rreq.ip =
|
|
||||||
human_addr2((void *)&ws->remote_addr, ws->remote_addr_len,
|
|
||||||
ipbuf, sizeof(ipbuf), 0);
|
|
||||||
|
|
||||||
if (ws->sid_set != 0) {
|
|
||||||
rreq.sid.data = ws->sid;
|
|
||||||
rreq.sid.len = sizeof(ws->sid);
|
|
||||||
}
|
|
||||||
|
|
||||||
sd = connect_to_secmod(ws);
|
|
||||||
if (sd == -1) {
|
|
||||||
oclog(ws, LOG_ERR,
|
|
||||||
"failed connecting to sec mod");
|
|
||||||
goto auth_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret =
|
|
||||||
send_msg_to_secmod(ws, sd,
|
|
||||||
SM_CMD_AUTH_CONT,
|
|
||||||
&rreq,
|
|
||||||
(pack_size_func)
|
|
||||||
sec_auth_cont_msg__get_packed_size,
|
|
||||||
(pack_func)
|
|
||||||
sec_auth_cont_msg__pack);
|
|
||||||
talloc_free(username);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
oclog(ws, LOG_ERR,
|
|
||||||
"failed sending auth reinit message to main");
|
|
||||||
goto auth_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ws->auth_state = S_AUTH_INIT;
|
|
||||||
goto recv_reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ret = parse_reply(ws, req->body, req->body_length,
|
||||||
|
USERNAME_FIELD, sizeof(USERNAME_FIELD)-1,
|
||||||
|
NULL, 0,
|
||||||
|
&username);
|
||||||
|
if (ret < 0) {
|
||||||
oclog(ws, LOG_INFO, "failed reading username");
|
oclog(ws, LOG_INFO, "failed reading username");
|
||||||
goto ask_auth;
|
goto ask_auth;
|
||||||
}
|
}
|
||||||
@@ -952,9 +928,10 @@ int post_auth_handler(worker_st * ws, unsigned http_ver)
|
|||||||
SecAuthContMsg areq = SEC_AUTH_CONT_MSG__INIT;
|
SecAuthContMsg areq = SEC_AUTH_CONT_MSG__INIT;
|
||||||
|
|
||||||
if (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
if (ws->config->auth_types & AUTH_TYPE_USERNAME_PASS) {
|
||||||
ret =
|
ret = parse_reply(ws, req->body, req->body_length,
|
||||||
read_user_pass(ws, req->body, req->body_length,
|
PASSWORD_FIELD, sizeof(PASSWORD_FIELD)-1,
|
||||||
NULL, &password);
|
NULL, 0,
|
||||||
|
&password);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
oclog(ws, LOG_ERR, "failed reading password");
|
oclog(ws, LOG_ERR, "failed reading password");
|
||||||
goto auth_fail;
|
goto auth_fail;
|
||||||
@@ -996,7 +973,6 @@ int post_auth_handler(worker_st * ws, unsigned http_ver)
|
|||||||
goto auth_fail;
|
goto auth_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_reply:
|
|
||||||
ret = recv_auth_reply(ws, sd, msg, sizeof(msg));
|
ret = recv_auth_reply(ws, sd, msg, sizeof(msg));
|
||||||
if (sd != -1)
|
if (sd != -1)
|
||||||
close(sd);
|
close(sd);
|
||||||
@@ -1019,11 +995,13 @@ int post_auth_handler(worker_st * ws, unsigned http_ver)
|
|||||||
return post_common_handler(ws, http_ver);
|
return post_common_handler(ws, http_ver);
|
||||||
|
|
||||||
ask_auth:
|
ask_auth:
|
||||||
|
|
||||||
if (sd != -1)
|
if (sd != -1)
|
||||||
close(sd);
|
close(sd);
|
||||||
return get_auth_handler(ws, http_ver);
|
return get_auth_handler(ws, http_ver);
|
||||||
|
|
||||||
auth_fail:
|
auth_fail:
|
||||||
|
|
||||||
if (sd != -1)
|
if (sd != -1)
|
||||||
close(sd);
|
close(sd);
|
||||||
tls_printf(ws->session,
|
tls_printf(ws->session,
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ typedef struct worker_st {
|
|||||||
|
|
||||||
|
|
||||||
char username[MAX_USERNAME_SIZE];
|
char username[MAX_USERNAME_SIZE];
|
||||||
|
char groupname[MAX_USERNAME_SIZE];
|
||||||
char hostname[MAX_HOSTNAME_SIZE];
|
char hostname[MAX_HOSTNAME_SIZE];
|
||||||
uint8_t cookie[COOKIE_SIZE];
|
uint8_t cookie[COOKIE_SIZE];
|
||||||
unsigned int cookie_set;
|
unsigned int cookie_set;
|
||||||
|
|||||||
Reference in New Issue
Block a user