parent
a3d0b3874b
commit
8c4ceb6bfc
@ -0,0 +1,89 @@
|
||||
commit c1c35487aba2cec828d9b8a1be9043000beadea5
|
||||
Author: Lixiaokeng <lixiaokeng@huawei.com>
|
||||
Date: Mon Oct 24 13:00:50 2022 -0400
|
||||
|
||||
blkmapd: fix coredump in bl_add_disk
|
||||
|
||||
The serial->data is not malloced separately (just part of
|
||||
the serial), so it can't be freed. The bl_serial has its
|
||||
own free function. Use it.
|
||||
|
||||
Signed-off-by: Lixiaokeng <lixiaokeng@huawei.com>
|
||||
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
|
||||
index 49935c2e..bd890598 100644
|
||||
--- a/utils/blkmapd/device-discovery.c
|
||||
+++ b/utils/blkmapd/device-discovery.c
|
||||
@@ -187,10 +187,7 @@ static void bl_add_disk(char *filepath)
|
||||
}
|
||||
|
||||
if (disk && diskpath) {
|
||||
- if (serial) {
|
||||
- free(serial->data);
|
||||
- free(serial);
|
||||
- }
|
||||
+ bl_free_scsi_string(serial);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -228,10 +225,7 @@ static void bl_add_disk(char *filepath)
|
||||
disk->size = size;
|
||||
disk->valid_path = path;
|
||||
}
|
||||
- if (serial) {
|
||||
- free(serial->data);
|
||||
- free(serial);
|
||||
- }
|
||||
+ bl_free_scsi_string(serial);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -241,10 +235,7 @@ static void bl_add_disk(char *filepath)
|
||||
free(path->full_path);
|
||||
free(path);
|
||||
}
|
||||
- if (serial) {
|
||||
- free(serial->data);
|
||||
- free(serial);
|
||||
- }
|
||||
+ bl_free_scsi_string(serial);
|
||||
return;
|
||||
}
|
||||
|
||||
diff --git a/utils/blkmapd/device-discovery.h b/utils/blkmapd/device-discovery.h
|
||||
index a86eed99..462aa943 100644
|
||||
--- a/utils/blkmapd/device-discovery.h
|
||||
+++ b/utils/blkmapd/device-discovery.h
|
||||
@@ -151,6 +151,8 @@ uint64_t process_deviceinfo(const char *dev_addr_buf,
|
||||
|
||||
extern ssize_t atomicio(ssize_t(*f) (int, void *, size_t),
|
||||
int fd, void *_s, size_t n);
|
||||
+extern struct bl_serial *bl_create_scsi_string(int len, const char *bytes);
|
||||
+extern void bl_free_scsi_string(struct bl_serial *str);
|
||||
extern struct bl_serial *bldev_read_serial(int fd, const char *filename);
|
||||
extern enum bl_path_state_e bldev_read_ap_state(int fd);
|
||||
extern int bl_discover_devices(void);
|
||||
diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
|
||||
index c7952c3e..9e5749ef 100644
|
||||
--- a/utils/blkmapd/device-inq.c
|
||||
+++ b/utils/blkmapd/device-inq.c
|
||||
@@ -53,7 +53,7 @@
|
||||
#define DEF_ALLOC_LEN 255
|
||||
#define MX_ALLOC_LEN (0xc000 + 0x80)
|
||||
|
||||
-static struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
|
||||
+struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
|
||||
{
|
||||
struct bl_serial *s;
|
||||
|
||||
@@ -66,7 +66,7 @@ static struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
|
||||
return s;
|
||||
}
|
||||
|
||||
-static void bl_free_scsi_string(struct bl_serial *str)
|
||||
+void bl_free_scsi_string(struct bl_serial *str)
|
||||
{
|
||||
if (str)
|
||||
free(str);
|
@ -0,0 +1,199 @@
|
||||
diff --git a/support/export/v4root.c b/support/export/v4root.c
|
||||
index c12a7d85..826cc219 100644
|
||||
--- a/support/export/v4root.c
|
||||
+++ b/support/export/v4root.c
|
||||
@@ -135,7 +135,7 @@ v4root_support(void)
|
||||
if (!warned) {
|
||||
xlog(L_WARNING, "Kernel does not have pseudo root support.");
|
||||
xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0");
|
||||
- xlog(L_WARNING, "is specfied in /etc/exports file.");
|
||||
+ xlog(L_WARNING, "is specified in /etc/exports file.");
|
||||
warned++;
|
||||
}
|
||||
return 0;
|
||||
diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service
|
||||
index 6aa45ba1..57181632 100644
|
||||
--- a/systemd/nfs-blkmap.service
|
||||
+++ b/systemd/nfs-blkmap.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=pNFS block layout mapping daemon
|
||||
+Documentation=man:blkmapd(8)
|
||||
DefaultDependencies=no
|
||||
Conflicts=umount.target
|
||||
After=rpc_pipefs.target
|
||||
diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service
|
||||
index f38fe527..bf6f4ded 100644
|
||||
--- a/systemd/nfs-idmapd.service
|
||||
+++ b/systemd/nfs-idmapd.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=NFSv4 ID-name mapping service
|
||||
+Documentation=man:idmapd(8)
|
||||
DefaultDependencies=no
|
||||
Requires=rpc_pipefs.target
|
||||
After=rpc_pipefs.target local-fs.target
|
||||
diff --git a/systemd/nfs-mountd.service b/systemd/nfs-mountd.service
|
||||
index e8ece533..4618fab1 100644
|
||||
--- a/systemd/nfs-mountd.service
|
||||
+++ b/systemd/nfs-mountd.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=NFS Mount Daemon
|
||||
+Documentation=man:rpc.mountd(8)
|
||||
DefaultDependencies=no
|
||||
Requires=proc-fs-nfsd.mount
|
||||
Wants=network-online.target
|
||||
diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
|
||||
index 41479169..58bc0917 100644
|
||||
--- a/systemd/nfs-server.service
|
||||
+++ b/systemd/nfs-server.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=NFS server and services
|
||||
+Documentation=man:rpc.nfsd(8) man:exportfs(8)
|
||||
DefaultDependencies=no
|
||||
Requires=network.target proc-fs-nfsd.mount
|
||||
Requires=nfs-mountd.service
|
||||
diff --git a/systemd/nfsdcld.service b/systemd/nfsdcld.service
|
||||
index a32d2430..3ced5658 100644
|
||||
--- a/systemd/nfsdcld.service
|
||||
+++ b/systemd/nfsdcld.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=NFSv4 Client Tracking Daemon
|
||||
+Documentation=man:nfsdcld(8)
|
||||
DefaultDependencies=no
|
||||
Conflicts=umount.target
|
||||
Requires=rpc_pipefs.target proc-fs-nfsd.mount
|
||||
diff --git a/systemd/rpc-gssd.service.in b/systemd/rpc-gssd.service.in
|
||||
index 6807db35..38382ed3 100644
|
||||
--- a/systemd/rpc-gssd.service.in
|
||||
+++ b/systemd/rpc-gssd.service.in
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=RPC security service for NFS client and server
|
||||
+Documentation=man:rpc.gssd(8)
|
||||
DefaultDependencies=no
|
||||
Conflicts=umount.target
|
||||
Requires=rpc_pipefs.target
|
||||
diff --git a/systemd/rpc-statd-notify.service b/systemd/rpc-statd-notify.service
|
||||
index aad4c0d2..962f18b2 100644
|
||||
--- a/systemd/rpc-statd-notify.service
|
||||
+++ b/systemd/rpc-statd-notify.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=Notify NFS peers of a restart
|
||||
+Documentation=man:sm-notify(8) man:rpc.statd(8)
|
||||
DefaultDependencies=no
|
||||
Wants=network-online.target
|
||||
After=local-fs.target network-online.target nss-lookup.target
|
||||
diff --git a/systemd/rpc-statd.service b/systemd/rpc-statd.service
|
||||
index 392750da..660ed861 100644
|
||||
--- a/systemd/rpc-statd.service
|
||||
+++ b/systemd/rpc-statd.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=NFS status monitor for NFSv2/3 locking.
|
||||
+Documentation=man:rpc.statd(8)
|
||||
DefaultDependencies=no
|
||||
Conflicts=umount.target
|
||||
Requires=nss-lookup.target rpcbind.socket
|
||||
diff --git a/systemd/rpc-svcgssd.service b/systemd/rpc-svcgssd.service
|
||||
index cb2bcd4f..401fba11 100644
|
||||
--- a/systemd/rpc-svcgssd.service
|
||||
+++ b/systemd/rpc-svcgssd.service
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=RPC security service for NFS server
|
||||
+Documentation=man:rpc.svcgssd(8)
|
||||
DefaultDependencies=no
|
||||
After=local-fs.target
|
||||
PartOf=nfs-server.service
|
||||
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
|
||||
index 83dd6807..e5fb10f5 100644
|
||||
--- a/utils/exportfs/exports.man
|
||||
+++ b/utils/exportfs/exports.man
|
||||
@@ -298,7 +298,7 @@ set.
|
||||
|
||||
The
|
||||
.I nocrossmnt
|
||||
-option can explictly disable
|
||||
+option can explicitly disable
|
||||
.I crossmnt
|
||||
if it was previously set. This is rarely useful.
|
||||
.TP
|
||||
diff --git a/utils/mount/mount_libmount.c b/utils/mount/mount_libmount.c
|
||||
index aa4ac5c3..fd6cb2cb 100644
|
||||
--- a/utils/mount/mount_libmount.c
|
||||
+++ b/utils/mount/mount_libmount.c
|
||||
@@ -442,7 +442,7 @@ int main(int argc, char *argv[])
|
||||
mnt_init_debug(0);
|
||||
cxt = mnt_new_context();
|
||||
if (!cxt) {
|
||||
- nfs_error(_("Can't initilize libmount: %s"),
|
||||
+ nfs_error(_("Can't initialize libmount: %s"),
|
||||
strerror(errno));
|
||||
rc = EX_FAIL;
|
||||
goto done;
|
||||
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
|
||||
index dfc31a5d..fe1ad354 100644
|
||||
--- a/utils/mount/nfs.man
|
||||
+++ b/utils/mount/nfs.man
|
||||
@@ -967,7 +967,7 @@ Some server features misbehave in the face of a migration-compatible
|
||||
identification string.
|
||||
The
|
||||
.B nomigration
|
||||
-option retains the use of a traditional client indentification string
|
||||
+option retains the use of a traditional client identification string
|
||||
which is compatible with legacy NFS servers.
|
||||
This is also the behavior if neither option is specified.
|
||||
A client's open and lock state cannot be migrated transparently
|
||||
@@ -1810,7 +1810,7 @@ auxiliary services such as the NLM service can choose
|
||||
any unused port number at random.
|
||||
.P
|
||||
Common firewall configurations block the well-known rpcbind port.
|
||||
-In the absense of an rpcbind service,
|
||||
+In the absence of an rpcbind service,
|
||||
the server administrator fixes the port number
|
||||
of NFS-related services so that the firewall
|
||||
can allow access to specific NFS service ports.
|
||||
diff --git a/utils/mount/nfsmount.conf.man b/utils/mount/nfsmount.conf.man
|
||||
index 73c3e118..7d4a33c9 100644
|
||||
--- a/utils/mount/nfsmount.conf.man
|
||||
+++ b/utils/mount/nfsmount.conf.man
|
||||
@@ -43,7 +43,7 @@ and will be shifted to lower case before being passed to the filesystem.
|
||||
.PP
|
||||
Boolean mount options which do not need an equals sign must be given as
|
||||
.RI \[dq] option =True".
|
||||
-Instead of preceeding such an option with
|
||||
+Instead of preceding such an option with
|
||||
.RB \[dq] no \[dq]
|
||||
its negation must be given as
|
||||
.RI \[dq] option =False".
|
||||
diff --git a/utils/nfsdcld/nfsdcld.man b/utils/nfsdcld/nfsdcld.man
|
||||
index 861f1c49..ee6e9dcf 100644
|
||||
--- a/utils/nfsdcld/nfsdcld.man
|
||||
+++ b/utils/nfsdcld/nfsdcld.man
|
||||
@@ -198,7 +198,7 @@ initialize client tracking in the following order: First, the \fBnfsdcld\fR upc
|
||||
the \fBnfsdcltrack\fR usermodehelper upcall. Finally, the legacy client tracking.
|
||||
.PP
|
||||
This daemon should be run as root, as the pipe that it uses to communicate
|
||||
-with the kernel is only accessable by root. The daemon however does drop all
|
||||
+with the kernel is only accessible by root. The daemon however does drop all
|
||||
superuser capabilities after starting. Because of this, the \fIstoragedir\fR
|
||||
should be owned by root, and be readable and writable by owner.
|
||||
.PP
|
||||
diff --git a/utils/nfsdcltrack/nfsdcltrack.man b/utils/nfsdcltrack/nfsdcltrack.man
|
||||
index cc24b7a2..3905ba46 100644
|
||||
--- a/utils/nfsdcltrack/nfsdcltrack.man
|
||||
+++ b/utils/nfsdcltrack/nfsdcltrack.man
|
||||
@@ -80,7 +80,7 @@ section. For example:
|
||||
.br
|
||||
storagedir = /shared/nfs/nfsdcltrack
|
||||
.in -5
|
||||
-Debuging to syslog can also be enabled by setting "debug = 1" in this file.
|
||||
+Debugging to syslog can also be enabled by setting "debug = 1" in this file.
|
||||
.SH "LEGACY TRANSITION MECHANISM"
|
||||
.IX Header "LEGACY TRANSITION MECHANISM"
|
||||
The Linux kernel NFSv4 server has historically tracked this information
|
@ -0,0 +1,239 @@
|
||||
diff --git a/aclocal/libtirpc.m4 b/aclocal/libtirpc.m4
|
||||
index 27368ff2..4379b14d 100644
|
||||
--- a/aclocal/libtirpc.m4
|
||||
+++ b/aclocal/libtirpc.m4
|
||||
@@ -26,6 +26,11 @@ AC_DEFUN([AC_LIBTIRPC], [
|
||||
[Define to 1 if your tirpc library provides libtirpc_set_debug])],,
|
||||
[${LIBS}])])
|
||||
|
||||
+ AS_IF([test -n "${LIBTIRPC}"],
|
||||
+ [AC_CHECK_LIB([tirpc], [rpc_gss_seccreate],
|
||||
+ [AC_DEFINE([HAVE_TIRPC_GSS_SECCREATE], [1],
|
||||
+ [Define to 1 if your tirpc library provides rpc_gss_seccreate])],,
|
||||
+ [${LIBS}])])
|
||||
AC_SUBST([AM_CPPFLAGS])
|
||||
AC_SUBST(LIBTIRPC)
|
||||
|
||||
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
|
||||
index ae568f15..7629de0b 100644
|
||||
--- a/utils/gssd/gssd_proc.c
|
||||
+++ b/utils/gssd/gssd_proc.c
|
||||
@@ -70,6 +70,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <syscall.h>
|
||||
+#ifdef HAVE_TIRPC_GSS_SECCREATE
|
||||
+#include <rpc/rpcsec_gss.h>
|
||||
+#endif
|
||||
|
||||
#include "gssd.h"
|
||||
#include "err_util.h"
|
||||
@@ -330,6 +333,11 @@ create_auth_rpc_client(struct clnt_info *clp,
|
||||
struct timeval timeout;
|
||||
struct sockaddr *addr = (struct sockaddr *) &clp->addr;
|
||||
socklen_t salen;
|
||||
+#ifdef HAVE_TIRPC_GSS_SECCREATE
|
||||
+ rpc_gss_options_req_t req;
|
||||
+ rpc_gss_options_ret_t ret;
|
||||
+ char mechanism[] = "kerberos_v5";
|
||||
+#endif
|
||||
pthread_t tid = pthread_self();
|
||||
|
||||
sec.qop = GSS_C_QOP_DEFAULT;
|
||||
@@ -410,15 +418,43 @@ create_auth_rpc_client(struct clnt_info *clp,
|
||||
|
||||
printerr(3, "create_auth_rpc_client(0x%lx): creating context with server %s\n",
|
||||
tid, tgtname);
|
||||
+#ifdef HAVE_TIRPC_GSS_SECCREATE
|
||||
+ memset(&req, 0, sizeof(req));
|
||||
+ req.my_cred = sec.cred;
|
||||
+ auth = rpc_gss_seccreate(rpc_clnt, tgtname, mechanism,
|
||||
+ rpcsec_gss_svc_none, NULL, &req, &ret);
|
||||
+#else
|
||||
auth = authgss_create_default(rpc_clnt, tgtname, &sec);
|
||||
+#endif
|
||||
if (!auth) {
|
||||
+#ifdef HAVE_TIRPC_GSS_SECCREATE
|
||||
+ if (ret.minor_status == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
|
||||
+ printerr(2, "WARNING: server=%s failed context "
|
||||
+ "creation with KRB5_AP_ERR_BAD_INTEGRITY\n",
|
||||
+ clp->servername);
|
||||
+ if (cred == GSS_C_NO_CREDENTIAL)
|
||||
+ retval = gssd_refresh_krb5_machine_credential(clp->servername,
|
||||
+ "*", NULL, 1);
|
||||
+ else
|
||||
+ retval = gssd_k5_remove_bad_service_cred(clp->servername);
|
||||
+ if (!retval) {
|
||||
+ auth = rpc_gss_seccreate(rpc_clnt, tgtname,
|
||||
+ mechanism, rpcsec_gss_svc_none,
|
||||
+ NULL, &req, &ret);
|
||||
+ if (auth)
|
||||
+ goto success;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
/* Our caller should print appropriate message */
|
||||
printerr(2, "WARNING: Failed to create krb5 context for "
|
||||
"user with uid %d for server %s\n",
|
||||
uid, tgtname);
|
||||
goto out_fail;
|
||||
}
|
||||
-
|
||||
+#ifdef HAVE_TIRPC_GSS_SECCREATE
|
||||
+success:
|
||||
+#endif
|
||||
/* Success !!! */
|
||||
rpc_clnt->cl_auth = auth;
|
||||
*clnt_return = rpc_clnt;
|
||||
@@ -571,7 +607,7 @@ krb5_use_machine_creds(struct clnt_info *clp, uid_t uid,
|
||||
|
||||
do {
|
||||
gssd_refresh_krb5_machine_credential(clp->servername,
|
||||
- service, srchost);
|
||||
+ service, srchost, 0);
|
||||
/*
|
||||
* Get a list of credential cache names and try each
|
||||
* of them until one works or we've tried them all
|
||||
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
|
||||
index e3f270e9..6f66ef4f 100644
|
||||
--- a/utils/gssd/krb5_util.c
|
||||
+++ b/utils/gssd/krb5_util.c
|
||||
@@ -165,7 +165,7 @@ static int select_krb5_ccache(const struct dirent *d);
|
||||
static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
|
||||
const char **cctype, struct dirent **d);
|
||||
static int gssd_get_single_krb5_cred(krb5_context context,
|
||||
- krb5_keytab kt, struct gssd_k5_kt_princ *ple);
|
||||
+ krb5_keytab kt, struct gssd_k5_kt_princ *ple, int force_renew);
|
||||
static int query_krb5_ccache(const char* cred_cache, char **ret_princname,
|
||||
char **ret_realm);
|
||||
|
||||
@@ -391,7 +391,8 @@ gssd_check_if_cc_exists(struct gssd_k5_kt_princ *ple)
|
||||
static int
|
||||
gssd_get_single_krb5_cred(krb5_context context,
|
||||
krb5_keytab kt,
|
||||
- struct gssd_k5_kt_princ *ple)
|
||||
+ struct gssd_k5_kt_princ *ple,
|
||||
+ int force_renew)
|
||||
{
|
||||
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
|
||||
krb5_get_init_creds_opt *init_opts = NULL;
|
||||
@@ -421,7 +422,7 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
*/
|
||||
now += 300;
|
||||
pthread_mutex_lock(&ple_lock);
|
||||
- if (ple->ccname && ple->endtime > now && !nocache) {
|
||||
+ if (ple->ccname && ple->endtime > now && !nocache && !force_renew) {
|
||||
printerr(3, "%s(0x%lx): Credentials in CC '%s' are good until %s",
|
||||
__func__, tid, ple->ccname, ctime((time_t *)&ple->endtime));
|
||||
code = 0;
|
||||
@@ -1155,7 +1156,8 @@ err_cache:
|
||||
static int
|
||||
gssd_refresh_krb5_machine_credential_internal(char *hostname,
|
||||
struct gssd_k5_kt_princ *ple,
|
||||
- char *service, char *srchost)
|
||||
+ char *service, char *srchost,
|
||||
+ int force_renew)
|
||||
{
|
||||
krb5_error_code code = 0;
|
||||
krb5_context context;
|
||||
@@ -1221,7 +1223,7 @@ gssd_refresh_krb5_machine_credential_internal(char *hostname,
|
||||
goto out_free_kt;
|
||||
}
|
||||
}
|
||||
- retval = gssd_get_single_krb5_cred(context, kt, ple);
|
||||
+ retval = gssd_get_single_krb5_cred(context, kt, ple, force_renew);
|
||||
out_free_kt:
|
||||
krb5_kt_close(context, kt);
|
||||
out_free_context:
|
||||
@@ -1344,7 +1346,7 @@ gssd_get_krb5_machine_cred_list(char ***list)
|
||||
pthread_mutex_unlock(&ple_lock);
|
||||
/* Make sure cred is up-to-date before returning it */
|
||||
retval = gssd_refresh_krb5_machine_credential_internal(NULL, ple,
|
||||
- NULL, NULL);
|
||||
+ NULL, NULL, 0);
|
||||
pthread_mutex_lock(&ple_lock);
|
||||
if (gssd_k5_kt_princ_list == NULL) {
|
||||
/* Looks like we did shutdown... abort */
|
||||
@@ -1456,10 +1458,12 @@ gssd_destroy_krb5_principals(int destroy_machine_creds)
|
||||
*/
|
||||
int
|
||||
gssd_refresh_krb5_machine_credential(char *hostname,
|
||||
- char *service, char *srchost)
|
||||
+ char *service, char *srchost,
|
||||
+ int force_renew)
|
||||
{
|
||||
return gssd_refresh_krb5_machine_credential_internal(hostname, NULL,
|
||||
- service, srchost);
|
||||
+ service, srchost,
|
||||
+ force_renew);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1549,6 +1553,48 @@ gssd_acquire_user_cred(gss_cred_id_t *gss_cred)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* Removed a service ticket for nfs/<name> from the ticket cache
|
||||
+ */
|
||||
+int
|
||||
+gssd_k5_remove_bad_service_cred(char *name)
|
||||
+{
|
||||
+ krb5_creds in_creds, out_creds;
|
||||
+ krb5_error_code ret;
|
||||
+ krb5_context context;
|
||||
+ krb5_ccache cache;
|
||||
+ krb5_principal principal;
|
||||
+ int retflags = KRB5_TC_MATCH_SRV_NAMEONLY;
|
||||
+ char srvname[1024];
|
||||
+
|
||||
+ ret = krb5_init_context(&context);
|
||||
+ if (ret)
|
||||
+ goto out_cred;
|
||||
+ ret = krb5_cc_default(context, &cache);
|
||||
+ if (ret)
|
||||
+ goto out_free_context;
|
||||
+ ret = krb5_cc_get_principal(context, cache, &principal);
|
||||
+ if (ret)
|
||||
+ goto out_close_cache;
|
||||
+ memset(&in_creds, 0, sizeof(in_creds));
|
||||
+ in_creds.client = principal;
|
||||
+ sprintf(srvname, "nfs/%s", name);
|
||||
+ ret = krb5_parse_name(context, srvname, &in_creds.server);
|
||||
+ if (ret)
|
||||
+ goto out_free_principal;
|
||||
+ ret = krb5_cc_retrieve_cred(context, cache, retflags, &in_creds, &out_creds);
|
||||
+ if (ret)
|
||||
+ goto out_free_principal;
|
||||
+ ret = krb5_cc_remove_cred(context, cache, 0, &out_creds);
|
||||
+out_free_principal:
|
||||
+ krb5_free_principal(context, principal);
|
||||
+out_close_cache:
|
||||
+ krb5_cc_close(context, cache);
|
||||
+out_free_context:
|
||||
+ krb5_free_context(context);
|
||||
+out_cred:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
|
||||
/*
|
||||
* this routine obtains a credentials handle via gss_acquire_cred()
|
||||
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
|
||||
index 2415205a..7ef87018 100644
|
||||
--- a/utils/gssd/krb5_util.h
|
||||
+++ b/utils/gssd/krb5_util.h
|
||||
@@ -16,11 +16,13 @@ int gssd_get_krb5_machine_cred_list(char ***list);
|
||||
void gssd_free_krb5_machine_cred_list(char **list);
|
||||
void gssd_destroy_krb5_principals(int destroy_machine_creds);
|
||||
int gssd_refresh_krb5_machine_credential(char *hostname,
|
||||
- char *service, char *srchost);
|
||||
+ char *service, char *srchost,
|
||||
+ int force_renew);
|
||||
char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
|
||||
void gssd_k5_get_default_realm(char **def_realm);
|
||||
|
||||
int gssd_acquire_user_cred(gss_cred_id_t *gss_cred);
|
||||
+int gssd_k5_remove_bad_service_cred(char *srvname);
|
||||
|
||||
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
|
||||
extern int limit_to_legacy_enctypes;
|
@ -0,0 +1,110 @@
|
||||
commit 75b04a9bff709a49f55326b439851822dd630be6
|
||||
Author: Olga Kornievskaia <kolga@netapp.com>
|
||||
Date: Mon Oct 16 11:45:54 2023 -0400
|
||||
|
||||
gssd: fix handling DNS lookup failure
|
||||
|
||||
When the kernel does its first ever lookup for a given server ip it
|
||||
sends down info for server, protocol, etc. On the gssd side as it
|
||||
scans the pipefs structure and sees a new entry it reads that info
|
||||
and creates a clp_info structure. At that time it also does
|
||||
a DNS lookup of the provided ip to name using getnameinfo(),
|
||||
this is saved in clp->servername for all other upcalls that is
|
||||
down under that directory.
|
||||
|
||||
If this 1st getnameinfo() results in a failed resolution for
|
||||
whatever reason (a temporary DNS resolution problem), this cause
|
||||
of all other future upcalls to fail.
|
||||
|
||||
As a fix, this patch proposed to (1) save the server info that's
|
||||
passed only in the initial pipefs new entry creation in the
|
||||
clp_info structure, then (2) for the upcalls, if clp->servername
|
||||
is NULL, then do the DNS lookup again and set all the needed
|
||||
clp_info fields upon successful resolution.
|
||||
|
||||
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
|
||||
index 833d8e0..ca9b326 100644
|
||||
--- a/utils/gssd/gssd.c
|
||||
+++ b/utils/gssd/gssd.c
|
||||
@@ -365,6 +365,12 @@ gssd_read_service_info(int dirfd, struct clnt_info *clp)
|
||||
|
||||
fail:
|
||||
printerr(0, "ERROR: failed to parse %s/info\n", clp->relpath);
|
||||
+ clp->upcall_address = strdup(address);
|
||||
+ clp->upcall_port = strdup(port);
|
||||
+ clp->upcall_program = program;
|
||||
+ clp->upcall_vers = version;
|
||||
+ clp->upcall_protoname = strdup(protoname);
|
||||
+ clp->upcall_service = strdup(service);
|
||||
free(servername);
|
||||
free(protoname);
|
||||
clp->servicename = NULL;
|
||||
@@ -408,6 +414,16 @@ gssd_free_client(struct clnt_info *clp)
|
||||
free(clp->servicename);
|
||||
free(clp->servername);
|
||||
free(clp->protocol);
|
||||
+ if (!clp->servername) {
|
||||
+ if (clp->upcall_address)
|
||||
+ free(clp->upcall_address);
|
||||
+ if (clp->upcall_port)
|
||||
+ free(clp->upcall_port);
|
||||
+ if (clp->upcall_protoname)
|
||||
+ free(clp->upcall_protoname);
|
||||
+ if (clp->upcall_service)
|
||||
+ free(clp->upcall_service);
|
||||
+ }
|
||||
free(clp);
|
||||
}
|
||||
|
||||
@@ -446,6 +462,31 @@ gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data)
|
||||
{
|
||||
struct clnt_info *clp = data;
|
||||
|
||||
+ /* if there was a failure to translate IP to name for this server,
|
||||
+ * try again
|
||||
+ */
|
||||
+ if (!clp->servername) {
|
||||
+ if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr,
|
||||
+ clp->upcall_address, clp->upcall_port ?
|
||||
+ clp->upcall_port : "")) {
|
||||
+ goto do_upcall;
|
||||
+ }
|
||||
+ clp->servername = gssd_get_servername(clp->upcall_address,
|
||||
+ (struct sockaddr *)&clp->addr, clp->upcall_address);
|
||||
+ if (!clp->servername)
|
||||
+ goto do_upcall;
|
||||
+
|
||||
+ if (asprintf(&clp->servicename, "%s@%s", clp->upcall_service,
|
||||
+ clp->servername) < 0) {
|
||||
+ free(clp->servername);
|
||||
+ clp->servername = NULL;
|
||||
+ goto do_upcall;
|
||||
+ }
|
||||
+ clp->prog = clp->upcall_program;
|
||||
+ clp->vers = clp->upcall_vers;
|
||||
+ clp->protocol = strdup(clp->upcall_protoname);
|
||||
+ }
|
||||
+do_upcall:
|
||||
handle_gssd_upcall(clp);
|
||||
}
|
||||
|
||||
diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
|
||||
index 519dc43..4e070ed 100644
|
||||
--- a/utils/gssd/gssd.h
|
||||
+++ b/utils/gssd/gssd.h
|
||||
@@ -86,6 +86,12 @@ struct clnt_info {
|
||||
int gssd_fd;
|
||||
struct event *gssd_ev;
|
||||
struct sockaddr_storage addr;
|
||||
+ char *upcall_address;
|
||||
+ char *upcall_port;
|
||||
+ int upcall_program;
|
||||
+ int upcall_vers;
|
||||
+ char *upcall_protoname;
|
||||
+ char *upcall_service;
|
||||
};
|
||||
|
||||
struct clnt_upcall_info {
|
@ -0,0 +1,30 @@
|
||||
commit 608591ddf1ee59c4dda82ceca3f27c90486c5618
|
||||
Author: Yongcheng Yang <yongcheng.yang@gmail.com>
|
||||
Date: Wed Apr 5 12:11:53 2023 -0400
|
||||
|
||||
nfsmount.conf: Fix typo of the attribute name
|
||||
|
||||
Signed-off-by: Yongcheng Yang <yongcheng.yang@gmail.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/mount/nfsmount.conf b/utils/mount/nfsmount.conf
|
||||
index 342063f..c498eb8 100644
|
||||
--- a/utils/mount/nfsmount.conf
|
||||
+++ b/utils/mount/nfsmount.conf
|
||||
@@ -59,13 +59,13 @@
|
||||
# acregmin=30
|
||||
#
|
||||
# The Maximum time (in seconds) file attributes are cached
|
||||
-# acregmin=60
|
||||
+# acregmax=60
|
||||
#
|
||||
# The minimum time (in seconds) directory attributes are cached
|
||||
-# acregmin=30
|
||||
+# acdirmin=30
|
||||
#
|
||||
# The Maximum time (in seconds) directory attributes are cached
|
||||
-# acregmin=60
|
||||
+# acdirmax=60
|
||||
#
|
||||
# Enable Access Control Lists
|
||||
# Acl=False
|
@ -0,0 +1,24 @@
|
||||
commit a746c35822e557766d1871ec976490a71e6962d9
|
||||
Author: Zhi Li <yieli@redhat.com>
|
||||
Date: Wed Apr 5 12:08:10 2023 -0400
|
||||
|
||||
rpcdebug: avoid buffer underflow if read() returns 0
|
||||
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2176740
|
||||
|
||||
Signed-off-by: Zhi Li <yieli@redhat.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/tools/rpcdebug/rpcdebug.c b/tools/rpcdebug/rpcdebug.c
|
||||
index 68206cc5..ec05179e 100644
|
||||
--- a/tools/rpcdebug/rpcdebug.c
|
||||
+++ b/tools/rpcdebug/rpcdebug.c
|
||||
@@ -257,7 +257,7 @@ get_flags(char *module)
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
- if ((len = read(sysfd, buffer, sizeof(buffer))) < 0) {
|
||||
+ if ((len = read(sysfd, buffer, sizeof(buffer))) <= 0) {
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
@ -0,0 +1,427 @@
|
||||
diff --git a/support/export/cache.c b/support/export/cache.c
|
||||
index a5823e92..396b3b73 100644
|
||||
--- a/support/export/cache.c
|
||||
+++ b/support/export/cache.c
|
||||
@@ -932,6 +932,7 @@ static void write_fsloc(char **bp, int *blen, struct exportent *ep)
|
||||
release_replicas(servers);
|
||||
}
|
||||
#endif
|
||||
+
|
||||
static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask)
|
||||
{
|
||||
struct sec_entry *p;
|
||||
@@ -949,7 +950,20 @@ static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_m
|
||||
qword_addint(bp, blen, p->flav->fnum);
|
||||
qword_addint(bp, blen, p->flags & flag_mask);
|
||||
}
|
||||
+}
|
||||
+
|
||||
+static void write_xprtsec(char **bp, int *blen, struct exportent *ep)
|
||||
+{
|
||||
+ struct xprtsec_entry *p;
|
||||
+
|
||||
+ for (p = ep->e_xprtsec; p->info; p++);
|
||||
+ if (p == ep->e_xprtsec)
|
||||
+ return;
|
||||
|
||||
+ qword_add(bp, blen, "xprtsec");
|
||||
+ qword_addint(bp, blen, p - ep->e_xprtsec);
|
||||
+ for (p = ep->e_xprtsec; p->info; p++)
|
||||
+ qword_addint(bp, blen, p->info->number);
|
||||
}
|
||||
|
||||
static int dump_to_cache(int f, char *buf, int blen, char *domain,
|
||||
@@ -992,6 +1006,7 @@ static int dump_to_cache(int f, char *buf, int blen, char *domain,
|
||||
qword_add(&bp, &blen, "uuid");
|
||||
qword_addhex(&bp, &blen, u, 16);
|
||||
}
|
||||
+ write_xprtsec(&bp, &blen, exp);
|
||||
xlog(D_AUTH, "granted access to %s for %s",
|
||||
path, *domain == '$' ? domain+1 : domain);
|
||||
} else {
|
||||
diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
|
||||
index 0eca828e..be5867cf 100644
|
||||
--- a/support/include/nfs/export.h
|
||||
+++ b/support/include/nfs/export.h
|
||||
@@ -40,4 +40,18 @@
|
||||
#define NFSEXP_OLD_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
|
||||
| NFSEXP_ALLSQUASH)
|
||||
|
||||
+/*
|
||||
+ * Transport layer security policies that are permitted to access
|
||||
+ * an export
|
||||
+ */
|
||||
+#define NFSEXP_XPRTSEC_NONE 0x0001
|
||||
+#define NFSEXP_XPRTSEC_TLS 0x0002
|
||||
+#define NFSEXP_XPRTSEC_MTLS 0x0004
|
||||
+
|
||||
+#define NFSEXP_XPRTSEC_NUM (3)
|
||||
+
|
||||
+#define NFSEXP_XPRTSEC_ALL (NFSEXP_XPRTSEC_NONE | \
|
||||
+ NFSEXP_XPRTSEC_TLS | \
|
||||
+ NFSEXP_XPRTSEC_MTLS)
|
||||
+
|
||||
#endif /* _NSF_EXPORT_H */
|
||||
diff --git a/support/include/nfslib.h b/support/include/nfslib.h
|
||||
index 6faba71b..61c19933 100644
|
||||
--- a/support/include/nfslib.h
|
||||
+++ b/support/include/nfslib.h
|
||||
@@ -62,6 +62,18 @@ struct sec_entry {
|
||||
int flags;
|
||||
};
|
||||
|
||||
+#define XPRTSECMODE_COUNT 3
|
||||
+
|
||||
+struct xprtsec_info {
|
||||
+ const char *name;
|
||||
+ int number;
|
||||
+};
|
||||
+
|
||||
+struct xprtsec_entry {
|
||||
+ const struct xprtsec_info *info;
|
||||
+ int flags;
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* Data related to a single exports entry as returned by getexportent.
|
||||
* FIXME: export options should probably be parsed at a later time to
|
||||
@@ -83,6 +95,7 @@ struct exportent {
|
||||
char * e_fslocdata;
|
||||
char * e_uuid;
|
||||
struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
|
||||
+ struct xprtsec_entry e_xprtsec[XPRTSECMODE_COUNT + 1];
|
||||
unsigned int e_ttl;
|
||||
char * e_realpath;
|
||||
};
|
||||
@@ -99,6 +112,7 @@ struct rmtabent {
|
||||
void setexportent(char *fname, char *type);
|
||||
struct exportent * getexportent(int,int);
|
||||
void secinfo_show(FILE *fp, struct exportent *ep);
|
||||
+void xprtsecinfo_show(FILE *fp, struct exportent *ep);
|
||||
void putexportent(struct exportent *xep);
|
||||
void endexportent(void);
|
||||
struct exportent * mkexportent(char *hname, char *path, char *opts);
|
||||
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
|
||||
index ec6f8013..d36f7664 100644
|
||||
--- a/support/nfs/exports.c
|
||||
+++ b/support/nfs/exports.c
|
||||
@@ -99,6 +99,7 @@ static void init_exportent (struct exportent *ee, int fromkernel)
|
||||
ee->e_fslocmethod = FSLOC_NONE;
|
||||
ee->e_fslocdata = NULL;
|
||||
ee->e_secinfo[0].flav = NULL;
|
||||
+ ee->e_xprtsec[0].info = NULL;
|
||||
ee->e_nsquids = 0;
|
||||
ee->e_nsqgids = 0;
|
||||
ee->e_uuid = NULL;
|
||||
@@ -122,7 +123,7 @@ getexportent(int fromkernel, int fromexports)
|
||||
if (first || (ok = getexport(exp, sizeof(exp))) == 0) {
|
||||
has_default_opts = 0;
|
||||
has_default_subtree_opts = 0;
|
||||
-
|
||||
+
|
||||
init_exportent(&def_ee, fromkernel);
|
||||
|
||||
ok = getpath(def_ee.e_path, sizeof(def_ee.e_path));
|
||||
@@ -146,7 +147,7 @@ getexportent(int fromkernel, int fromexports)
|
||||
if (exp[0] == '-' && !fromkernel) {
|
||||
if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0)
|
||||
return NULL;
|
||||
-
|
||||
+
|
||||
has_default_opts = 1;
|
||||
|
||||
ok = getexport(exp, sizeof(exp));
|
||||
@@ -239,7 +240,6 @@ void secinfo_show(FILE *fp, struct exportent *ep)
|
||||
if (ep->e_secinfo[0].flav == NULL)
|
||||
secinfo_addflavor(find_flavor("sys"), ep);
|
||||
for (p1=ep->e_secinfo; p1->flav; p1=p2) {
|
||||
-
|
||||
fprintf(fp, ",sec=%s", p1->flav->flavour);
|
||||
for (p2=p1+1; (p2->flav != NULL) && (p1->flags == p2->flags);
|
||||
p2++) {
|
||||
@@ -249,6 +249,17 @@ void secinfo_show(FILE *fp, struct exportent *ep)
|
||||
}
|
||||
}
|
||||
|
||||
+void xprtsecinfo_show(FILE *fp, struct exportent *ep)
|
||||
+{
|
||||
+ struct xprtsec_entry *p1, *p2;
|
||||
+
|
||||
+ for (p1 = ep->e_xprtsec; p1->info; p1 = p2) {
|
||||
+ fprintf(fp, ",xprtsec=%s", p1->info->name);
|
||||
+ for (p2 = p1 + 1; p2->info && (p1->flags == p2->flags); p2++)
|
||||
+ fprintf(fp, ":%s", p2->info->name);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void
|
||||
fprintpath(FILE *fp, const char *path)
|
||||
{
|
||||
@@ -345,6 +356,7 @@ putexportent(struct exportent *ep)
|
||||
}
|
||||
fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid);
|
||||
secinfo_show(fp, ep);
|
||||
+ xprtsecinfo_show(fp, ep);
|
||||
fprintf(fp, ")\n");
|
||||
}
|
||||
|
||||
@@ -483,6 +495,75 @@ static unsigned int parse_flavors(char *str, struct exportent *ep)
|
||||
return out;
|
||||
}
|
||||
|
||||
+static const struct xprtsec_info xprtsec_name2info[] = {
|
||||
+ { "none", NFSEXP_XPRTSEC_NONE },
|
||||
+ { "tls", NFSEXP_XPRTSEC_TLS },
|
||||
+ { "mtls", NFSEXP_XPRTSEC_MTLS },
|
||||
+ { NULL, 0 }
|
||||
+};
|
||||
+
|
||||
+static const struct xprtsec_info *find_xprtsec_info(const char *name)
|
||||
+{
|
||||
+ const struct xprtsec_info *info;
|
||||
+
|
||||
+ for (info = xprtsec_name2info; info->name; info++)
|
||||
+ if (strcmp(info->name, name) == 0)
|
||||
+ return info;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Append the given xprtsec mode to the exportent's e_xprtsec array,
|
||||
+ * or do nothing if it's already there. Returns the index of flavor in
|
||||
+ * the resulting array in any case.
|
||||
+ */
|
||||
+static int xprtsec_addmode(const struct xprtsec_info *info, struct exportent *ep)
|
||||
+{
|
||||
+ struct xprtsec_entry *p;
|
||||
+
|
||||
+ for (p = ep->e_xprtsec; p->info; p++)
|
||||
+ if (p->info == info || p->info->number == info->number)
|
||||
+ return p - ep->e_xprtsec;
|
||||
+
|
||||
+ if (p - ep->e_xprtsec >= XPRTSECMODE_COUNT) {
|
||||
+ xlog(L_ERROR, "more than %d xprtsec modes on an export\n",
|
||||
+ XPRTSECMODE_COUNT);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ p->info = info;
|
||||
+ p->flags = ep->e_flags;
|
||||
+ (p + 1)->info = NULL;
|
||||
+ return p - ep->e_xprtsec;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * @str is a colon seperated list of transport layer security modes.
|
||||
+ * Their order is recorded in @ep, and a bitmap corresponding to the
|
||||
+ * list is returned.
|
||||
+ *
|
||||
+ * A zero return indicates an error.
|
||||
+ */
|
||||
+static unsigned int parse_xprtsec(char *str, struct exportent *ep)
|
||||
+{
|
||||
+ unsigned int out = 0;
|
||||
+ char *name;
|
||||
+
|
||||
+ while ((name = strsep(&str, ":"))) {
|
||||
+ const struct xprtsec_info *info = find_xprtsec_info(name);
|
||||
+ int bit;
|
||||
+
|
||||
+ if (!info) {
|
||||
+ xlog(L_ERROR, "unknown xprtsec mode %s\n", name);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ bit = xprtsec_addmode(info, ep);
|
||||
+ if (bit < 0)
|
||||
+ return 0;
|
||||
+ out |= 1 << bit;
|
||||
+ }
|
||||
+ return out;
|
||||
+}
|
||||
+
|
||||
/* Sets the bits in @mask for the appropriate security flavor flags. */
|
||||
static void setflags(int mask, unsigned int active, struct exportent *ep)
|
||||
{
|
||||
@@ -621,7 +702,7 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
|
||||
ep->e_anonuid = strtol(opt+8, &oe, 10);
|
||||
if (opt[8]=='\0' || *oe != '\0') {
|
||||
xlog(L_ERROR, "%s: %d: bad anonuid \"%s\"\n",
|
||||
- flname, flline, opt);
|
||||
+ flname, flline, opt);
|
||||
bad_option:
|
||||
free(opt);
|
||||
return -1;
|
||||
@@ -631,7 +712,7 @@ bad_option:
|
||||
ep->e_anongid = strtol(opt+8, &oe, 10);
|
||||
if (opt[8]=='\0' || *oe != '\0') {
|
||||
xlog(L_ERROR, "%s: %d: bad anongid \"%s\"\n",
|
||||
- flname, flline, opt);
|
||||
+ flname, flline, opt);
|
||||
goto bad_option;
|
||||
}
|
||||
} else if (strncmp(opt, "squash_uids=", 12) == 0) {
|
||||
@@ -649,13 +730,13 @@ bad_option:
|
||||
setflags(NFSEXP_FSID, active, ep);
|
||||
} else {
|
||||
ep->e_fsid = strtoul(opt+5, &oe, 0);
|
||||
- if (opt[5]!='\0' && *oe == '\0')
|
||||
+ if (opt[5]!='\0' && *oe == '\0')
|
||||
setflags(NFSEXP_FSID, active, ep);
|
||||
else if (valid_uuid(opt+5))
|
||||
ep->e_uuid = strdup(opt+5);
|
||||
else {
|
||||
xlog(L_ERROR, "%s: %d: bad fsid \"%s\"\n",
|
||||
- flname, flline, opt);
|
||||
+ flname, flline, opt);
|
||||
goto bad_option;
|
||||
}
|
||||
}
|
||||
@@ -688,6 +769,9 @@ bad_option:
|
||||
active = parse_flavors(opt+4, ep);
|
||||
if (!active)
|
||||
goto bad_option;
|
||||
+ } else if (strncmp(opt, "xprtsec=", 8) == 0) {
|
||||
+ if (!parse_xprtsec(opt + 8, ep))
|
||||
+ goto bad_option;
|
||||
} else {
|
||||
xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
|
||||
flname, flline, opt);
|
||||
@@ -709,7 +793,7 @@ out:
|
||||
if (warn && !had_subtree_opt)
|
||||
xlog(L_WARNING, "%s [%d]: Neither 'subtree_check' or 'no_subtree_check' specified for export \"%s:%s\".\n"
|
||||
" Assuming default behaviour ('no_subtree_check').\n"
|
||||
- " NOTE: this default has changed since nfs-utils version 1.0.x\n",
|
||||
+ " NOTE: this default has changed since nfs-utils version 1.0.x\n",
|
||||
|
||||
flname, flline,
|
||||
ep->e_hostname, ep->e_path);
|
||||
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
|
||||
index 6ba615d1..a87a7806 100644
|
||||
--- a/utils/exportfs/exportfs.c
|
||||
+++ b/utils/exportfs/exportfs.c
|
||||
@@ -743,6 +743,7 @@ dump(int verbose, int export_format)
|
||||
#endif
|
||||
}
|
||||
secinfo_show(stdout, ep);
|
||||
+ xprtsecinfo_show(stdout, ep);
|
||||
printf("%c\n", (c != '(')? ')' : ' ');
|
||||
}
|
||||
}
|
||||
diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
|
||||
index 54b3f877..83dd6807 100644
|
||||
--- a/utils/exportfs/exports.man
|
||||
+++ b/utils/exportfs/exports.man
|
||||
@@ -125,7 +125,55 @@ In that case you may include multiple sec= options, and following options
|
||||
will be enforced only for access using flavors listed in the immediately
|
||||
preceding sec= option. The only options that are permitted to vary in
|
||||
this way are ro, rw, no_root_squash, root_squash, and all_squash.
|
||||
+.SS Transport layer security
|
||||
+The Linux NFS server allows the use of RPC-with-TLS (RFC 9289) to
|
||||
+protect RPC traffic between itself and its clients.
|
||||
+Alternately, administrators can secure NFS traffic using a VPN,
|
||||
+or an ssh tunnel or similar mechanism, in a way that is transparent
|
||||
+to the server.
|
||||
.PP
|
||||
+To enable the use of RPC-with-TLS, the server's administrator must
|
||||
+install and configure
|
||||
+.BR tlshd
|
||||
+to handle transport layer security handshake requests from the local
|
||||
+kernel.
|
||||
+Clients can then choose to use RPC-with-TLS or they may continue
|
||||
+operating without it.
|
||||
+.PP
|
||||
+Administrators may require the use of RPC-with-TLS to protect access
|
||||
+to individual exports.
|
||||
+This is particularly useful when using non-cryptographic security
|
||||
+flavors such as
|
||||
+.IR sec=sys .
|
||||
+The
|
||||
+.I xprtsec=
|
||||
+option, followed by an unordered colon-delimited list of security policies,
|
||||
+can restrict access to the export to only clients that have negotiated
|
||||
+transport-layer security.
|
||||
+Currently supported transport layer security policies include:
|
||||
+.TP
|
||||
+.IR none
|
||||
+The server permits clients to access the export
|
||||
+without the use of transport layer security.
|
||||
+.TP
|
||||
+.IR tls
|
||||
+The server permits clients that have negotiated an RPC-with-TLS session
|
||||
+without peer authentication (confidentiality only) to access the export.
|
||||
+Clients are not required to offer an x.509 certificate
|
||||
+when establishing a transport layer security session.
|
||||
+.TP
|
||||
+.IR mtls
|
||||
+The server permits clients that have negotiated an RPC-with-TLS session
|
||||
+with peer authentication to access the export.
|
||||
+The server requires clients to offer an x.509 certificate
|
||||
+when establishing a transport layer security session.
|
||||
+.PP
|
||||
+If RPC-with-TLS is configured and enabled and the
|
||||
+.I xprtsec=
|
||||
+option is not specified, the default setting for an export is
|
||||
+.IR xprtsec=none:tls:mtls .
|
||||
+With this setting, the server permits clients to use any transport
|
||||
+layer security mechanism or none at all to access the export.
|
||||
.SS General Options
|
||||
.BR exportfs
|
||||
understands the following export options:
|
||||
@@ -581,7 +629,8 @@ a character class wildcard match.
|
||||
.BR netgroup (5),
|
||||
.BR mountd (8),
|
||||
.BR nfsd (8),
|
||||
-.BR showmount (8).
|
||||
+.BR showmount (8),
|
||||
+.BR tlshd (8).
|
||||
.\".SH DIAGNOSTICS
|
||||
.\"An error parsing the file is reported using syslogd(8) as level NOTICE from
|
||||
.\"a DAEMON whenever
|
||||
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
|
||||
index d9f34df3..dfc31a5d 100644
|
||||
--- a/utils/mount/nfs.man
|
||||
+++ b/utils/mount/nfs.man
|
||||
@@ -574,7 +574,43 @@ The
|
||||
.B sloppy
|
||||
option is an alternative to specifying
|
||||
.BR mount.nfs " -s " option.
|
||||
-
|
||||
+.TP 1.5i
|
||||
+.BI xprtsec= policy
|
||||
+Specifies the use of transport layer security to protect NFS network
|
||||
+traffic on behalf of this mount point.
|
||||
+.I policy
|
||||
+can be one of
|
||||
+.BR none ,
|
||||
+.BR tls ,
|
||||
+or
|
||||
+.BR mtls .
|
||||
+.IP
|
||||
+If
|
||||
+.B none
|
||||
+is specified,
|
||||
+transport layer security is forced off, even if the NFS server supports
|
||||
+transport layer security.
|
||||
+If
|
||||
+.B tls
|
||||
+is specified, the client uses RPC-with-TLS to provide in-transit
|
||||
+confidentiality.
|
||||
+If
|
||||
+.B mtls
|
||||
+is specified, the client uses RPC-with-TLS to authenticate itself and
|
||||
+to provide in-transit confidentiality.
|
||||
+If either
|
||||
+.B tls
|
||||
+or
|
||||
+.B mtls
|
||||
+is specified and the server does not support RPC-with-TLS or peer
|
||||
+authentication fails, the mount attempt fails.
|
||||
+.IP
|
||||
+If the
|
||||
+.B xprtsec=
|
||||
+option is not specified,
|
||||
+the default behavior depends on the kernel version,
|
||||
+but is usually equivalent to
|
||||
+.BR "xprtsec=none" .
|
||||
.SS "Options for NFS versions 2 and 3 only"
|
||||
Use these options, along with the options in the above subsection,
|
||||
for NFS versions 2 and 3 only.
|
Loading…
Reference in new issue