kdc: rename windc to kdc plugin
Rename the "windc" plugin API to the more general "kdc" plugin API, for two reasons: the Heimdal KDC uses the Windows PAC even when not emulating a domain controller, and the plugin API has accreted methods that are not specific to emulating a domain controller (such as referral_policy and finalize_reply).
This commit is contained in:
@@ -111,7 +111,7 @@ CLEANFILES = \
|
||||
vis.h \
|
||||
wind.h \
|
||||
wind_err.h \
|
||||
windc_plugin.h \
|
||||
kdc-plugin.h \
|
||||
xdbm.h
|
||||
|
||||
DISTCLEANFILES = \
|
||||
|
@@ -129,7 +129,7 @@ libkdc_la_SOURCES = \
|
||||
token_validator.c \
|
||||
csr_authorizer.c \
|
||||
process.c \
|
||||
windc.c \
|
||||
kdc-plugin.c \
|
||||
gss_preauth.c
|
||||
|
||||
KDC_PROTOS = $(srcdir)/kdc-protos.h $(srcdir)/kdc-private.h
|
||||
@@ -239,7 +239,7 @@ include_HEADERS = kdc.h $(srcdir)/kdc-protos.h
|
||||
noinst_HEADERS = $(srcdir)/kdc-private.h
|
||||
|
||||
krb5dir = $(includedir)/krb5
|
||||
krb5_HEADERS = windc_plugin.h token_validator_plugin.h csr_authorizer_plugin.h
|
||||
krb5_HEADERS = kdc-plugin.h token_validator_plugin.h csr_authorizer_plugin.h
|
||||
|
||||
build_HEADERZ = $(krb5_HEADERS) # XXX
|
||||
|
||||
|
@@ -51,7 +51,7 @@ INCFILES=\
|
||||
$(INCDIR)\kdc.h \
|
||||
$(INCDIR)\kdc-protos.h \
|
||||
$(INCDIR)\kdc-private.h \
|
||||
$(INCDIR)\krb5\windc_plugin.h
|
||||
$(INCDIR)\krb5\kdc-plugin.h
|
||||
|
||||
all:: $(INCFILES) $(LIBKDC) $(BINPROGRAMS) $(SBINPROGRAMS) $(LIBEXECPROGRAMS)
|
||||
|
||||
@@ -109,7 +109,7 @@ LIBKDC_OBJS=\
|
||||
$(OBJ)\token_validator.obj \
|
||||
$(OBJ)\csr_authorizer.obj \
|
||||
$(OBJ)\process.obj \
|
||||
$(OBJ)\windc.obj \
|
||||
$(OBJ)\kdc-plugin.obj \
|
||||
$(OBJ)\gss_preauth.obj
|
||||
|
||||
LIBKDC_LIBS=\
|
||||
@@ -150,7 +150,7 @@ libkdc_la_SOURCES = \
|
||||
token_validator.c \
|
||||
csr_authorizer.c \
|
||||
process.c \
|
||||
windc.c \
|
||||
kdc-plugin.c \
|
||||
gss_preauth.c
|
||||
|
||||
$(OBJ)\kdc-protos.h: $(libkdc_la_SOURCES)
|
||||
|
@@ -309,7 +309,7 @@ configure(krb5_context context, int argc, char **argv, int *optidx)
|
||||
krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE);
|
||||
}
|
||||
|
||||
krb5_kdc_windc_init(context);
|
||||
krb5_kdc_plugin_init(context);
|
||||
|
||||
krb5_kdc_pkinit_config(context, config);
|
||||
|
||||
|
@@ -104,7 +104,7 @@
|
||||
#include <heimntlm.h>
|
||||
#endif
|
||||
#include <kdc.h>
|
||||
#include <windc_plugin.h>
|
||||
#include <kdc-plugin.h>
|
||||
|
||||
#include <heimbase.h>
|
||||
|
||||
|
@@ -36,21 +36,21 @@
|
||||
static int have_plugin = 0;
|
||||
|
||||
/*
|
||||
* Pick the first WINDC module that we find.
|
||||
* Pick the first KDC plugin module that we find.
|
||||
*/
|
||||
|
||||
static const char *windc_plugin_deps[] = {
|
||||
static const char *kdc_plugin_deps[] = {
|
||||
"kdc",
|
||||
"krb5",
|
||||
"hdb",
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct heim_plugin_data windc_plugin_data = {
|
||||
static struct heim_plugin_data kdc_plugin_data = {
|
||||
"krb5",
|
||||
"windc",
|
||||
KRB5_WINDC_PLUGIN_MINOR,
|
||||
windc_plugin_deps,
|
||||
"kdc",
|
||||
KRB5_KDC_PLUGIN_MINOR,
|
||||
kdc_plugin_deps,
|
||||
kdc_get_instance
|
||||
};
|
||||
|
||||
@@ -62,9 +62,9 @@ load(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
krb5_kdc_windc_init(krb5_context context)
|
||||
krb5_kdc_plugin_init(krb5_context context)
|
||||
{
|
||||
(void)_krb5_plugin_run_f(context, &windc_plugin_data, 0, NULL, load);
|
||||
(void)_krb5_plugin_run_f(context, &kdc_plugin_data, 0, NULL, load);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -80,7 +80,7 @@ struct generate_uc {
|
||||
static krb5_error_code KRB5_LIB_CALL
|
||||
generate(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
{
|
||||
krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
|
||||
krb5plugin_kdc_ftable *ft = (krb5plugin_kdc_ftable *)plug;
|
||||
struct generate_uc *uc = (struct generate_uc *)userctx;
|
||||
|
||||
if (ft->pac_generate == NULL)
|
||||
@@ -120,7 +120,7 @@ _kdc_pac_generate(krb5_context context,
|
||||
uc.pac = pac;
|
||||
uc.pac_attributes = pac_attributes;
|
||||
|
||||
ret = _krb5_plugin_run_f(context, &windc_plugin_data,
|
||||
ret = _krb5_plugin_run_f(context, &kdc_plugin_data,
|
||||
0, &uc, generate);
|
||||
if (ret != KRB5_PLUGIN_NO_HANDLE)
|
||||
return ret;
|
||||
@@ -145,7 +145,7 @@ struct verify_uc {
|
||||
static krb5_error_code KRB5_LIB_CALL
|
||||
verify(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
{
|
||||
krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
|
||||
krb5plugin_kdc_ftable *ft = (krb5plugin_kdc_ftable *)plug;
|
||||
struct verify_uc *uc = (struct verify_uc *)userctx;
|
||||
krb5_error_code ret;
|
||||
|
||||
@@ -180,14 +180,14 @@ _kdc_pac_verify(krb5_context context,
|
||||
uc.krbtgt = krbtgt;
|
||||
uc.pac = pac;
|
||||
|
||||
return _krb5_plugin_run_f(context, &windc_plugin_data,
|
||||
return _krb5_plugin_run_f(context, &kdc_plugin_data,
|
||||
0, &uc, verify);
|
||||
}
|
||||
|
||||
static krb5_error_code KRB5_LIB_CALL
|
||||
check(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
{
|
||||
krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
|
||||
krb5plugin_kdc_ftable *ft = (krb5plugin_kdc_ftable *)plug;
|
||||
|
||||
if (ft->client_access == NULL)
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
@@ -200,7 +200,7 @@ _kdc_check_access(astgs_request_t r)
|
||||
krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
|
||||
|
||||
if (have_plugin) {
|
||||
ret = _krb5_plugin_run_f(r->context, &windc_plugin_data,
|
||||
ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data,
|
||||
0, r, check);
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ _kdc_check_access(astgs_request_t r)
|
||||
static krb5_error_code KRB5_LIB_CALL
|
||||
referral_policy(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
{
|
||||
krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
|
||||
krb5plugin_kdc_ftable *ft = (krb5plugin_kdc_ftable *)plug;
|
||||
|
||||
if (ft->referral_policy == NULL)
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
@@ -226,7 +226,7 @@ _kdc_referral_policy(astgs_request_t r)
|
||||
krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
|
||||
|
||||
if (have_plugin)
|
||||
ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, 0, r, referral_policy);
|
||||
ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, referral_policy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -234,7 +234,7 @@ _kdc_referral_policy(astgs_request_t r)
|
||||
static krb5_error_code KRB5_LIB_CALL
|
||||
finalize_reply(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
{
|
||||
krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
|
||||
krb5plugin_kdc_ftable *ft = (krb5plugin_kdc_ftable *)plug;
|
||||
|
||||
if (ft->finalize_reply == NULL)
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
@@ -247,7 +247,7 @@ _kdc_finalize_reply(astgs_request_t r)
|
||||
krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
|
||||
|
||||
if (have_plugin)
|
||||
ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, 0, r, finalize_reply);
|
||||
ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, finalize_reply);
|
||||
|
||||
if (ret == KRB5_PLUGIN_NO_HANDLE)
|
||||
ret = 0;
|
||||
@@ -258,7 +258,7 @@ _kdc_finalize_reply(astgs_request_t r)
|
||||
static krb5_error_code KRB5_LIB_CALL
|
||||
audit(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
{
|
||||
krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
|
||||
krb5plugin_kdc_ftable *ft = (krb5plugin_kdc_ftable *)plug;
|
||||
|
||||
if (ft->audit == NULL)
|
||||
return KRB5_PLUGIN_NO_HANDLE;
|
||||
@@ -266,12 +266,12 @@ audit(krb5_context context, const void *plug, void *plugctx, void *userctx)
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
_kdc_windc_audit(astgs_request_t r)
|
||||
_kdc_plugin_audit(astgs_request_t r)
|
||||
{
|
||||
krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
|
||||
|
||||
if (have_plugin)
|
||||
ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, 0, r, audit);
|
||||
ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, audit);
|
||||
|
||||
if (ret == KRB5_PLUGIN_NO_HANDLE)
|
||||
ret = 0;
|
@@ -33,8 +33,8 @@
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef HEIMDAL_KDC_WINDC_PLUGIN_H
|
||||
#define HEIMDAL_KDC_WINDC_PLUGIN_H 1
|
||||
#ifndef HEIMDAL_KDC_KDC_PLUGIN_H
|
||||
#define HEIMDAL_KDC_KDC_PLUGIN_H 1
|
||||
|
||||
#include <krb5.h>
|
||||
#include <kdc.h>
|
||||
@@ -47,12 +47,12 @@ struct hdb_entry_ex;
|
||||
*/
|
||||
|
||||
typedef krb5_error_code
|
||||
(KRB5_CALLCONV *krb5plugin_windc_pac_generate)(void *, krb5_context,
|
||||
struct hdb_entry_ex *, /* client */
|
||||
struct hdb_entry_ex *, /* server */
|
||||
const krb5_keyblock *, /* pk_replykey */
|
||||
uint64_t, /* pac_attributes */
|
||||
krb5_pac *);
|
||||
(KRB5_CALLCONV *krb5plugin_kdc_pac_generate)(void *, krb5_context,
|
||||
struct hdb_entry_ex *, /* client */
|
||||
struct hdb_entry_ex *, /* server */
|
||||
const krb5_keyblock *, /* pk_replykey */
|
||||
uint64_t, /* pac_attributes */
|
||||
krb5_pac *);
|
||||
|
||||
/*
|
||||
* Verify the PAC KDC signatures by fetching the appropriate TGS key
|
||||
@@ -61,13 +61,13 @@ typedef krb5_error_code
|
||||
*/
|
||||
|
||||
typedef krb5_error_code
|
||||
(KRB5_CALLCONV *krb5plugin_windc_pac_verify)(void *, krb5_context,
|
||||
const krb5_principal, /* new ticket client */
|
||||
const krb5_principal, /* delegation proxy */
|
||||
struct hdb_entry_ex *,/* client */
|
||||
struct hdb_entry_ex *,/* server */
|
||||
struct hdb_entry_ex *,/* krbtgt */
|
||||
krb5_pac *);
|
||||
(KRB5_CALLCONV *krb5plugin_kdc_pac_verify)(void *, krb5_context,
|
||||
const krb5_principal, /* new ticket client */
|
||||
const krb5_principal, /* delegation proxy */
|
||||
struct hdb_entry_ex *,/* client */
|
||||
struct hdb_entry_ex *,/* server */
|
||||
struct hdb_entry_ex *,/* krbtgt */
|
||||
krb5_pac *);
|
||||
|
||||
/*
|
||||
* Authorize the client principal's access to the Authentication Service (AS).
|
||||
@@ -75,7 +75,7 @@ typedef krb5_error_code
|
||||
*/
|
||||
|
||||
typedef krb5_error_code
|
||||
(KRB5_CALLCONV *krb5plugin_windc_client_access)(void *, astgs_request_t);
|
||||
(KRB5_CALLCONV *krb5plugin_kdc_client_access)(void *, astgs_request_t);
|
||||
|
||||
/*
|
||||
* A referral policy plugin can either rewrite the server principal
|
||||
@@ -89,14 +89,14 @@ typedef krb5_error_code
|
||||
*/
|
||||
|
||||
typedef krb5_error_code
|
||||
(KRB5_CALLCONV *krb5plugin_windc_referral_policy)(void *, astgs_request_t r);
|
||||
(KRB5_CALLCONV *krb5plugin_kdc_referral_policy)(void *, astgs_request_t);
|
||||
|
||||
/*
|
||||
* Update the AS or TGS reply immediately prior to encoding.
|
||||
*/
|
||||
|
||||
typedef krb5_error_code
|
||||
(KRB5_CALLCONV *krb5plugin_windc_finalize_reply)(void *, astgs_request_t r);
|
||||
(KRB5_CALLCONV *krb5plugin_kdc_finalize_reply)(void *, astgs_request_t);
|
||||
|
||||
/*
|
||||
* Audit an AS or TGS request. This function is called after encoding the
|
||||
@@ -107,21 +107,21 @@ typedef krb5_error_code
|
||||
*/
|
||||
|
||||
typedef krb5_error_code
|
||||
(KRB5_CALLCONV *krb5plugin_windc_audit)(void *, astgs_request_t r);
|
||||
(KRB5_CALLCONV *krb5plugin_kdc_audit)(void *, astgs_request_t);
|
||||
|
||||
#define KRB5_WINDC_PLUGIN_MINOR 8
|
||||
#define KRB5_WINDC_PLUGING_MINOR KRB5_WINDC_PLUGIN_MINOR
|
||||
#define KRB5_KDC_PLUGIN_MINOR 8
|
||||
#define KRB5_KDC_PLUGING_MINOR KRB5_KDC_PLUGIN_MINOR
|
||||
|
||||
typedef struct krb5plugin_windc_ftable {
|
||||
typedef struct krb5plugin_kdc_ftable {
|
||||
int minor_version;
|
||||
krb5_error_code (KRB5_CALLCONV *init)(krb5_context, void **);
|
||||
void (KRB5_CALLCONV *fini)(void *);
|
||||
krb5plugin_windc_pac_generate pac_generate;
|
||||
krb5plugin_windc_pac_verify pac_verify;
|
||||
krb5plugin_windc_client_access client_access;
|
||||
krb5plugin_windc_referral_policy referral_policy;
|
||||
krb5plugin_windc_finalize_reply finalize_reply;
|
||||
krb5plugin_windc_audit audit;
|
||||
} krb5plugin_windc_ftable;
|
||||
krb5plugin_kdc_pac_generate pac_generate;
|
||||
krb5plugin_kdc_pac_verify pac_verify;
|
||||
krb5plugin_kdc_client_access client_access;
|
||||
krb5plugin_kdc_referral_policy referral_policy;
|
||||
krb5plugin_kdc_finalize_reply finalize_reply;
|
||||
krb5plugin_kdc_audit audit;
|
||||
} krb5plugin_kdc_ftable;
|
||||
|
||||
#endif /* HEIMDAL_KDC_WINDC_PLUGIN_H */
|
||||
#endif /* HEIMDAL_KDC_KDC_PLUGIN_H */
|
@@ -7,7 +7,7 @@ EXPORTS
|
||||
kdc_log_msg_va
|
||||
kdc_openlog
|
||||
kdc_validate_token
|
||||
krb5_kdc_windc_init
|
||||
krb5_kdc_plugin_init
|
||||
krb5_kdc_get_config
|
||||
krb5_kdc_pkinit_config
|
||||
krb5_kdc_set_dbinfo
|
||||
|
@@ -343,7 +343,7 @@ _kdc_include_pac_p(astgs_request_t r)
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify the HDB backend and windc plugin of the audited event.
|
||||
* Notify the HDB backend and KDC plugin of the audited event.
|
||||
*/
|
||||
|
||||
krb5_error_code
|
||||
@@ -352,7 +352,7 @@ _kdc_audit_request(astgs_request_t r)
|
||||
krb5_error_code ret;
|
||||
struct HDB *hdb;
|
||||
|
||||
ret = _kdc_windc_audit(r);
|
||||
ret = _kdc_plugin_audit(r);
|
||||
if (ret == 0 &&
|
||||
(hdb = r->clientdb ? r->clientdb : r->config->db[0]) &&
|
||||
hdb->hdb_audit)
|
||||
|
@@ -11,7 +11,7 @@ HEIMDAL_KDC_1.0 {
|
||||
kdc_openlog;
|
||||
kdc_check_flags;
|
||||
kdc_validate_token;
|
||||
krb5_kdc_windc_init;
|
||||
krb5_kdc_plugin_init;
|
||||
krb5_kdc_get_config;
|
||||
krb5_kdc_pkinit_config;
|
||||
krb5_kdc_set_dbinfo;
|
||||
|
@@ -29,10 +29,10 @@ krb5.conf: krb5.conf.in Makefile
|
||||
$(do_subst) < $(srcdir)/krb5.conf.in > krb5.conf.tmp
|
||||
mv krb5.conf.tmp krb5.conf
|
||||
|
||||
lib_LTLIBRARIES = windc.la
|
||||
lib_LTLIBRARIES = kdc_test_plugin.la
|
||||
|
||||
windc_la_SOURCES = windc.c
|
||||
windc_la_LDFLAGS = -module
|
||||
kdc_test_plugin_la_SOURCES = kdc_test_plugin.c
|
||||
kdc_test_plugin_la_LDFLAGS = -module
|
||||
|
||||
CLEANFILES= \
|
||||
$(TESTS) \
|
||||
|
@@ -115,8 +115,8 @@ trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
|
||||
|
||||
ec=0
|
||||
|
||||
echo "Check that WINDC module was loaded "
|
||||
grep "windc init" messages.log >/dev/null || \
|
||||
echo "Check that KDC plugin module was loaded "
|
||||
grep "kdc plugin init" messages.log >/dev/null || \
|
||||
{ ec=1 ; eval "${testfailed}"; }
|
||||
|
||||
echo "Getting client initial tickets"; > messages.log
|
||||
|
@@ -3,18 +3,18 @@
|
||||
#include <hdb.h>
|
||||
#include <hx509.h>
|
||||
#include <kdc.h>
|
||||
#include <windc_plugin.h>
|
||||
#include <kdc-plugin.h>
|
||||
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
windc_init(krb5_context context, void **ctx)
|
||||
init(krb5_context context, void **ctx)
|
||||
{
|
||||
krb5_warnx(context, "windc init");
|
||||
krb5_warnx(context, "kdc plugin init");
|
||||
*ctx = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void KRB5_CALLCONV
|
||||
windc_fini(void *ctx)
|
||||
fini(void *ctx)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -123,10 +123,10 @@ audit(void *ctx, astgs_request_t r)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5plugin_windc_ftable windc = {
|
||||
KRB5_WINDC_PLUGING_MINOR,
|
||||
windc_init,
|
||||
windc_fini,
|
||||
static krb5plugin_kdc_ftable kdc_plugin = {
|
||||
KRB5_KDC_PLUGING_MINOR,
|
||||
init,
|
||||
fini,
|
||||
pac_generate,
|
||||
pac_verify,
|
||||
client_access,
|
||||
@@ -135,18 +135,18 @@ static krb5plugin_windc_ftable windc = {
|
||||
audit
|
||||
};
|
||||
|
||||
static const krb5plugin_windc_ftable *const windc_plugins[] = {
|
||||
&windc
|
||||
static const krb5plugin_kdc_ftable *const kdc_plugins[] = {
|
||||
&kdc_plugin
|
||||
};
|
||||
|
||||
krb5_error_code KRB5_CALLCONV
|
||||
windc_plugin_load(krb5_context context,
|
||||
krb5_get_instance_func_t *get_instance,
|
||||
size_t *num_plugins,
|
||||
const krb5plugin_windc_ftable *const **plugins);
|
||||
kdc_plugin_load(krb5_context context,
|
||||
krb5_get_instance_func_t *get_instance,
|
||||
size_t *num_plugins,
|
||||
const krb5plugin_kdc_ftable *const **plugins);
|
||||
|
||||
static uintptr_t KRB5_CALLCONV
|
||||
windc_get_instance(const char *libname)
|
||||
kdc_plugin_get_instance(const char *libname)
|
||||
{
|
||||
if (strcmp(libname, "hdb") == 0)
|
||||
return hdb_get_instance(libname);
|
||||
@@ -157,14 +157,14 @@ windc_get_instance(const char *libname)
|
||||
}
|
||||
|
||||
krb5_error_code KRB5_CALLCONV
|
||||
windc_plugin_load(krb5_context context,
|
||||
krb5_get_instance_func_t *get_instance,
|
||||
size_t *num_plugins,
|
||||
const krb5plugin_windc_ftable *const **plugins)
|
||||
kdc_plugin_load(krb5_context context,
|
||||
krb5_get_instance_func_t *get_instance,
|
||||
size_t *num_plugins,
|
||||
const krb5plugin_kdc_ftable *const **plugins)
|
||||
{
|
||||
*get_instance = windc_get_instance;
|
||||
*num_plugins = sizeof(windc_plugins) / sizeof(windc_plugins[0]);
|
||||
*plugins = windc_plugins;
|
||||
*get_instance = kdc_plugin_get_instance;
|
||||
*num_plugins = sizeof(kdc_plugins) / sizeof(kdc_plugins[0]);
|
||||
*plugins = kdc_plugins;
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user