mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +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:
@@ -38,7 +38,7 @@ auth = "plain[./sample.passwd]"
|
||||
# will be sufficient to login.
|
||||
#enable-auth = certificate
|
||||
#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:
|
||||
# pam: can only be combined with PAM authentication method, it provides
|
||||
|
||||
@@ -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 \
|
||||
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) \
|
||||
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 \
|
||||
sup-config/file.c sup-config/file.h \
|
||||
sup-config/radius.c sup-config/radius.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 \
|
||||
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
|
||||
$(PROTOBUF_SOURCES) kkdcp.asn kkdcp_asn1_tab.c sec-mod-acct.h
|
||||
|
||||
@@ -35,9 +35,11 @@
|
||||
#include <gssapi/gssapi_ext.h>
|
||||
#include <gssapi/gssapi_krb5.h>
|
||||
#include <gl/base64.h>
|
||||
#include "cfg.h"
|
||||
|
||||
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 {
|
||||
char username[MAX_USERNAME_SIZE];
|
||||
@@ -86,17 +88,17 @@ static void gssapi_global_init(void *pool, const char *server_name, void *additi
|
||||
int ret;
|
||||
OM_uint32 time, minor;
|
||||
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_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.value = additional+7;
|
||||
element.value = config->keytab;
|
||||
cred_store.count = 1;
|
||||
cred_store.elements = &element;
|
||||
|
||||
@@ -155,18 +157,21 @@ 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);
|
||||
gss_release_buffer(&minor, &name);
|
||||
|
||||
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);
|
||||
syslog(LOG_INFO, "gssapi: authenticated user doesn't map to a local user");
|
||||
return -1;
|
||||
if (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);
|
||||
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;
|
||||
syslog(LOG_INFO, "gssapi: authenticated local user: %s", pctx->username);
|
||||
|
||||
gss_release_buffer(&minor, &name);
|
||||
}
|
||||
|
||||
memcpy(pctx->username, name.value, name.length);
|
||||
pctx->username[name.length] = 0;
|
||||
syslog(LOG_INFO, "gssapi: authenticated local user: %s", pctx->username);
|
||||
|
||||
gss_release_buffer(&minor, &name);
|
||||
if (pctx->username[0] == 0)
|
||||
return -1;
|
||||
else
|
||||
|
||||
50
src/cfg.h
Normal file
50
src/cfg.h
Normal file
@@ -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
|
||||
15
src/config.c
15
src/config.c
@@ -50,6 +50,7 @@
|
||||
#include <main.h>
|
||||
#include <ctl.h>
|
||||
#include <tlslib.h>
|
||||
#include "cfg.h"
|
||||
|
||||
#define OLD_DEFAULT_CFG_FILE "/etc/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
|
||||
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
|
||||
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;
|
||||
unsigned len;
|
||||
@@ -204,7 +205,7 @@ static char *get_brackets_string2(struct cfg_st *config, const char *str)
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
unsigned len;
|
||||
@@ -435,7 +436,7 @@ typedef struct auth_types_st {
|
||||
unsigned name_size;
|
||||
const struct auth_mod_st *mod;
|
||||
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;
|
||||
|
||||
#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},
|
||||
#endif
|
||||
#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
|
||||
#ifdef HAVE_RADIUS
|
||||
{NAME("radius"), &radius_auth_funcs, AUTH_TYPE_RADIUS, radius_get_brackets_string},
|
||||
@@ -541,7 +542,7 @@ typedef struct acct_types_st {
|
||||
const char *name;
|
||||
unsigned name_size;
|
||||
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;
|
||||
|
||||
static acct_types_st avail_acct_types[] =
|
||||
|
||||
@@ -113,7 +113,7 @@ An example configuration file follows.
|
||||
# will be sufficient to login.
|
||||
#enable-auth = certificate
|
||||
#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:
|
||||
# pam: can only be combined with PAM authentication method, it provides
|
||||
|
||||
114
src/subconfig.c
Normal file
114
src/subconfig.c
Normal file
@@ -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