Multiple important patches have been queued up in the cifs-utils for-next branch (see attached or the link https://git.samba.org/?p=cifs-utils.git;a=shortlog;h=refs/heads/for-next and its mirror smb3-utils for-next) over the past four months, and wanted to make sure no objections, or problems to the 14 currently there. Let us know if anything important missing before the next update (to version 7.2) -- Thanks, Steve
From e44d4b12f9b5c07550e738142c111dd8916fa976 Mon Sep 17 00:00:00 2001 From: Thiago Becker <tbecker@xxxxxxxxxx> Date: Tue, 14 Jan 2025 17:34:49 -0300 Subject: [PATCH 11/14] cifscreds: use continue instead of break when matching commands While matching the commands in cifscreds, continue attempting to match to detect ambiguous commands. Reviewed-by: Paulo Alcantara (Red Hat) <pc@xxxxxxxxxxxxx> Signed-off-by: Thiago Becker <tbecker@xxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- cifscreds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cifscreds.c b/cifscreds.c index 32f2ee4..c52f495 100644 --- a/cifscreds.c +++ b/cifscreds.c @@ -501,7 +501,7 @@ int main(int argc, char **argv) if (cmd->name[n] == 0) { /* exact match */ best = cmd; - break; + continue; } /* partial match */ -- 2.43.0
From 0fec5847be61f77939a532cbce876227b65a1861 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni <thomas.petazzoni@xxxxxxxxxxx> Date: Thu, 26 Dec 2024 21:42:12 +0100 Subject: [PATCH 13/14] configure.ac: libtalloc is now mandatory Since commit c6bf4d9a59809fbb0c22ef9eb167c099ab8089fb ("Implement CLDAP Ping to find the closest site"), libtalloc is mandatory to cifs-utils. This needs to be reflected in the configure.ac script to get a failure at configure time and not build time. Reviewed-by: Paulo Alcantara (Red Hat) <pc@xxxxxxxxxxxxx> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@xxxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- configure.ac | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index b84c41f..b74358d 100644 --- a/configure.ac +++ b/configure.ac @@ -133,6 +133,10 @@ AC_CHECK_HEADERS([arpa/inet.h ctype.h fcntl.h inttypes.h limits.h mntent.h netdb AC_CHECK_HEADERS([sys/fsuid.h]) AC_CHECK_FUNC(setfsuid, , [AC_MSG_ERROR([System does not support setfsuid()])]) +# libtalloc +AC_CHECK_HEADERS([talloc.h], ,[AC_MSG_ERROR([talloc.h not found, consider installing libtalloc-devel.])]) +AC_CHECK_LIB(talloc, talloc_init, ,[AC_MSG_ERROR([talloc.h not found, consider installing libtalloc-devel.])]) + # FIXME: add test(s) to autodisable these flags when compiler/linker don't support it if test $enable_pie != "no"; then PIE_CFLAGS="-fpie -pie" @@ -177,16 +181,6 @@ if test $enable_cifsupcall != "no"; then [Whether the krb5_keyblock struct has a keyvalue property]) fi fi -if test $enable_cifsupcall != "no"; then - AC_CHECK_HEADERS([talloc.h], , [ - if test "$enable_cifsupcall" = "yes"; then - AC_MSG_ERROR([talloc.h not found, consider installing libtalloc-devel.]) - else - AC_MSG_WARN([talloc.h not found, consider installing libtalloc-devel. Disabling cifs.upcall.]) - enable_cifsupcall="no" - fi - ]) -fi if test $enable_cifsupcall != "no" -o $enable_cifsidmap != "no"; then AC_CHECK_HEADERS([keyutils.h], , [ if test "$enable_cifsupcall" = "yes"; then -- 2.43.0
From 261da7e083d101cd9e02685de1afce12eec596c2 Mon Sep 17 00:00:00 2001 From: Thiago Becker <tbecker@xxxxxxxxxx> Date: Tue, 14 Jan 2025 17:35:09 -0300 Subject: [PATCH 12/14] cifscreds: allow user to set the key's timeout Allow the user to set the key's timeout when adding a new credential. Reviewed-by: Paulo Alcantara (Red Hat) <pc@xxxxxxxxxxxxx> Signed-off-by: Thiago Becker <tbecker@xxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- cifscreds.c | 17 +++++++++++------ cifskey.c | 12 ++++++++++-- cifskey.h | 7 ++++++- pam_cifscreds.c | 4 ++-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/cifscreds.c b/cifscreds.c index c52f495..f552bc8 100644 --- a/cifscreds.c +++ b/cifscreds.c @@ -43,6 +43,7 @@ struct cmdarg { char *host; char *user; char keytype; + unsigned int timeout; }; struct command { @@ -59,7 +60,7 @@ static int cifscreds_update(struct cmdarg *arg); static const char *thisprogram; static struct command commands[] = { - { cifscreds_add, "add", "[-u username] [-d] <host|domain>" }, + { cifscreds_add, "add", "[-u username] [-d] <host|domain> [-t timeout]" }, { cifscreds_clear, "clear", "[-u username] [-d] <host|domain>" }, { cifscreds_clearall, "clearall", "" }, { cifscreds_update, "update", "[-u username] [-d] <host|domain>" }, @@ -69,6 +70,7 @@ static struct command commands[] = { static struct option longopts[] = { {"username", 1, NULL, 'u'}, {"domain", 0, NULL, 'd' }, + {"timeout", 0, NULL, 't' }, {NULL, 0, NULL, 0} }; @@ -218,7 +220,7 @@ static int cifscreds_add(struct cmdarg *arg) *nextaddress++ = '\0'; while (currentaddress) { - key_serial_t key = key_add(currentaddress, arg->user, pass, arg->keytype); + key_serial_t key = key_add(currentaddress, arg->user, pass, arg->keytype, arg->timeout); if (key <= 0) { fprintf(stderr, "error: Add credential key for %s: %s\n", currentaddress, strerror(errno)); @@ -253,7 +255,7 @@ static int cifscreds_clear(struct cmdarg *arg) char *currentaddress, *nextaddress; int ret = 0, count = 0, errors = 0; - if (arg->host == NULL || arg->user == NULL) + if (arg->host == NULL || arg->user == NULL || arg->timeout) return usage(); if (arg->keytype == 'd') @@ -362,7 +364,7 @@ static int cifscreds_update(struct cmdarg *arg) char *addrs[16]; int ret = 0, id, count = 0; - if (arg->host == NULL || arg->user == NULL) + if (arg->host == NULL || arg->user == NULL || arg->timeout) return usage(); if (arg->keytype == 'd') @@ -419,7 +421,7 @@ static int cifscreds_update(struct cmdarg *arg) pass = getpass("Password: "); for (id = 0; id < count; id++) { - key_serial_t key = key_add(addrs[id], arg->user, pass, arg->keytype); + key_serial_t key = key_add(addrs[id], arg->user, pass, arg->keytype, 0); if (key <= 0) fprintf(stderr, "error: Update credential key " "for %s: %s\n", addrs[id], strerror(errno)); @@ -474,7 +476,7 @@ int main(int argc, char **argv) if (argc == 1) return usage(); - while((n = getopt_long(argc, argv, "du:", longopts, NULL)) != -1) { + while((n = getopt_long(argc, argv, "dut:", longopts, NULL)) != -1) { switch (n) { case 'd': arg.keytype = (char) n; @@ -482,6 +484,9 @@ int main(int argc, char **argv) case 'u': arg.user = optarg; break; + case 't': + arg.timeout = atoi(optarg); + break; default: return usage(); } diff --git a/cifskey.c b/cifskey.c index 919540f..4fef02f 100644 --- a/cifskey.c +++ b/cifskey.c @@ -40,11 +40,12 @@ key_search(const char *addr, char keytype) /* add or update a specific key to keyring */ key_serial_t -key_add(const char *addr, const char *user, const char *pass, char keytype) +key_add(const char *addr, const char *user, const char *pass, char keytype, unsigned timeout) { int len; char desc[INET6_ADDRSTRLEN + sizeof(KEY_PREFIX) + 4]; char val[MOUNT_PASSWD_SIZE + MAX_USERNAME_SIZE + 2]; + key_serial_t key; /* set key description */ if (snprintf(desc, sizeof(desc), "%s:%c:%s", KEY_PREFIX, keytype, addr) >= (int)sizeof(desc)) { @@ -59,5 +60,12 @@ key_add(const char *addr, const char *user, const char *pass, char keytype) return -1; } - return add_key(CIFS_KEY_TYPE, desc, val, len + 1, DEST_KEYRING); + if ((key = add_key(CIFS_KEY_TYPE, desc, val, len + 1, DEST_KEYRING)) < 0) { + return -1; + } + + if (timeout > 0) + keyctl_set_timeout(key, timeout); + + return key; } diff --git a/cifskey.h b/cifskey.h index ed0c469..0069445 100644 --- a/cifskey.h +++ b/cifskey.h @@ -41,7 +41,12 @@ #define CIFS_KEY_PERMS (KEY_POS_VIEW|KEY_POS_WRITE|KEY_POS_SEARCH| \ KEY_USR_VIEW|KEY_USR_WRITE|KEY_USR_SEARCH) +/** + * Default key timeout is 24 hours + */ +#define DEFAULT_KEY_TIMEOUT (24 * 60 * 60) + key_serial_t key_search(const char *addr, char keytype); -key_serial_t key_add(const char *addr, const char *user, const char *pass, char keytype); +key_serial_t key_add(const char *addr, const char *user, const char *pass, char keytype, unsigned timeout); #endif /* _CIFSKEY_H */ diff --git a/pam_cifscreds.c b/pam_cifscreds.c index eb9851d..2b8c0b6 100644 --- a/pam_cifscreds.c +++ b/pam_cifscreds.c @@ -232,7 +232,7 @@ static int cifscreds_pam_add(pam_handle_t *ph, const char *user, const char *pas *nextaddress++ = '\0'; while (currentaddress) { - key_serial_t key = key_add(currentaddress, user, password, keytype); + key_serial_t key = key_add(currentaddress, user, password, keytype, DEFAULT_KEY_TIMEOUT); if (key <= 0) { pam_syslog(ph, LOG_ERR, "error: Add credential key for %s: %s", currentaddress, strerror(errno)); @@ -335,7 +335,7 @@ static int cifscreds_pam_update(pam_handle_t *ph, const char *user, const char * } for (id = 0; id < count; id++) { - key_serial_t key = key_add(currentaddress, user, password, keytype); + key_serial_t key = key_add(currentaddress, user, password, keytype, DEFAULT_KEY_TIMEOUT); if (key <= 0) { pam_syslog(ph, LOG_ERR, "error: Update credential key for %s: %s", (currentaddress ?: "(null)"), strerror(errno)); -- 2.43.0
From 18169a919fbe9fe67277e17bb8c9e0d28e143896 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni <thomas.petazzoni@xxxxxxxxxxx> Date: Thu, 26 Dec 2024 21:42:35 +0100 Subject: [PATCH 14/14] cldap_ping.c: add missing <sys/types.h> include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: cldap_ping.c: In function ‘read_dns_string’: cldap_ping.c:72:37: error: ‘u_char’ undeclared (first use in this function) when building with the musl C library, but even with glibc u_char is defined in <sys/types.h>, it happens to work with glibc <sys/types.h> gets included by another header. Reviewed-by: Paulo Alcantara (Red Hat) <pc@xxxxxxxxxxxxx> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@xxxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- cldap_ping.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cldap_ping.c b/cldap_ping.c index 9183b27..a603be3 100644 --- a/cldap_ping.c +++ b/cldap_ping.c @@ -20,6 +20,7 @@ #include <talloc.h> #include <string.h> #include <sys/socket.h> +#include <sys/types.h> #include <arpa/inet.h> #include <unistd.h> #include <resolv.h> -- 2.43.0
From 4fd906f26ab7d648136b65dc0c63d4ba545f0e6d Mon Sep 17 00:00:00 2001 From: Meetakshi Setiya <msetiya@xxxxxxxxxxxxx> Date: Thu, 2 Jan 2025 10:42:22 +0000 Subject: [PATCH 10/14] Do not pass passwords with sec=none and sec=krb5 --- mount.cifs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mount.cifs.c b/mount.cifs.c index dd7dc80..e46693e 100644 --- a/mount.cifs.c +++ b/mount.cifs.c @@ -198,6 +198,7 @@ struct parsed_mount_info { unsigned int nofail:1; unsigned int got_domain:1; unsigned int is_krb5:1; + unsigned int is_noauth:1; uid_t sudo_uid; }; @@ -954,6 +955,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) case OPT_SEC: if (value) { if (!strncmp(value, "none", 4)) { + parsed_info->is_noauth = 1; parsed_info->got_password = 1; parsed_info->got_password2 = 1; } @@ -2328,7 +2330,7 @@ mount_retry: fprintf(stderr, "%s kernel mount options: %s", thisprogram, options); - if (parsed_info->got_password) { + if (parsed_info->got_password && !(parsed_info->is_krb5 || parsed_info->is_noauth)) { /* * Commas have to be doubled, or else they will * look like the parameter separator @@ -2339,7 +2341,7 @@ mount_retry: fprintf(stderr, ",pass=********"); } - if (parsed_info->got_password2) { + if (parsed_info->got_password2 && !(parsed_info->is_krb5 || parsed_info->is_noauth)) { strlcat(options, ",password2=", options_size); strlcat(options, parsed_info->password2, options_size); if (parsed_info->verboseflag) -- 2.43.0
From adfdc239717339700537eb5bcb7638483cc0d8d9 Mon Sep 17 00:00:00 2001 From: Henrique Carvalho <henrique.carvalho@xxxxxxxx> Date: Sat, 5 Oct 2024 11:50:53 -0300 Subject: [PATCH 07/14] docs: update actimeo description Signed-off-by: Henrique Carvalho <henrique.carvalho@xxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- mount.cifs.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mount.cifs.rst b/mount.cifs.rst index 5281896..e4d88c4 100644 --- a/mount.cifs.rst +++ b/mount.cifs.rst @@ -600,7 +600,8 @@ actimeo=arg the server. Longer timeouts mean a reduced number of calls to the server but looser cache coherency. The ``actimeo`` value is a positive integer that can hold values between 0 and a maximum value of 2^30 \* - HZ (frequency of timer interrupt) setting. + HZ (frequency of timer interrupt) setting. Setting it to 0 disables + caching. acregmax=arg The maximum time (in seconds) that the CIFS client caches attributes of a -- 2.43.0
From bc76f3a121734c4215745df360b23e39e7deb2a3 Mon Sep 17 00:00:00 2001 From: Henrique Carvalho <henrique.carvalho@xxxxxxxx> Date: Wed, 18 Dec 2024 19:10:13 -0300 Subject: [PATCH 09/14] docs: add esize description Signed-off-by: Henrique Carvalho <henrique.carvalho@xxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- mount.cifs.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mount.cifs.rst b/mount.cifs.rst index 756ecd3..67c5138 100644 --- a/mount.cifs.rst +++ b/mount.cifs.rst @@ -402,6 +402,19 @@ seal Request encryption at the SMB layer. The encryption algorithm used is AES-128-CCM. Requires SMB3 or above (see ``vers``). +esize=arg + The minimum size (in bytes) of an encrypted read response at which the + client will offload decryption to a separate worker thread. This will work + when the number of in-flight requests are greater than 1. + + Decryption of large encrypted read responses can be computationally expensive + and, when multiple reads are in flight, offloading the work can improve + performance. + + The default is ``esize=0``, which means that all encrypted read responses are + decrypted without offload and can be set up to the maximum buffer size, which + can range from 8192 to 130048 bytes, and defaults to 16384 bytes. + rdma Connect directly to the server using SMB Direct via a RDMA adapter. Requires SMB3 or above (see ``vers``). -- 2.43.0
From 041ea42c7fbfae9cc4949c40677bc411c2dce129 Mon Sep 17 00:00:00 2001 From: Henrique Carvalho <henrique.carvalho@xxxxxxxx> Date: Wed, 18 Dec 2024 18:03:41 -0300 Subject: [PATCH 08/14] docs: add max_cached_dirs description Signed-off-by: Henrique Carvalho <henrique.carvalho@xxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- mount.cifs.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mount.cifs.rst b/mount.cifs.rst index e4d88c4..756ecd3 100644 --- a/mount.cifs.rst +++ b/mount.cifs.rst @@ -285,6 +285,14 @@ handlecache nohandlecache Disable caching of the share root directory handle. +max_cached_dirs=arg + The maximum number of cached directories per share. Directories are cached locally + when a lease is granted by the server, which improves performance by reducing network + traffic. + + By default, ``max_cached_dirs`` is set to 16 and can hold values between 0 + and a maximum value of 2^32 - 1. + handletimeout=arg The time (in milliseconds) for which the server should reserve the handle after a failover waiting for the client to reconnect. When mounting with -- 2.43.0
From d695fa89e47e2c37e79a43e6d07c13f25d2e7307 Mon Sep 17 00:00:00 2001 From: Meetakshi Setiya <msetiya@xxxxxxxxxxxxx> Date: Fri, 6 Dec 2024 01:58:50 -0500 Subject: [PATCH 06/14] Fix compiler warnings in mount.cifs Signed-off-by: Meetakshi Setiya <msetiya@xxxxxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- mount.cifs.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/mount.cifs.c b/mount.cifs.c index 041e64f..dd7dc80 100644 --- a/mount.cifs.c +++ b/mount.cifs.c @@ -859,7 +859,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) * wide +1 for NULL, and +1 for good measure */ char txtbuf[22]; - unsigned long long snapshot; + unsigned long long snapshot = 0; struct tm tm; /* make sure we're starting from beginning */ @@ -1266,7 +1266,11 @@ nocopy: strlcat(out, ",", MAX_OPTIONS_LEN); out_len++; } - snprintf(out + out_len, word_len + 5, "uid=%s", txtbuf); + rc = snprintf(out + out_len, word_len + 5, "uid=%s", txtbuf); + if (rc < 0) { + fprintf(stderr, "Error in creating mount string\n"); + return EX_SYSERR; + } out_len = strlen(out); } if (parsed_info->is_krb5 && parsed_info->sudo_uid) { @@ -1286,7 +1290,11 @@ nocopy: strlcat(out, ",", MAX_OPTIONS_LEN); out_len++; } - snprintf(out + out_len, word_len + 7, "cruid=%s", txtbuf); + rc = snprintf(out + out_len, word_len + 7, "cruid=%s", txtbuf); + if (rc < 0) { + fprintf(stderr, "Error in creating mount string\n"); + return EX_SYSERR; + } out_len = strlen(out); } if (got_gid) { @@ -1302,7 +1310,11 @@ nocopy: strlcat(out, ",", MAX_OPTIONS_LEN); out_len++; } - snprintf(out + out_len, word_len + 5, "gid=%s", txtbuf); + rc = snprintf(out + out_len, word_len + 5, "gid=%s", txtbuf); + if (rc < 0) { + fprintf(stderr, "Error in creating mount string\n"); + return EX_SYSERR; + } out_len = strlen(out); } if (got_bkupuid) { @@ -1318,7 +1330,11 @@ nocopy: strlcat(out, ",", MAX_OPTIONS_LEN); out_len++; } - snprintf(out + out_len, word_len + 11, "backupuid=%s", txtbuf); + rc = snprintf(out + out_len, word_len + 11, "backupuid=%s", txtbuf); + if (rc < 0) { + fprintf(stderr, "Error in creating mount string\n"); + return EX_SYSERR; + } out_len = strlen(out); } if (got_bkupgid) { @@ -1334,7 +1350,11 @@ nocopy: strlcat(out, ",", MAX_OPTIONS_LEN); out_len++; } - snprintf(out + out_len, word_len + 11, "backupgid=%s", txtbuf); + rc = snprintf(out + out_len, word_len + 11, "backupgid=%s", txtbuf); + if (rc < 0) { + fprintf(stderr, "Error in creating mount string\n"); + return EX_SYSERR; + } out_len = strlen(out); } if (got_snapshot) { @@ -1350,7 +1370,11 @@ nocopy: strlcat(out, ",", MAX_OPTIONS_LEN); out_len++; } - snprintf(out + out_len, word_len + 10, "snapshot=%s", txtbuf); + rc = snprintf(out + out_len, word_len + 10, "snapshot=%s", txtbuf); + if (rc < 0) { + fprintf(stderr, "Error in creating mount string\n"); + return EX_SYSERR; + } out_len = strlen(out); } -- 2.43.0
From 454ae44edf93ecfb10cfb1860333b5bf7fa430f8 Mon Sep 17 00:00:00 2001 From: Ritvik Budhiraja <rbudhiraja@xxxxxxxxxxxxx> Date: Tue, 19 Nov 2024 06:07:58 +0000 Subject: [PATCH 05/14] CIFS.upcall to accomodate new namespace mount opt NOTE: This patch is dependent on one of the previously sent patches: [PATCH] CIFS: New mount option for cifs.upcall namespace resolution which introduces a new mount option called upcall_target, to customise the upcall behaviour. Building upon the above patch, the following patch adds functionality to handle upcall_target as a mount option in cifs.upcall. It can have 2 values - mount, app. Having this new mount option allows the mount command to specify where the upcall should happen: 'mount' for resolving the upcall to the host namespace, and 'app' for resolving the upcall to the ns of the calling thread. This will enable both the scenarios where the Kerberos credentials can be found on the application namespace or the host namespace to which just the mount operation is "delegated". This aids use cases like Kubernetes where the mount happens on behalf of the application in another container altogether. Signed-off-by: Ritvik Budhiraja <rbudhiraja@xxxxxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- cifs.upcall.c | 55 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/cifs.upcall.c b/cifs.upcall.c index 4ad0c8e..678b140 100644 --- a/cifs.upcall.c +++ b/cifs.upcall.c @@ -992,6 +992,13 @@ struct decoded_args { #define MAX_USERNAME_SIZE 256 char username[MAX_USERNAME_SIZE + 1]; +#define MAX_UPCALL_STRING_LEN 6 /* "mount\0" */ + enum upcall_target_enum { + UPTARGET_UNSPECIFIED, /* not specified, defaults to app */ + UPTARGET_MOUNT, /* upcall to the mount namespace */ + UPTARGET_APP, /* upcall to the application namespace which did the mount */ + } upcall_target; + uid_t uid; uid_t creduid; pid_t pid; @@ -1008,6 +1015,7 @@ struct decoded_args { #define DKD_HAVE_PID 0x20 #define DKD_HAVE_CREDUID 0x40 #define DKD_HAVE_USERNAME 0x80 +#define DKD_HAVE_UPCALL_TARGET 0x100 #define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC) int have; }; @@ -1018,6 +1026,7 @@ __decode_key_description(const char *desc, struct decoded_args *arg) size_t len; char *pos; const char *tkn = desc; + arg->upcall_target = UPTARGET_UNSPECIFIED; do { pos = index(tkn, ';'); @@ -1116,6 +1125,31 @@ __decode_key_description(const char *desc, struct decoded_args *arg) } arg->have |= DKD_HAVE_VERSION; syslog(LOG_DEBUG, "ver=%d", arg->ver); + } else if (strncmp(tkn, "upcall_target=", 14) == 0) { + if (pos == NULL) + len = strlen(tkn); + else + len = pos - tkn; + + len -= 14; + if (len > MAX_UPCALL_STRING_LEN) { + syslog(LOG_ERR, "upcall_target= value too long for buffer"); + return 1; + } + if (strncmp(tkn + 14, "mount", 5) == 0) { + arg->upcall_target = UPTARGET_MOUNT; + syslog(LOG_DEBUG, "upcall_target=mount"); + } else if (strncmp(tkn + 14, "app", 3) == 0) { + arg->upcall_target = UPTARGET_APP; + syslog(LOG_DEBUG, "upcall_target=app"); + } else { + // Should never happen + syslog(LOG_ERR, "Invalid upcall_target value: %s, defaulting to app", + tkn + 14); + arg->upcall_target = UPTARGET_APP; + syslog(LOG_DEBUG, "upcall_target=app"); + } + arg->have |= DKD_HAVE_UPCALL_TARGET; } if (pos == NULL) break; @@ -1479,15 +1513,20 @@ int main(const int argc, char *const argv[]) * acceptably in containers, because we'll be looking at the correct * filesystem and have the correct network configuration. */ - rc = switch_to_process_ns(arg->pid); - if (rc == -1) { - syslog(LOG_ERR, "unable to switch to process namespace: %s", strerror(errno)); - rc = 1; - goto out; + if (arg->upcall_target == UPTARGET_APP || arg->upcall_target == UPTARGET_UNSPECIFIED) { + syslog(LOG_INFO, "upcall_target=app, switching namespaces to application thread"); + rc = switch_to_process_ns(arg->pid); + if (rc == -1) { + syslog(LOG_ERR, "unable to switch to process namespace: %s", strerror(errno)); + rc = 1; + goto out; + } + if (trim_capabilities(env_probe)) + goto out; + } else { + syslog(LOG_INFO, "upcall_target=mount, not switching namespaces to application thread"); } - if (trim_capabilities(env_probe)) - goto out; /* * The kernel doesn't pass down the gid, so we resort here to scraping @@ -1534,7 +1573,7 @@ int main(const int argc, char *const argv[]) * look at the environ file. */ env_cachename = - get_cachename_from_process_env(env_probe ? arg->pid : 0); + get_cachename_from_process_env((env_probe && (arg->upcall_target == UPTARGET_APP)) ? arg->pid : 0); rc = setuid(uid); if (rc == -1) { -- 2.43.0
From e92759ee6362ac8dedbb1aa301e55c8e7c016f98 Mon Sep 17 00:00:00 2001 From: Meetakshi Setiya <msetiya@xxxxxxxxxxxxx> Date: Tue, 22 Oct 2024 12:59:30 -0400 Subject: [PATCH 02/14] cifs-utils: support and document password2 mount option Currently, there are some issues when using the password2 mount option: 1. When password2 is provided in the credential file, mount.cifs overwrites password1 with the alternate password2. 2. There is no support to retrieve password2 from the environment. 3. password2 is not masked when mounting with verbose option. This commit fixes the aforementioned issues and adds documentation for the password2 mount option. Signed-off-by: Meetakshi Setiya <msetiya@xxxxxxxxxxxxx> Reviewed-by: Bharath SM <bharathsm@xxxxxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- mount.cifs.c | 96 ++++++++++++++++++++++++++++++++++++++++++-------- mount.cifs.rst | 19 ++++++++-- 2 files changed, 98 insertions(+), 17 deletions(-) diff --git a/mount.cifs.c b/mount.cifs.c index 3b7a6b3..71a2032 100644 --- a/mount.cifs.c +++ b/mount.cifs.c @@ -124,6 +124,7 @@ #define CRED_USER 1 #define CRED_PASS 2 #define CRED_DOM 4 +#define CRED_PASS2 5 /* * Values for parsing command line options. @@ -163,6 +164,7 @@ #define OPT_BKUPGID 31 #define OPT_NOFAIL 32 #define OPT_SNAPSHOT 33 +#define OPT_PASS2 34 #define MNT_TMP_FILE "/.mtab.cifs.XXXXXX" @@ -185,9 +187,11 @@ struct parsed_mount_info { char domain[MAX_DOMAIN_SIZE + 1]; char username[MAX_USERNAME_SIZE + 1]; char password[MOUNT_PASSWD_SIZE + 1]; + char password2[MOUNT_PASSWD_SIZE + 1]; char addrlist[MAX_ADDR_LIST_LEN]; unsigned int got_user:1; unsigned int got_password:1; + unsigned int got_password2:1; unsigned int fakemnt:1; unsigned int nomtab:1; unsigned int verboseflag:1; @@ -294,7 +298,7 @@ static int mount_usage(FILE * stream) fprintf(stream, "\n\tsign,seal,fsc,snapshot=<token|time>,nosharesock,persistenthandles,"); fprintf(stream, - "\n\tresilienthandles,rdma,vers=<smb_dialect>,cruid"); + "\n\tresilienthandles,rdma,vers=<smb_dialect>,cruid,password2=<alt password>"); fprintf(stream, "\n\nOptions not needed for servers supporting CIFS Unix extensions"); fprintf(stream, @@ -330,21 +334,29 @@ static int mount_usage(FILE * stream) * end up getting confused for option delimiters. Copy password into pw * field, turning any commas into double commas. */ -static int set_password(struct parsed_mount_info *parsed_info, const char *src) +static int +set_password(struct parsed_mount_info *parsed_info, const char *src, + const int is_pass2) { - char *dst = parsed_info->password; + char *dst = is_pass2 ? + parsed_info->password2 : parsed_info->password; + unsigned int pass_length = is_pass2 ? + sizeof(parsed_info->password2) : sizeof(parsed_info->password); unsigned int i = 0, j = 0; while (src[i]) { if (src[i] == ',') dst[j++] = ','; dst[j++] = src[i++]; - if (j > sizeof(parsed_info->password)) { + if (j > pass_length) { fprintf(stderr, "Converted password too long!\n"); return EX_USAGE; } } dst[j] = '\0'; + if (is_pass2) + parsed_info->got_password2 = 1; + else parsed_info->got_password = 1; return 0; } @@ -559,6 +571,9 @@ static int parse_cred_line(char *line, char **target) /* tell the caller which value target points to */ if (strncasecmp("user", line, 4) == 0) return CRED_USER; + if (strncasecmp("pass2", line, 5) == 0 || + strncasecmp("password2", line, 9) == 0) + return CRED_PASS2; if (strncasecmp("pass", line, 4) == 0) return CRED_PASS; if (strncasecmp("dom", line, 3) == 0) @@ -623,7 +638,12 @@ static int open_cred_file(char *file_name, parsed_info->got_user = 1; break; case CRED_PASS: - i = set_password(parsed_info, temp_val); + i = set_password(parsed_info, temp_val, 0); + if (i) + goto return_i; + break; + case CRED_PASS2: + i = set_password(parsed_info, temp_val, 1); if (i) goto return_i; break; @@ -652,10 +672,13 @@ return_i: static int get_password_from_file(int file_descript, char *filename, - struct parsed_mount_info *parsed_info, const char *program) + struct parsed_mount_info *parsed_info, const char *program, + const int is_pass2) { int rc = 0; - char buf[sizeof(parsed_info->password) + 1]; + unsigned int pass_length = is_pass2 ? + sizeof(parsed_info->password2) : sizeof(parsed_info->password); + char buf[pass_length + 1]; if (filename != NULL) { rc = toggle_dac_capability(0, 1); @@ -697,7 +720,7 @@ get_password_from_file(int file_descript, char *filename, goto get_pw_exit; } - rc = set_password(parsed_info, buf); + rc = set_password(parsed_info, buf, is_pass2); get_pw_exit: if (filename != NULL) @@ -727,6 +750,9 @@ static int parse_opt_token(const char *token) if (strcmp(token, "pass") == 0 || strcmp(token, "password") == 0) return OPT_PASS; + if (strcmp(token, "pass2") == 0 || + strcmp(token, "password2") == 0) + return OPT_PASS2; if (strcmp(token, "sec") == 0) return OPT_SEC; if (strcmp(token, "ip") == 0 || @@ -902,18 +928,36 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) parsed_info->got_password = 1; goto nocopy; } - rc = set_password(parsed_info, value); + rc = set_password(parsed_info, value, 0); + if (rc) + return rc; + goto nocopy; + + case OPT_PASS2: + if (parsed_info->got_password2) { + fprintf(stderr, + "password2 specified twice, ignoring second\n"); + goto nocopy; + } + if (!value || !*value) { + parsed_info->got_password2 = 1; + goto nocopy; + } + rc = set_password(parsed_info, value, 1); if (rc) return rc; goto nocopy; case OPT_SEC: if (value) { - if (!strncmp(value, "none", 4)) + if (!strncmp(value, "none", 4)) { parsed_info->got_password = 1; + parsed_info->got_password2 = 1; + } if (!strncmp(value, "krb5", 4)) { parsed_info->is_krb5 = 1; parsed_info->got_password = 1; + parsed_info->got_password2 = 1; } } break; @@ -1110,6 +1154,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) case OPT_GUEST: parsed_info->got_user = 1; parsed_info->got_password = 1; + parsed_info->got_password2 = 1; goto nocopy; case OPT_RO: *filesys_flags |= MS_RDONLY; @@ -1381,13 +1426,25 @@ static int get_pw_from_env(struct parsed_mount_info *parsed_info, const char *pr int rc = 0; if (getenv("PASSWD")) - rc = set_password(parsed_info, getenv("PASSWD")); + rc = set_password(parsed_info, getenv("PASSWD"), 0); else if (getenv("PASSWD_FD")) rc = get_password_from_file(atoi(getenv("PASSWD_FD")), NULL, - parsed_info, program); + parsed_info, program, 0); else if (getenv("PASSWD_FILE")) rc = get_password_from_file(0, getenv("PASSWD_FILE"), - parsed_info, program); + parsed_info, program, 0); + + if (rc < 0) + return rc; + + if (getenv("PASSWD2")) + rc = set_password(parsed_info, getenv("PASSWD2"), 1); + else if (getenv("PASSWD2_FD")) + rc = get_password_from_file(atoi(getenv("PASSWD2_FD")), NULL, + parsed_info, program, 1); + else if (getenv("PASSWD2_FILE")) + rc = get_password_from_file(0, getenv("PASSWD2_FILE"), + parsed_info, program, 1); return rc; } @@ -1413,6 +1470,8 @@ static struct option longopts[] = { {"domain", 1, NULL, 'd'}, {"password", 1, NULL, 'p'}, {"pass", 1, NULL, 'p'}, + {"password2", 1, NULL, 0}, + {"pass2", 1, NULL, 0}, {"credentials", 1, NULL, 'c'}, {"port", 1, NULL, 'P'}, {"sloppy", 0, NULL, 's'}, @@ -1923,6 +1982,7 @@ assemble_mountinfo(struct parsed_mount_info *parsed_info, parsed_info->got_user = 1; } + // no need to prompt for password2 if (!parsed_info->got_password) { char tmp_pass[MOUNT_PASSWD_SIZE + 1]; char *prompt = NULL; @@ -1931,7 +1991,7 @@ assemble_mountinfo(struct parsed_mount_info *parsed_info, prompt = NULL; if (get_password(prompt ? prompt : "Password: ", tmp_pass, MOUNT_PASSWD_SIZE + 1)) { - rc = set_password(parsed_info, tmp_pass); + rc = set_password(parsed_info, tmp_pass, 0); } else { fprintf(stderr, "Error reading password, exiting\n"); rc = EX_SYSERR; @@ -2252,6 +2312,13 @@ mount_retry: fprintf(stderr, ",pass=********"); } + if (parsed_info->got_password2) { + strlcat(options, ",password2=", options_size); + strlcat(options, parsed_info->password2, options_size); + if (parsed_info->verboseflag) + fprintf(stderr, ",password2=********"); + } + if (parsed_info->verboseflag) fprintf(stderr, "\n"); @@ -2343,6 +2410,7 @@ do_mtab: mount_exit: if (parsed_info) { memset(parsed_info->password, 0, sizeof(parsed_info->password)); + memset(parsed_info->password2, 0, sizeof(parsed_info->password2)); munmap(parsed_info, sizeof(*parsed_info)); } diff --git a/mount.cifs.rst b/mount.cifs.rst index 05d16d4..d461d0a 100644 --- a/mount.cifs.rst +++ b/mount.cifs.rst @@ -78,15 +78,28 @@ password=arg|pass=arg Note that a password which contains the delimiter character (i.e. a comma ',') will fail to be parsed correctly on the command line. However, the same password defined in the PASSWD environment - variable or via a credentials file (see below) or entered at the - password prompt will be read correctly. + variable or via a credentials file or entered at the password prompt + will be read correctly. + +password2=arg|pass2=arg + specifies an alternate password to help with password rotation. If + this option is not given, then the environment variable PASSWD2 is used. + If password2 is not specified directly or indirectly via an argument + to mount, mount.cifs will NOT prompt for password2. + + Note that a password2 which contains the delimiter character (i.e. a + comma ',') will fail to be parsed correctly on the command + line. However, the same password2 defined in the PASSWD2 environment + variable or via a credentials file (see below) will be read correctly. credentials=filename|cred=filename specifies a file that contains a username and/or password and - optionally the name of the workgroup. The format of the file is:: + optionally an alternate password and/or the name of the workgroup. + The format of the file is:: username=value password=value + password2=value domain=value This is preferred over having passwords in plaintext in a shared file, -- 2.43.0
From 62b1a926706cdf133f520242ac066a5a49b18051 Mon Sep 17 00:00:00 2001 From: Bharath SM <bharathsm@xxxxxxxxxxxxx> Date: Tue, 26 Nov 2024 22:57:44 +0530 Subject: [PATCH 04/14] cifs-utils: Skip TGT check if valid service ticket is already available When handling upcalls from the kernel for SMB session setup requests using Kerberos authentication, if the credential cache already contains a valid service ticket, it can be used directly without checking for the TGT again. Signed-off-by: Bharath SM <bharathsm@xxxxxxxxxxxxx> Reviewed-by: Shyam Prasad N <sprasad@xxxxxxxxxxxxx> Acked-by: Alexander Bokovoy <ab@xxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- cifs.upcall.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/cifs.upcall.c b/cifs.upcall.c index ff6f2bd..4ad0c8e 100644 --- a/cifs.upcall.c +++ b/cifs.upcall.c @@ -552,11 +552,6 @@ get_existing_cc(const char *env_cachename) syslog(LOG_DEBUG, "%s: default ccache is %s\n", __func__, cachename); krb5_free_string(context, cachename); } - - if (!get_tgt_time(cc)) { - krb5_cc_close(context, cc); - cc = NULL; - } return cc; } @@ -638,6 +633,49 @@ icfk_cleanup: #define CIFS_SERVICE_NAME "cifs" +static krb5_error_code check_service_ticket_exists(krb5_ccache ccache, + const char *hostname) { + + krb5_error_code rc; + krb5_creds mcreds, out_creds; + + memset(&mcreds, 0, sizeof(mcreds)); + + rc = krb5_cc_get_principal(context, ccache, &mcreds.client); + if (rc) { + syslog(LOG_DEBUG, "%s: unable to get client principal from cache: %s", + __func__, krb5_get_error_message(context, rc)); + return rc; + } + + rc = krb5_sname_to_principal(context, hostname, CIFS_SERVICE_NAME, + KRB5_NT_UNKNOWN, &mcreds.server); + if (rc) { + syslog(LOG_DEBUG, "%s: unable to convert service name (%s) to principal: %s", + __func__, hostname, krb5_get_error_message(context, rc)); + krb5_free_principal(context, mcreds.client); + return rc; + } + + rc = krb5_timeofday(context, &mcreds.times.endtime); + if (rc) { + syslog(LOG_DEBUG, "%s: unable to get time: %s", + __func__, krb5_get_error_message(context, rc)); + goto out_free_principal; + } + + rc = krb5_cc_retrieve_cred(context, ccache, KRB5_TC_MATCH_TIMES, &mcreds, &out_creds); + + if (!rc) + krb5_free_cred_contents(context, &out_creds); + +out_free_principal: + krb5_free_principal(context, mcreds.server); + krb5_free_principal(context, mcreds.client); + + return rc; +} + static int cifs_krb5_get_req(const char *host, krb5_ccache ccache, DATA_BLOB * mechtoken, DATA_BLOB * sess_key) @@ -1516,12 +1554,26 @@ int main(const int argc, char *const argv[]) goto out; } + host = arg->hostname; ccache = get_existing_cc(env_cachename); + if (ccache != NULL) { + rc = check_service_ticket_exists(ccache, host); + if(rc == 0) { + syslog(LOG_DEBUG, "%s: valid service ticket exists in credential cache", + __func__); + } else { + if (!get_tgt_time(ccache)) { + syslog(LOG_DEBUG, "%s: valid TGT is not present in credential cache", + __func__); + krb5_cc_close(context, ccache); + ccache = NULL; + } + } + } /* Couldn't find credcache? Try to use keytab */ if (ccache == NULL && arg->username[0] != '\0') ccache = init_cc_from_keytab(keytab_name, arg->username); - host = arg->hostname; // do mech specific authorization switch (arg->sec) { -- 2.43.0
From 5d5cb04759eb6d8b6216d09e7d33d711d2a46c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= <pfilipensky@xxxxxxxxx> Date: Mon, 7 Oct 2024 21:48:31 +0200 Subject: [PATCH 01/14] smbinfo: add bash completion support for filestreaminfo, keys, gettconinfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Pavel Filipenský <pfilipensky@xxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- bash-completion/smbinfo | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bash-completion/smbinfo b/bash-completion/smbinfo index d56b581..ec0d8a4 100644 --- a/bash-completion/smbinfo +++ b/bash-completion/smbinfo @@ -15,19 +15,22 @@ smb_info() filemodeinfo filepositioninfo filestandardinfo + filestreaminfo fsctl-getobjid getcompression setcompression list-snapshots quota - secdesc" + secdesc + keys + gettconinfo" case $prev in '-v'|'-h') return 0 ;; 'fileaccessinfo'|'filealigninfo'|'fileallinfo'|'filebasicinfo'|'fileeainfo'|'filefsfullsizeinfo'|\ - 'fileinternalinfo'|'filemodeinfo'|'filepositioninfo'|'filestandardinfo'|'fsctl-getobjid'|\ - 'getcompression'|'setcompression'|'list-snapshots'|'quota'|'secdesc') + 'fileinternalinfo'|'filemodeinfo'|'filepositioninfo'|'filestandardinfo'|'filestreaminfo'|'fsctl-getobjid'|\ + 'getcompression'|'setcompression'|'list-snapshots'|'quota'|'secdesc'|'keys'|'gettconinfo') local IFS=$'\n' compopt -o filenames COMPREPLY=( $(compgen -f -o dirnames -- ${cur:-""}) ) -- 2.43.0
From ecc241229028a5382218aa1402df9efde81353f2 Mon Sep 17 00:00:00 2001 From: Meetakshi Setiya <msetiya@xxxxxxxxxxxxx> Date: Mon, 11 Nov 2024 00:10:53 -0500 Subject: [PATCH 03/14] use enums to check password or password2 in set_password, get_password_from_file and minor documentation additions Signed-off-by: Meetakshi Setiya <msetiya@xxxxxxxxxxxxx> Reviewed-by: Bharath SM <bharathsm@xxxxxxxxxxxxx> Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> --- mount.cifs.c | 33 ++++++++++++++++++--------------- mount.cifs.rst | 10 +++++----- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/mount.cifs.c b/mount.cifs.c index 71a2032..041e64f 100644 --- a/mount.cifs.c +++ b/mount.cifs.c @@ -336,8 +336,10 @@ static int mount_usage(FILE * stream) */ static int set_password(struct parsed_mount_info *parsed_info, const char *src, - const int is_pass2) + const int which_pass) { + int is_pass2 = which_pass == OPT_PASS2 || which_pass == CRED_PASS2; + char *dst = is_pass2 ? parsed_info->password2 : parsed_info->password; unsigned int pass_length = is_pass2 ? @@ -638,12 +640,12 @@ static int open_cred_file(char *file_name, parsed_info->got_user = 1; break; case CRED_PASS: - i = set_password(parsed_info, temp_val, 0); + i = set_password(parsed_info, temp_val, CRED_PASS); if (i) goto return_i; break; case CRED_PASS2: - i = set_password(parsed_info, temp_val, 1); + i = set_password(parsed_info, temp_val, CRED_PASS2); if (i) goto return_i; break; @@ -673,9 +675,10 @@ return_i: static int get_password_from_file(int file_descript, char *filename, struct parsed_mount_info *parsed_info, const char *program, - const int is_pass2) + const int which_pass) { int rc = 0; + int is_pass2 = which_pass == OPT_PASS2; unsigned int pass_length = is_pass2 ? sizeof(parsed_info->password2) : sizeof(parsed_info->password); char buf[pass_length + 1]; @@ -720,7 +723,7 @@ get_password_from_file(int file_descript, char *filename, goto get_pw_exit; } - rc = set_password(parsed_info, buf, is_pass2); + rc = set_password(parsed_info, buf, which_pass); get_pw_exit: if (filename != NULL) @@ -928,7 +931,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) parsed_info->got_password = 1; goto nocopy; } - rc = set_password(parsed_info, value, 0); + rc = set_password(parsed_info, value, OPT_PASS); if (rc) return rc; goto nocopy; @@ -943,7 +946,7 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info) parsed_info->got_password2 = 1; goto nocopy; } - rc = set_password(parsed_info, value, 1); + rc = set_password(parsed_info, value, OPT_PASS2); if (rc) return rc; goto nocopy; @@ -1426,25 +1429,25 @@ static int get_pw_from_env(struct parsed_mount_info *parsed_info, const char *pr int rc = 0; if (getenv("PASSWD")) - rc = set_password(parsed_info, getenv("PASSWD"), 0); + rc = set_password(parsed_info, getenv("PASSWD"), OPT_PASS); else if (getenv("PASSWD_FD")) rc = get_password_from_file(atoi(getenv("PASSWD_FD")), NULL, - parsed_info, program, 0); + parsed_info, program, OPT_PASS); else if (getenv("PASSWD_FILE")) rc = get_password_from_file(0, getenv("PASSWD_FILE"), - parsed_info, program, 0); + parsed_info, program, OPT_PASS); if (rc < 0) return rc; if (getenv("PASSWD2")) - rc = set_password(parsed_info, getenv("PASSWD2"), 1); + rc = set_password(parsed_info, getenv("PASSWD2"), OPT_PASS2); else if (getenv("PASSWD2_FD")) rc = get_password_from_file(atoi(getenv("PASSWD2_FD")), NULL, - parsed_info, program, 1); + parsed_info, program, OPT_PASS2); else if (getenv("PASSWD2_FILE")) rc = get_password_from_file(0, getenv("PASSWD2_FILE"), - parsed_info, program, 1); + parsed_info, program, OPT_PASS2); return rc; } @@ -1983,7 +1986,7 @@ assemble_mountinfo(struct parsed_mount_info *parsed_info, } // no need to prompt for password2 - if (!parsed_info->got_password) { + if (!parsed_info->got_password && !(parsed_info->flags & MS_REMOUNT)) { char tmp_pass[MOUNT_PASSWD_SIZE + 1]; char *prompt = NULL; @@ -1991,7 +1994,7 @@ assemble_mountinfo(struct parsed_mount_info *parsed_info, prompt = NULL; if (get_password(prompt ? prompt : "Password: ", tmp_pass, MOUNT_PASSWD_SIZE + 1)) { - rc = set_password(parsed_info, tmp_pass, 0); + rc = set_password(parsed_info, tmp_pass, OPT_PASS); } else { fprintf(stderr, "Error reading password, exiting\n"); rc = EX_SYSERR; diff --git a/mount.cifs.rst b/mount.cifs.rst index d461d0a..5281896 100644 --- a/mount.cifs.rst +++ b/mount.cifs.rst @@ -943,12 +943,12 @@ The variable ``USER`` may contain the username of the person to be used to authenticate to the server. The variable can be used to set both username and password by using the format ``username%password``. -The variable ``PASSWD`` may contain the password of the person using -the client. +The variables ``PASSWD`` and ``PASSWD2`` may contain the password and the +alternate password of the person using the client, respectively. -The variable ``PASSWD_FILE`` may contain the pathname of a file to read -the password from. A single line of input is read and used as the -password. +The variables ``PASSWD_FILE`` and ``PASSWD2_FILE`` may contain the +pathname of the file to read password or password2 from, respectively. +A single line of input is read and used as the password in each case. ***** NOTES -- 2.43.0