set_flavor_all krb5p
-test_1() {
+test_1a() {
local file=$DIR/$tdir/$tfile
mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
$RUNAS touch $file || error "should not fail"
[ -f $file ] || error "$file not found"
}
-run_test 1 "access with or without krb5 credential"
+run_test 1a "access with or without krb5 credential"
+
+test_1b() {
+ local file=$DIR/$tdir/$tfile
+ local lgssconf=/etc/request-key.d/lgssc.conf
+ local clients=$CLIENTS
+ local realm
+
+ [ -z $clients ] && clients=$HOSTNAME
+ zconf_umount_clients $clients $MOUNT || error "umount clients failed"
+
+ echo "stop gss daemons..."
+ stop_gss_daemons
+
+ # get local realm from krb5.conf, assume the same for all nodes
+ realm=$(grep default_realm /etc/krb5.conf | awk '{print $3}')
+
+ # add -R option to lgss_keyring on local client
+ cp $lgssconf $TMP/lgssc.conf
+ stack_trap "yes | cp $TMP/lgssc.conf $lgssconf" EXIT
+ sed -i s+lgss_keyring+\&\ \-R\ $realm+ $lgssconf
+
+ # add -R option to lsvcgssd
+ echo "bring up gss daemons..."
+ start_gss_daemons '' '' "-R $realm"
+ stack_trap "stop_gss_daemons ; start_gss_daemons" EXIT
+
+ zconf_mount_clients $clients $MOUNT || error "mount clients failed"
+
+ mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ chmod 0777 $DIR/$tdir || error "chmod $DIR/$tdir failed"
+ $RUNAS touch $file || error "touch $file failed"
+ [ -f $file ] || error "$file not found"
+}
+run_test 1b "Use specified realm"
test_2() {
local file1=$DIR/$tdir/$tfile-1
start_gss_daemons() {
local nodes=$1
local daemon=$2
+ local options=$3
if [ "$nodes" ] && [ "$daemon" ] ; then
echo "Starting gss daemon on nodes: $nodes"
- do_nodes $nodes "$daemon" || return 8
+ do_nodes $nodes "$daemon" "$options" || return 8
return 0
fi
echo "Starting gss daemon on mds: $nodes"
if $GSS_SK; then
# Start all versions, in case of switching
- do_nodes $nodes "$LSVCGSSD -vvv -s -m -o -z" || return 1
+ do_nodes $nodes "$LSVCGSSD -vvv -s -m -o -z $options" ||
+ return 1
else
- do_nodes $nodes "$LSVCGSSD -vvv" || return 1
+ do_nodes $nodes "$LSVCGSSD -vvv $options" || return 1
fi
nodes=$(comma_list $(osts_nodes))
echo "Starting gss daemon on ost: $nodes"
if $GSS_SK; then
# Start all versions, in case of switching
- do_nodes $nodes "$LSVCGSSD -vvv -s -m -o -z" || return 3
+ do_nodes $nodes "$LSVCGSSD -vvv -s -m -o -z $options" ||
+ return 3
else
- do_nodes $nodes "$LSVCGSSD -vvv" || return 3
+ do_nodes $nodes "$LSVCGSSD -vvv $options" || return 3
fi
# starting on clients
\
lsupport.h
-l_idmap_LDADD = $(top_builddir)/lustre/utils/liblustreapi.la
+l_idmap_LDADD = $(top_builddir)/lustre/utils/liblustreapi.la $(KRBLIBS)
lgss_keyring_SOURCES = \
lgss_keyring.c \
c = strchr(sname, '@');
if (!c) {
- printerr(2, "no realm found in principal, use default\n");
- *realm = strdup(this_realm);
+ printerr(2, "no realm in principal, using '%s' instead\n",
+ krb5_this_realm);
+ *realm = strdup(krb5_this_realm);
if (!*realm) {
printerr(0, "failed to duplicate default realm\n");
rc = -ENOMEM;
* FIXME should be in krb5_util.c
*********************************/
-/* realm of this node */
-char *this_realm = NULL;
-
-int gssd_get_local_realm(void)
+void gssd_cleanup_realms(void)
{
krb5_context context = NULL;
krb5_error_code code;
- int retval = -1;
- if (this_realm != NULL)
- return 0;
-
- code = krb5_init_context(&context);
- if (code) {
- printerr(0, "ERROR: get default realm: init ctx: %s\n",
- error_message(code));
- goto out;
- }
-
- code = krb5_get_default_realm(context, &this_realm);
- if (code) {
- printerr(0, "ERROR: get default realm: %s\n",
- error_message(code));
- goto out;
+ if (krb5_this_realm) {
+ code = krb5_init_context(&context);
+ if (code) {
+ printerr(0, "ERROR: cleanup realms: init ctx: %s\n",
+ error_message(code));
+ } else {
+ krb5_free_string(context, krb5_this_realm);
+ krb5_this_realm = NULL;
+ krb5_free_context(context);
+ }
}
- retval = 0;
-
- printerr(1, "Local realm: %s\n", this_realm);
-out:
- krb5_free_context(context);
- return retval;
+ if (mgs_local_realm)
+ free(mgs_local_realm);
+ if (mds_local_realm)
+ free(mds_local_realm);
+ if (oss_local_realm)
+ free(oss_local_realm);
}
-
# endif
#endif
-extern char *this_realm;
extern gss_cred_id_t gssd_creds;
void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
const gss_OID mech);
int gssd_check_mechs(void);
-int gssd_get_local_realm(void);
+void gssd_cleanup_realms(void);
#endif /* _GSS_UTIL_H_ */
#include <keyutils.h>
#include <gssapi/gssapi.h>
#include <sys/wait.h>
+#include <getopt.h>
#include <libcfs/util/param.h>
#include <libcfs/util/string.h>
#include <uapi/linux/lustre/lgss.h>
#include "lsupport.h"
#include "lgss_utils.h"
+#include "lgss_krb5_utils.h"
#include "write_bytes.h"
#include "context.h"
int main(int argc, char *argv[])
{
- struct keyring_upcall_param uparam;
- key_serial_t keyid;
- key_serial_t sring;
- pid_t child;
- int req_fd[2] = { -1, -1 };
- int reply_fd[2] = { -1, -1 };
- struct lgss_mech_type *mech;
- struct lgss_cred *cred;
- char path[PATH_MAX] = "";
- int other_ns = 0;
- int rc = 0;
- struct stat parent_ns = { .st_ino = 0 };
- struct stat caller_ns = { .st_ino = 0 };
+ struct keyring_upcall_param uparam;
+ key_serial_t keyid;
+ key_serial_t sring;
+ pid_t child;
+ int req_fd[2] = { -1, -1 };
+ int reply_fd[2] = { -1, -1 };
+ struct lgss_mech_type *mech;
+ struct lgss_cred *cred;
+ char path[PATH_MAX] = "";
+ int other_ns = 0;
+ int rc = 0, opt;
+ struct stat parent_ns = { .st_ino = 0 };
+ struct stat caller_ns = { .st_ino = 0 };
+
+ static struct option long_opts[] = {
+ { .name = "realm", .has_arg = required_argument, .val = 'R'},
+ { .name = NULL, } };
set_log_level();
logmsg(LL_TRACE, "start parsing parameters\n");
+
+ /* one possible option before upcall parameters: -R REALM */
+ while ((opt = getopt_long(argc, argv, "R:", long_opts, NULL)) != EOF) {
+ switch (opt) {
+ case 'R':
+ lgss_client_realm = optarg;
+ break;
+ default:
+ logmsg(LL_ERR, "invalid parameter %s\n",
+ argv[optind - 1]);
+ return 1;
+ }
+ }
+
+ if (lgss_client_realm) {
+ /* shift args to meet expected upcall parameters */
+ argc -= optind - 1;
+ argv += optind - 1;
+ }
+
/*
* parse & sanity check upcall parameters
* expected to be called with:
close(req_fd[1]);
close(reply_fd[0]);
close(reply_fd[1]);
+ lgss_fini(cred);
return rc;
} else {
if (uparam.kup_pid)
rc = prepare_and_instantiate(cred, keyid, uparam.kup_uid);
if (rc != 0)
- return rc;
+ goto out_reg;
/*
* fork a child to do the real gss negotiation
if (child == -1) {
logmsg(LL_ERR, "key %08x: can't create child: %s\n",
keyid, strerror(errno));
- return 1;
+ rc = 1;
+ goto out_reg;
} else if (child == 0) {
- return lgssc_kr_negotiate(keyid, cred, &uparam,
- req_fd, reply_fd);
+ rc = lgssc_kr_negotiate(keyid, cred, &uparam,
+ req_fd, reply_fd);
+ goto out_reg;
+ } else {
+ logmsg(LL_TRACE, "forked child %d\n", child);
+ return rc;
}
- logmsg(LL_TRACE, "forked child %d\n", child);
- return 0;
+out_reg:
+ lgss_fini(cred);
+ return rc;
}
}
#include "lgss_utils.h"
#include "lgss_krb5_utils.h"
+char *lgss_client_realm;
+
static void lgss_krb5_mutex_lock(void)
{
if (lgss_mutex_lock(LGSS_MUTEX_KRB5)) {
const char *krb5_cred_mds_suffix = "lustre_mds";
const char *krb5_cred_oss_suffix = "lustre_oss";
-char *krb5_this_realm = NULL;
char *krb5_keytab_file = "/etc/krb5.keytab";
static int lgss_krb5_set_ccache_name(const char *ccname)
}
static
-int lgss_krb5_get_local_realm(void)
-{
- krb5_context context = NULL;
- krb5_error_code code;
- int retval = -1;
-
- if (krb5_this_realm != NULL)
- return 0;
-
- code = krb5_init_context(&context);
- if (code) {
- logmsg(LL_ERR, "init ctx: %s\n", krb5_err_msg(code));
- return -1;
- }
-
- code = krb5_get_default_realm(context, &krb5_this_realm);
- if (code) {
- logmsg(LL_ERR, "get default realm: %s\n", krb5_err_msg(code));
- goto out;
- }
-
- logmsg(LL_DEBUG, "Local realm: %s\n", krb5_this_realm);
- retval = 0;
-out:
- krb5_free_context(context);
- return retval;
-}
-
-static
int princ_is_local_realm(krb5_context ctx, krb5_principal princ)
{
return (lgss_krb5_strcasecmp(krb5_princ_realm(ctx, princ),
cred->lc_mech_cred = NULL;
if (cred->lc_root_flags != 0) {
- if (lgss_krb5_get_local_realm())
+ rc = gss_get_realm(lgss_client_realm);
+ if (rc) {
+ logmsg(LL_ERR, "ERROR: no Kerberos realm: %s\n",
+ error_message(rc));
return -1;
+ }
+ logmsg(LL_DEBUG, "Kerberos realm: %s\n", krb5_this_realm);
rc = lkrb5_prepare_root_cred(cred);
} else {
cred->lc_mech_cred = NULL;
}
-struct lgss_mech_type lgss_mech_krb5 =
+static void lgss_krb5_fini(void)
+{
+ krb5_context context = NULL;
+ krb5_error_code code;
+
+ if (krb5_this_realm) {
+ code = krb5_init_context(&context);
+ if (code) {
+ logmsg(LL_ERR, "ERROR: krb5 fini: init ctx: %s\n",
+ error_message(code));
+ } else {
+ krb5_free_string(context, krb5_this_realm);
+ krb5_this_realm = NULL;
+ krb5_free_context(context);
+ }
+ }
+}
+
+struct lgss_mech_type lgss_mech_krb5 =
{
- .lmt_name = "krb5",
- .lmt_mech_n = LGSS_MECH_KRB5,
- .lmt_prepare_cred = lgss_krb5_prepare_cred,
- .lmt_release_cred = lgss_krb5_release_cred,
+ .lmt_name = "krb5",
+ .lmt_mech_n = LGSS_MECH_KRB5,
+ .lmt_prepare_cred = lgss_krb5_prepare_cred,
+ .lmt_release_cred = lgss_krb5_release_cred,
+ .lmt_fini = lgss_krb5_fini,
};
#define LGSS_USER_CRED_DIR "/run/user/%U"
#define LGSS_DEFAULT_CRED_PREFIX "krb5cc"
+extern char *lgss_client_realm;
+
/*
* convenient macros, these perhaps need further cleanup
*/
return 0;
}
+void lgss_fini(struct lgss_cred *cred)
+{
+ struct lgss_mech_type *mech = cred->lc_mech;
+
+ logmsg(LL_TRACE, "finishing %s\n", mech->lmt_name);
+
+ if (mech && mech->lmt_fini)
+ mech->lmt_fini();
+}
+
/****************************************
* helper functions *
****************************************/
int lgss_using_cred(struct lgss_cred *cred);
int lgss_validate_cred(struct lgss_cred *cred, gss_buffer_desc *token,
gss_buffer_desc *ctx_token);
+void lgss_fini(struct lgss_cred *cred);
int lgss_get_service_str(char **string, uint32_t lsvc, uint64_t tgt_nid);
printerr(LL_INFO, "no mapping for %s/%#Lx\n", princ, nid);
return -1;
}
+
+/* realm of this node */
+char *krb5_this_realm;
+
+static int gss_get_provided_realm(char *realm)
+{
+ if (krb5_this_realm)
+ return 0;
+
+ if (!realm)
+ return -1;
+
+ krb5_this_realm = strdup(realm);
+ return 0;
+}
+
+static int gss_get_local_realm(void)
+{
+ krb5_context context = NULL;
+ krb5_error_code code;
+
+ if (krb5_this_realm != NULL)
+ return 0;
+
+ code = krb5_init_context(&context);
+ if (code)
+ return code;
+
+ code = krb5_get_default_realm(context, &krb5_this_realm);
+ krb5_free_context(context);
+
+ if (code)
+ return code;
+
+ return 0;
+}
+
+int gss_get_realm(char *realm)
+{
+ int rc;
+
+ /* Try to use provided realm first.
+ * If no provided realm, get default local realm.
+ */
+ rc = gss_get_provided_realm(realm);
+ if (rc)
+ rc = gss_get_local_realm();
+
+ return rc;
+}
#include <linux/lnet/lnet-types.h>
#include <linux/lnet/nidstr.h>
+#include <krb5.h>
+
#define GSSD_CLI (0)
#define GSSD_SVC (1)
#define LUSTRE_GSS_MECH_SHIFT 16
extern const char * lustre_svc_name[];
+extern char *krb5_this_realm;
enum lgss_mech {
LGSS_MECH_KRB5 = 0,
void load_mapping(void);
int mapping_empty(void);
int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid);
+int gss_get_realm(char *realm);
#endif /* __LSUPPORT_H__ */
{
/* destroy krb5 machine creds */
cleanup_mapping();
+ /* cleanup allocated strings for realms */
+ gssd_cleanup_realms();
printerr(LL_WARN, "exiting on signal %d\n", signal);
exit(1);
}
static void
usage(FILE *fp, char *progname)
{
- fprintf(fp, "usage: %s [ -fnvmogk ]\n",
+ fprintf(fp, "usage: %s [ -fnvmogkRsz ]\n",
progname);
- fprintf(stderr, "-f - Run in foreground\n");
- fprintf(stderr, "-n - Don't establish kerberos credentials\n");
- fprintf(stderr, "-v - Verbosity\n");
- fprintf(stderr, "-m - Service MDS\n");
- fprintf(stderr, "-o - Service OSS\n");
- fprintf(stderr, "-g - Service MGS\n");
- fprintf(stderr, "-k - Enable kerberos support\n");
+ fprintf(stderr, "-f - Run in foreground\n");
+ fprintf(stderr, "-n - Don't establish kerberos credentials\n");
+ fprintf(stderr, "-v - Verbosity\n");
+ fprintf(stderr, "-m - Service MDS\n");
+ fprintf(stderr, "-o - Service OSS\n");
+ fprintf(stderr, "-g - Service MGS\n");
+ fprintf(stderr, "-k - Enable kerberos support\n");
+ fprintf(stderr, "-R REALM - Kerberos Realm to use, instead of default\n");
#ifdef HAVE_OPENSSL_SSK
- fprintf(stderr, "-s - Enable shared secret key support\n");
+ fprintf(stderr, "-s - Enable shared secret key support\n");
#endif
- fprintf(stderr, "-z - Enable gssnull support\n");
+ fprintf(stderr, "-z - Enable gssnull support\n");
exit(fp == stderr);
}
int verbosity = 0;
int opt;
int must_srv_mds = 0, must_srv_oss = 0, must_srv_mgs = 0;
+ char *realm = NULL;
char *progname;
- while ((opt = getopt(argc, argv, "fnvmogksz")) != -1) {
+ while ((opt = getopt(argc, argv, "fgkmnoR:svz")) != -1) {
switch (opt) {
case 'f':
fg = 1;
break;
- case 'n':
- get_creds = 0;
+ case 'g':
+ get_creds = 1;
+ must_srv_mgs = 1;
break;
- case 'v':
- verbosity++;
+ case 'h':
+ usage(stdout, argv[0]);
+ break;
+ case 'k':
+ krb_enabled = 1;
break;
case 'm':
get_creds = 1;
must_srv_mds = 1;
break;
+ case 'n':
+ get_creds = 0;
+ break;
case 'o':
get_creds = 1;
must_srv_oss = 1;
break;
- case 'g':
- get_creds = 1;
- must_srv_mgs = 1;
- break;
- case 'k':
- krb_enabled = 1;
- break;
- case 'h':
- usage(stdout, argv[0]);
+ case 'R':
+ realm = optarg;
break;
case 's':
#ifdef HAVE_OPENSSL_SSK
usage(stderr, argv[0]);
#endif
break;
+ case 'v':
+ verbosity++;
+ break;
case 'z':
null_enabled = 1;
break;
#endif
}
+
+ if (realm && !krb_enabled) {
+ fprintf(stderr, "error: need -k option if -R is used\n");
+ usage(stderr, argv[0]);
+ }
+
initerr(progname, verbosity, fg);
/* For kerberos use gss mechanisms but ignore for sk and null */
if (krb_enabled) {
+ int ret;
+
if (gssd_check_mechs()) {
printerr(LL_ERR,
"ERROR: problem with gssapi library\n");
exit(1);
}
- if (gssd_get_local_realm()) {
- printerr(LL_ERR,
- "ERROR: Can't get Local Kerberos realm\n");
+ ret = gss_get_realm(realm);
+ if (ret) {
+ printerr(LL_ERR, "ERROR: no Kerberos realm: %s\n",
+ error_message(ret));
exit(1);
}
-
+ printerr(LL_WARN, "Kerberos realm: %s\n", krb5_this_realm);
if (get_creds &&
gssd_prepare_creds(must_srv_mgs, must_srv_mds,
must_srv_oss)) {
svcgssd_run();
cleanup_mapping();
+ gssd_cleanup_realms();
printerr(LL_ERR, "svcgssd_run returned!\n");
abort();
}