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:
Nikos Mavrogiannopoulos
2015-02-24 11:30:33 +01:00
parent 7b9e5a9f2a
commit e16ae6614c
8 changed files with 200 additions and 28 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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,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);
gss_release_buffer(&minor, &name);
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);
@@ -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);
gss_release_buffer(&minor, &name);
}
if (pctx->username[0] == 0)
return -1;
else

50
src/cfg.h Normal file
View 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

View File

@@ -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[] =

View File

@@ -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
View 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

View File

@@ -365,6 +365,8 @@ struct cfg_st {
char *default_group_conf;
char *default_user_conf;
bool gssapi_no_local_user_map;
/* the tun network */
struct vpn_st network;
};