mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-14 02:22:03 +08:00
Added more advanced suboption parser
That adds the ability to parse options in the form: auth = "gssapi[option1=value1,option2=value2,...] It also introduces the keytab, and require-local-user-map suboptions for gssapi.
This commit is contained in:
+1
-1
@@ -38,7 +38,7 @@ auth = "plain[./sample.passwd]"
|
|||||||
# will be sufficient to login.
|
# will be sufficient to login.
|
||||||
#enable-auth = certificate
|
#enable-auth = certificate
|
||||||
#enable-auth = gssapi
|
#enable-auth = gssapi
|
||||||
#enable-auth = "gssapi[keytab:/etc/key.tab]"
|
#enable-auth = "gssapi[keytab=/etc/key.tab,require-local-user-map=true]"
|
||||||
|
|
||||||
# Accounting methods available:
|
# Accounting methods available:
|
||||||
# pam: can only be combined with PAM authentication method, it provides
|
# pam: can only be combined with PAM authentication method, it provides
|
||||||
|
|||||||
+2
-2
@@ -76,12 +76,12 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
|||||||
main-user.c worker-misc.c route-add.c route-add.h worker-privs.c \
|
main-user.c worker-misc.c route-add.c route-add.h worker-privs.c \
|
||||||
sec-mod.c sec-mod-db.c sec-mod-auth.c sec-mod-auth.h sec-mod.h sec-mod-ban.c \
|
sec-mod.c sec-mod-db.c sec-mod-auth.c sec-mod-auth.h sec-mod.h sec-mod-ban.c \
|
||||||
script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) $(ACCT_SOURCES) \
|
script-list.h $(COMMON_SOURCES) $(AUTH_SOURCES) $(ACCT_SOURCES) \
|
||||||
icmp-ping.c icmp-ping.h worker-kkdcp.c \
|
icmp-ping.c icmp-ping.h worker-kkdcp.c subconfig.c \
|
||||||
sec-mod-sup-config.c sec-mod-sup-config.h \
|
sec-mod-sup-config.c sec-mod-sup-config.h \
|
||||||
sup-config/file.c sup-config/file.h \
|
sup-config/file.c sup-config/file.h \
|
||||||
sup-config/radius.c sup-config/radius.h \
|
sup-config/radius.c sup-config/radius.h \
|
||||||
worker-bandwidth.c worker-bandwidth.h ctl.h main-ctl.h \
|
worker-bandwidth.c worker-bandwidth.h ctl.h main-ctl.h \
|
||||||
vasprintf.c vasprintf.h lzs.c lzs.h \
|
vasprintf.c vasprintf.h lzs.c lzs.h cfg.h \
|
||||||
proc-search.c proc-search.h http-heads.h \
|
proc-search.c proc-search.h http-heads.h \
|
||||||
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
|
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
|
||||||
$(PROTOBUF_SOURCES) kkdcp.asn kkdcp_asn1_tab.c sec-mod-acct.h
|
$(PROTOBUF_SOURCES) kkdcp.asn kkdcp_asn1_tab.c sec-mod-acct.h
|
||||||
|
|||||||
+12
-7
@@ -35,9 +35,11 @@
|
|||||||
#include <gssapi/gssapi_ext.h>
|
#include <gssapi/gssapi_ext.h>
|
||||||
#include <gssapi/gssapi_krb5.h>
|
#include <gssapi/gssapi_krb5.h>
|
||||||
#include <gl/base64.h>
|
#include <gl/base64.h>
|
||||||
|
#include "cfg.h"
|
||||||
|
|
||||||
static gss_cred_id_t glob_creds;
|
static gss_cred_id_t glob_creds;
|
||||||
gss_OID_set glob_oids;
|
static gss_OID_set glob_oids;
|
||||||
|
static unsigned no_local_map = 0;
|
||||||
|
|
||||||
struct gssapi_ctx_st {
|
struct gssapi_ctx_st {
|
||||||
char username[MAX_USERNAME_SIZE];
|
char username[MAX_USERNAME_SIZE];
|
||||||
@@ -86,17 +88,17 @@ static void gssapi_global_init(void *pool, const char *server_name, void *additi
|
|||||||
int ret;
|
int ret;
|
||||||
OM_uint32 time, minor;
|
OM_uint32 time, minor;
|
||||||
gss_name_t name = GSS_C_NO_NAME;
|
gss_name_t name = GSS_C_NO_NAME;
|
||||||
|
gssapi_cfg_st *config = additional;
|
||||||
|
|
||||||
if (additional && strncmp(additional, "keytab", 6) == 0) {
|
if (config)
|
||||||
|
no_local_map = config->no_local_map;
|
||||||
|
|
||||||
|
if (config && config->keytab) {
|
||||||
gss_key_value_element_desc element;
|
gss_key_value_element_desc element;
|
||||||
gss_key_value_set_desc cred_store;
|
gss_key_value_set_desc cred_store;
|
||||||
|
|
||||||
if (((uint8_t*)additional)[6] != ':' && ((uint8_t*)additional)[6] != '=') {
|
|
||||||
fprintf(stderr, "syntax error at: %s\n", (char*)additional);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
element.key = "keytab";
|
element.key = "keytab";
|
||||||
element.value = additional+7;
|
element.value = config->keytab;
|
||||||
cred_store.count = 1;
|
cred_store.count = 1;
|
||||||
cred_store.elements = &element;
|
cred_store.elements = &element;
|
||||||
|
|
||||||
@@ -155,6 +157,7 @@ static int get_name(struct gssapi_ctx_st *pctx, gss_name_t client, gss_OID mech_
|
|||||||
syslog(LOG_DEBUG, "gssapi: authenticated GSSAPI user: %.*s", (unsigned)name.length, (char*)name.value);
|
syslog(LOG_DEBUG, "gssapi: authenticated GSSAPI user: %.*s", (unsigned)name.length, (char*)name.value);
|
||||||
gss_release_buffer(&minor, &name);
|
gss_release_buffer(&minor, &name);
|
||||||
|
|
||||||
|
if (no_local_map == 0) {
|
||||||
ret = gss_localname(&minor, client, mech_type, &name);
|
ret = gss_localname(&minor, client, mech_type, &name);
|
||||||
if (GSS_ERROR(ret) || name.length >= MAX_USERNAME_SIZE) {
|
if (GSS_ERROR(ret) || name.length >= MAX_USERNAME_SIZE) {
|
||||||
print_gss_err("gss_localname", mech_type, ret, minor);
|
print_gss_err("gss_localname", mech_type, ret, minor);
|
||||||
@@ -167,6 +170,8 @@ static int get_name(struct gssapi_ctx_st *pctx, gss_name_t client, gss_OID mech_
|
|||||||
syslog(LOG_INFO, "gssapi: authenticated local user: %s", pctx->username);
|
syslog(LOG_INFO, "gssapi: authenticated local user: %s", pctx->username);
|
||||||
|
|
||||||
gss_release_buffer(&minor, &name);
|
gss_release_buffer(&minor, &name);
|
||||||
|
}
|
||||||
|
|
||||||
if (pctx->username[0] == 0)
|
if (pctx->username[0] == 0)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Author: Nikos Mavrogiannopoulos
|
||||||
|
*
|
||||||
|
* This file is part of ocserv.
|
||||||
|
*
|
||||||
|
* The GnuTLS is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CFG_H
|
||||||
|
#define CFG_H
|
||||||
|
#define MAX_SUBOPTIONS 5
|
||||||
|
|
||||||
|
typedef struct subcfg_val_st {
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
} subcfg_val_st;
|
||||||
|
|
||||||
|
typedef struct gssapi_cfg_st {
|
||||||
|
char *keytab;
|
||||||
|
unsigned no_local_map;
|
||||||
|
} gssapi_cfg_st;
|
||||||
|
|
||||||
|
unsigned expand_brackets_string(struct cfg_st *config, const char *str, subcfg_val_st out[MAX_SUBOPTIONS]);
|
||||||
|
inline static void free_expanded_brackets_string(subcfg_val_st out[MAX_SUBOPTIONS], unsigned size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i=0;i<size;i++) {
|
||||||
|
talloc_free(out[i].name);
|
||||||
|
talloc_free(out[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_TRUE(str) (c_strcasecmp(str, "true") == 0 || c_strcasecmp(str, "yes") == 0)?1:0
|
||||||
|
|
||||||
|
void *gssapi_get_brackets_string(struct cfg_st *config, const char *str);
|
||||||
|
|
||||||
|
#endif
|
||||||
+8
-7
@@ -50,6 +50,7 @@
|
|||||||
#include <main.h>
|
#include <main.h>
|
||||||
#include <ctl.h>
|
#include <ctl.h>
|
||||||
#include <tlslib.h>
|
#include <tlslib.h>
|
||||||
|
#include "cfg.h"
|
||||||
|
|
||||||
#define OLD_DEFAULT_CFG_FILE "/etc/ocserv.conf"
|
#define OLD_DEFAULT_CFG_FILE "/etc/ocserv.conf"
|
||||||
#define DEFAULT_CFG_FILE "/etc/ocserv/ocserv.conf"
|
#define DEFAULT_CFG_FILE "/etc/ocserv/ocserv.conf"
|
||||||
@@ -167,10 +168,10 @@ static struct cfg_options available_options[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define get_brackets_string get_brackets_string1
|
#define get_brackets_string get_brackets_string1
|
||||||
static char *get_brackets_string1(struct cfg_st *config, const char *str);
|
static void *get_brackets_string1(struct cfg_st *config, const char *str);
|
||||||
|
|
||||||
#ifdef HAVE_RADIUS
|
#ifdef HAVE_RADIUS
|
||||||
static char *get_brackets_string2(struct cfg_st *config, const char *str)
|
static void *get_brackets_string2(struct cfg_st *config, const char *str)
|
||||||
{
|
{
|
||||||
char *p, *p2;
|
char *p, *p2;
|
||||||
unsigned len;
|
unsigned len;
|
||||||
@@ -204,7 +205,7 @@ static char *get_brackets_string2(struct cfg_st *config, const char *str)
|
|||||||
return talloc_strndup(config, p, len);
|
return talloc_strndup(config, p, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *radius_get_brackets_string(struct cfg_st *config, const char *str)
|
static void *radius_get_brackets_string(struct cfg_st *config, const char *str)
|
||||||
{
|
{
|
||||||
char *ret, *p;
|
char *ret, *p;
|
||||||
|
|
||||||
@@ -381,7 +382,7 @@ unsigned j;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_brackets_string1(struct cfg_st *config, const char *str)
|
static void *get_brackets_string1(struct cfg_st *config, const char *str)
|
||||||
{
|
{
|
||||||
char *p, *p2;
|
char *p, *p2;
|
||||||
unsigned len;
|
unsigned len;
|
||||||
@@ -435,7 +436,7 @@ typedef struct auth_types_st {
|
|||||||
unsigned name_size;
|
unsigned name_size;
|
||||||
const struct auth_mod_st *mod;
|
const struct auth_mod_st *mod;
|
||||||
unsigned type;
|
unsigned type;
|
||||||
char *(*get_brackets_string)(struct cfg_st *config, const char *);
|
void *(*get_brackets_string)(struct cfg_st *config, const char *);
|
||||||
} auth_types_st;
|
} auth_types_st;
|
||||||
|
|
||||||
#define NAME(x) (x),(sizeof(x)-1)
|
#define NAME(x) (x),(sizeof(x)-1)
|
||||||
@@ -445,7 +446,7 @@ static auth_types_st avail_auth_types[] =
|
|||||||
{NAME("pam"), &pam_auth_funcs, AUTH_TYPE_PAM, get_brackets_string},
|
{NAME("pam"), &pam_auth_funcs, AUTH_TYPE_PAM, get_brackets_string},
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GSSAPI
|
#ifdef HAVE_GSSAPI
|
||||||
{NAME("gssapi"), &gssapi_auth_funcs, AUTH_TYPE_GSSAPI, get_brackets_string},
|
{NAME("gssapi"), &gssapi_auth_funcs, AUTH_TYPE_GSSAPI, gssapi_get_brackets_string},
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_RADIUS
|
#ifdef HAVE_RADIUS
|
||||||
{NAME("radius"), &radius_auth_funcs, AUTH_TYPE_RADIUS, radius_get_brackets_string},
|
{NAME("radius"), &radius_auth_funcs, AUTH_TYPE_RADIUS, radius_get_brackets_string},
|
||||||
@@ -541,7 +542,7 @@ typedef struct acct_types_st {
|
|||||||
const char *name;
|
const char *name;
|
||||||
unsigned name_size;
|
unsigned name_size;
|
||||||
const struct acct_mod_st *mod;
|
const struct acct_mod_st *mod;
|
||||||
char *(*get_brackets_string)(struct cfg_st *config, const char *);
|
void *(*get_brackets_string)(struct cfg_st *config, const char *);
|
||||||
} acct_types_st;
|
} acct_types_st;
|
||||||
|
|
||||||
static acct_types_st avail_acct_types[] =
|
static acct_types_st avail_acct_types[] =
|
||||||
|
|||||||
+1
-1
@@ -113,7 +113,7 @@ An example configuration file follows.
|
|||||||
# will be sufficient to login.
|
# will be sufficient to login.
|
||||||
#enable-auth = certificate
|
#enable-auth = certificate
|
||||||
#enable-auth = gssapi
|
#enable-auth = gssapi
|
||||||
#enable-auth = "gssapi[keytab:/etc/key.tab]"
|
#enable-auth = "gssapi[keytab=/etc/key.tab,require-local-user-map=true]"
|
||||||
|
|
||||||
# Accounting methods available:
|
# Accounting methods available:
|
||||||
# pam: can only be combined with PAM authentication method, it provides
|
# pam: can only be combined with PAM authentication method, it provides
|
||||||
|
|||||||
+114
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <c-strcase.h>
|
||||||
|
#include <c-ctype.h>
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <vpn.h>
|
||||||
|
#include "cfg.h"
|
||||||
|
|
||||||
|
/* Returns the number of suboptions processed.
|
||||||
|
*/
|
||||||
|
unsigned expand_brackets_string(struct cfg_st *config, const char *str, subcfg_val_st out[MAX_SUBOPTIONS])
|
||||||
|
{
|
||||||
|
char *p, *p2, *p3;
|
||||||
|
unsigned len, len2;
|
||||||
|
unsigned pos = 0, finish = 0;
|
||||||
|
|
||||||
|
p = strchr(str, '[');
|
||||||
|
if (p == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
while (c_isspace(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
do {
|
||||||
|
p2 = strchr(p, '=');
|
||||||
|
if (p2 == NULL) {
|
||||||
|
if (p2 == NULL) {
|
||||||
|
fprintf(stderr, "error parsing %s\n", str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len = p2 - p;
|
||||||
|
|
||||||
|
p2++;
|
||||||
|
while (c_isspace(*p2))
|
||||||
|
p2++;
|
||||||
|
|
||||||
|
p3 = strchr(p2, ',');
|
||||||
|
if (p3 == NULL) {
|
||||||
|
p3 = strchr(p2, ']');
|
||||||
|
if (p3 == NULL) {
|
||||||
|
fprintf(stderr, "error parsing %s\n", str);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
finish = 1;
|
||||||
|
}
|
||||||
|
len2 = p3 - p2;
|
||||||
|
|
||||||
|
while (c_isspace(p[len-1]))
|
||||||
|
len--;
|
||||||
|
while (c_isspace(p2[len2-1]))
|
||||||
|
len2--;
|
||||||
|
|
||||||
|
out[pos].name = talloc_strndup(config, p, len);
|
||||||
|
out[pos].value = talloc_strndup(config, p2, len2);
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
} while(finish == 0 && pos < MAX_SUBOPTIONS);
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
void *gssapi_get_brackets_string(struct cfg_st *config, const char *str)
|
||||||
|
{
|
||||||
|
subcfg_val_st vals[MAX_SUBOPTIONS];
|
||||||
|
unsigned vals_size, i;
|
||||||
|
gssapi_cfg_st *additional;
|
||||||
|
|
||||||
|
additional = talloc_zero(config, gssapi_cfg_st);
|
||||||
|
if (additional == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vals_size = expand_brackets_string(config, str, vals);
|
||||||
|
for (i=0;i<vals_size;i++) {
|
||||||
|
if (c_strcasecmp(vals[i].name, "keytab") == 0) {
|
||||||
|
additional->keytab = talloc_strdup(config, vals[i].value);
|
||||||
|
vals[i].value = NULL;
|
||||||
|
} else if (c_strcasecmp(vals[i].name, "require-local-user-map") == 0) {
|
||||||
|
additional->no_local_map = 1-CHECK_TRUE(vals[i].value);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "unknown option '%s'\n", vals[i].name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free_expanded_brackets_string(vals, vals_size);
|
||||||
|
return additional;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user