2011-11-17 20:26:06

by Steve Dickson

[permalink] [raw]
Subject: [PATCH 0/2] nfsidmap: Allow admins to clean up id mappings that have failed

In working with the new idmapper, it became very apparent that
keys created from bad id mapping were very persistent and were
not easy disposed of. Unlike with rpc.idmapd, to git rid
of bad id mapping one just needed to restart the daemon.

So I've added some functionality to the nfsidmap command
that will allow admins to:

- remove all the keys on the keyring.
- remove a particular key from the keying.

The intention is to allow admins a way to clean up the id
name space when name resolution mechanisms, like NIS or LDAP,
fail and leave a large number (or small number) of id mapping
pointing to nobody.

Note, for the second patch to work, there need to be a small
kernel patch that will change the per-key permissions to
allow root to revoke them.

Steve Dickson (2):
nfsidmap: Allow all keys to clear on the keyring
nfsidmap: Allow a particular key to be revoked.

utils/nfsidmap/nfsidmap.c | 138 +++++++++++++++++++++++++++++++++++++++++--
utils/nfsidmap/nfsidmap.man | 27 ++++++++-
2 files changed, 159 insertions(+), 6 deletions(-)

--
1.7.7



2011-11-17 20:26:06

by Steve Dickson

[permalink] [raw]
Subject: [PATCH 2/2] nfsidmap: Allow a particular key to be revoked.

Introducing three new command line arguments
that allow particular keys to be revoke

-u will remove a uid key
-g will revoke a gid key
-r will revoke both the uid and gid keys

The user name has also needs to be supply
with these new flags.

Signed-off-by: Steve Dickson <[email protected]>
---
utils/nfsidmap/nfsidmap.c | 84 ++++++++++++++++++++++++++++++++++++++++--
utils/nfsidmap/nfsidmap.man | 23 ++++++++++--
2 files changed, 99 insertions(+), 8 deletions(-)

diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
index 2625dc1..7b64cd4 100644
--- a/utils/nfsidmap/nfsidmap.c
+++ b/utils/nfsidmap/nfsidmap.c
@@ -13,7 +13,7 @@
#include "xlog.h"

int verbose = 0;
-char *usage="Usage: %s [-v] [-c [keyring]] [-t timeout] key desc";
+char *usage="Usage: %s [-v] [[-u|-g|-r key]] | [-c [keyring]] | [[-t timeout] key desc]";

#define MAX_ID_LEN 11
#define IDMAP_NAMESZ 128
@@ -22,6 +22,9 @@ char *usage="Usage: %s [-v] [-c [keyring]] [-t timeout] key desc";
#define DEFAULT_KEYRING "id_resolver"
#define PROCKEYS "/proc/keys"

+#define UIDKEYS 0x1
+#define GIDKEYS 0x2
+
/*
* Find either a user or group id based on the name@domain string
*/
@@ -130,6 +133,63 @@ static int keyring_clear(char *keyring)
xlog_err("'%s' keyring was not found.", keyring);
return 1;
}
+/*
+ * Revoke a key
+ */
+static int key_revoke(char *keystr, int keymask)
+{
+ FILE *fp;
+ char buf[BUFSIZ], *ptr;
+ key_serial_t key;
+ int mask;
+
+ xlog_syslog(0);
+
+ if ((fp = fopen(PROCKEYS, "r")) == NULL) {
+ xlog_err("fopen(%s) failed: %m", PROCKEYS);
+ return 1;
+ }
+
+ while(fgets(buf, BUFSIZ, fp) != NULL) {
+ if (strstr(buf, "keyring") != NULL)
+ continue;
+
+ mask = 0;
+ if ((ptr = strstr(buf, "uid:")) != NULL)
+ mask = UIDKEYS;
+ else if ((ptr = strstr(buf, "gid:")) != NULL)
+ mask = GIDKEYS;
+ else
+ continue;
+
+ if ((keymask & mask) == 0)
+ continue;
+
+ if (strncmp(ptr+4, keystr, strlen(keystr)) != NULL)
+ continue;
+
+ if (verbose) {
+ *(strchr(buf, '\n')) = '\0';
+ xlog_warn("revoking '%s'", buf);
+ }
+ /*
+ * The key is the first arugment in the string
+ */
+ *(strchr(buf, ' ')) = '\0';
+ sscanf(buf, "%x", &key);
+
+ if (keyctl_revoke(key) < 0) {
+ xlog_err("keyctl_revoke(0x%x) failed: %m", key);
+ return 1;
+ }
+
+ keymask &= ~mask;
+ if (keymask == 0)
+ return 0;
+ }
+ xlog_err("'%s' key was not found.", keystr);
+ return 1;
+}

int main(int argc, char **argv)
{
@@ -139,8 +199,8 @@ int main(int argc, char **argv)
int rc = 1, opt;
int timeout = 600;
key_serial_t key;
- char *progname, *keyring = NULL;
- int clearring;
+ char *progname, *keyring = NULL, *keystr = NULL;
+ int clearring, keymask = 0;

/* Set the basename */
if ((progname = strrchr(argv[0], '/')) != NULL)
@@ -150,8 +210,20 @@ int main(int argc, char **argv)

xlog_open(progname);

- while ((opt = getopt(argc, argv, "ct:v")) != -1) {
+ while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
switch (opt) {
+ case 'u':
+ keymask = UIDKEYS;
+ keystr = strdup(optarg);
+ break;
+ case 'g':
+ keymask = GIDKEYS;
+ keystr = strdup(optarg);
+ break;
+ case 'r':
+ keymask = GIDKEYS|UIDKEYS;
+ keystr = strdup(optarg);
+ break;
case 'c':
clearring++;
break;
@@ -167,6 +239,10 @@ int main(int argc, char **argv)
}
}

+ if (keystr) {
+ rc = key_revoke(keystr, keymask);
+ return rc;
+ }
if (clearring) {
keyring = ((argc - optind) ? argv[optind] : NULL);
rc = keyring_clear(keyring);
diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
index db65a1f..216afd1 100644
--- a/utils/nfsidmap/nfsidmap.man
+++ b/utils/nfsidmap/nfsidmap.man
@@ -6,7 +6,11 @@
.SH NAME
nfsidmap \- The NFS idmapper upcall program
.SH SYNOPSIS
-.B "nfsidmap [-v] [-c [keyring]] [-t timeout] key desc"
+.B "nfsidmap [-v] [-t timeout] key desc"
+.br
+.B "nfsidmap [-v] [-c [keyring]]"
+.br
+.B "nfsidmap [-v] [-u|-g|-r user]"
.SH DESCRIPTION
The file
.I /usr/sbin/nfsidmap
@@ -18,9 +22,11 @@ is called by /sbin/request-key, and will perform the translation and
initialize a key with the resulting information.
.PP
.I nfsidmap
-can also used to clear the keyring of all the keys.
-This is useful when all the mappings have failed to due to an DNS outage
-or some other error resulting in all the cached uid/gid to be invalid.
+can also used to clear the keyring of all the keys or
+revoke one particular key.
+This is useful when the id mappings have failed to due
+to a lookup error resulting in all the cached uids/gids to be set
+to the user id nobody.
.SH OPTIONS
.TP
.B -c [keyring]
@@ -28,10 +34,19 @@ Clear the keyring of all the keys. If a
keyring is not supplied the default
keyring 'id_resolver' will be used.
.TP
+.B -g user
+Revoke the gid key of the given user.
+.TP
+.B -r user
+Revoke both the uid and gid key of the given user.
+.TP
.B -t timeout
Set the expiration timer, in seconds, on the key.
The default is 600 seconds (10 mins).
.TP
+.B -u user
+Revoke the uid key of the given user.
+.TP
.B -v
Increases the verbosity of the output to syslog
(can be specified multiple times).
--
1.7.7


2011-11-17 20:26:06

by Steve Dickson

[permalink] [raw]
Subject: [PATCH 1/2] nfsidmap: Allow all keys to clear on the keyring

Introduce the '-c [keyring]' command line argument
which will clear the giving keyring of the keys.
If a keyring not supplied the default 'id_resolver'
keyring will be used.

Signed-off-by: Steve Dickson <[email protected]>
---
utils/nfsidmap/nfsidmap.c | 62 +++++++++++++++++++++++++++++++++++++++---
utils/nfsidmap/nfsidmap.man | 14 ++++++++-
2 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
index 6a09f38..2625dc1 100644
--- a/utils/nfsidmap/nfsidmap.c
+++ b/utils/nfsidmap/nfsidmap.c
@@ -13,12 +13,14 @@
#include "xlog.h"

int verbose = 0;
-char *usage="Usage: %s [-v] [-t timeout] key desc";
+char *usage="Usage: %s [-v] [-c [keyring]] [-t timeout] key desc";

#define MAX_ID_LEN 11
#define IDMAP_NAMESZ 128
#define USER 1
#define GROUP 0
+#define DEFAULT_KEYRING "id_resolver"
+#define PROCKEYS "/proc/keys"

/*
* Find either a user or group id based on the name@domain string
@@ -87,6 +89,47 @@ int name_lookup(char *id, key_serial_t key, int type)
out:
return rc;
}
+/*
+ * Clear all the keys on the given keyring
+ */
+static int keyring_clear(char *keyring)
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+ key_serial_t key;
+
+ xlog_syslog(0);
+ if (keyring == NULL)
+ keyring = DEFAULT_KEYRING;
+
+ if ((fp = fopen(PROCKEYS, "r")) == NULL) {
+ xlog_err("fopen(%s) failed: %m", PROCKEYS);
+ return 1;
+ }
+
+ while(fgets(buf, BUFSIZ, fp) != NULL) {
+ if (strstr(buf, "keyring") == NULL)
+ continue;
+ if (strstr(buf, keyring) == NULL)
+ continue;
+ if (verbose) {
+ *(strchr(buf, '\n')) = '\0';
+ xlog_warn("clearing '%s'", buf);
+ }
+ /*
+ * The key is the first arugment in the string
+ */
+ *(strchr(buf, ' ')) = '\0';
+ sscanf(buf, "%x", &key);
+ if (keyctl_clear(key) < 0) {
+ xlog_err("keyctl_clear(0x%x) failed: %m", key);
+ return 1;
+ }
+ return 0;
+ }
+ xlog_err("'%s' keyring was not found.", keyring);
+ return 1;
+}

int main(int argc, char **argv)
{
@@ -96,7 +139,8 @@ int main(int argc, char **argv)
int rc = 1, opt;
int timeout = 600;
key_serial_t key;
- char *progname;
+ char *progname, *keyring = NULL;
+ int clearring;

/* Set the basename */
if ((progname = strrchr(argv[0], '/')) != NULL)
@@ -105,11 +149,12 @@ int main(int argc, char **argv)
progname = argv[0];

xlog_open(progname);
- xlog_syslog(1);
- xlog_stderr(0);

- while ((opt = getopt(argc, argv, "t:v")) != -1) {
+ while ((opt = getopt(argc, argv, "ct:v")) != -1) {
switch (opt) {
+ case 'c':
+ clearring++;
+ break;
case 'v':
verbose++;
break;
@@ -122,6 +167,13 @@ int main(int argc, char **argv)
}
}

+ if (clearring) {
+ keyring = ((argc - optind) ? argv[optind] : NULL);
+ rc = keyring_clear(keyring);
+ return rc;
+ }
+
+ xlog_stderr(0);
if ((argc - optind) != 2) {
xlog_err("Bad arg count. Check /etc/request-key.conf");
xlog_warn(usage, progname);
diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
index c67aab6..db65a1f 100644
--- a/utils/nfsidmap/nfsidmap.man
+++ b/utils/nfsidmap/nfsidmap.man
@@ -6,7 +6,7 @@
.SH NAME
nfsidmap \- The NFS idmapper upcall program
.SH SYNOPSIS
-.B "nfsidmap [-v] [-t timeout] key desc"
+.B "nfsidmap [-v] [-c [keyring]] [-t timeout] key desc"
.SH DESCRIPTION
The file
.I /usr/sbin/nfsidmap
@@ -14,10 +14,20 @@ is used by the NFS idmapper to translate user and group ids into names, and to
translate user and group names into ids. Idmapper uses request-key to perform
the upcall and cache the result.
.I /usr/sbin/nfsidmap
-should only be called by request-key, and will perform the translation and
+is called by /sbin/request-key, and will perform the translation and
initialize a key with the resulting information.
+.PP
+.I nfsidmap
+can also used to clear the keyring of all the keys.
+This is useful when all the mappings have failed to due to an DNS outage
+or some other error resulting in all the cached uid/gid to be invalid.
.SH OPTIONS
.TP
+.B -c [keyring]
+Clear the keyring of all the keys. If a
+keyring is not supplied the default
+keyring 'id_resolver' will be used.
+.TP
.B -t timeout
Set the expiration timer, in seconds, on the key.
The default is 600 seconds (10 mins).
--
1.7.7


2011-11-17 20:36:25

by Mkrtchyan, Tigran

[permalink] [raw]
Subject: Re: [PATCH 1/2] nfsidmap: Allow all keys to clear on the keyring

On Thu, Nov 17, 2011 at 9:26 PM, Steve Dickson <[email protected]> wrote:
> Introduce the '-c [keyring]' command line argument
> which will clear the giving keyring of the keys.
> If a keyring not supplied the default 'id_resolver'
> keyring will be used.
>
> Signed-off-by: Steve Dickson <[email protected]>
> ---
>  utils/nfsidmap/nfsidmap.c   |   62 +++++++++++++++++++++++++++++++++++++++---
>  utils/nfsidmap/nfsidmap.man |   14 ++++++++-
>  2 files changed, 69 insertions(+), 7 deletions(-)
>
> diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
> index 6a09f38..2625dc1 100644
> --- a/utils/nfsidmap/nfsidmap.c
> +++ b/utils/nfsidmap/nfsidmap.c
> @@ -13,12 +13,14 @@
>  #include "xlog.h"
>
>  int verbose = 0;
> -char *usage="Usage: %s [-v] [-t timeout] key desc";
> +char *usage="Usage: %s [-v] [-c [keyring]] [-t timeout] key desc";
>
>  #define MAX_ID_LEN   11
>  #define IDMAP_NAMESZ 128
>  #define USER  1
>  #define GROUP 0
> +#define DEFAULT_KEYRING "id_resolver"
> +#define PROCKEYS "/proc/keys"
>
>  /*
>  * Find either a user or group id based on the name@domain string
> @@ -87,6 +89,47 @@ int name_lookup(char *id, key_serial_t key, int type)
>  out:
>        return rc;
>  }
> +/*
> + * Clear all the keys on the given keyring
> + */
> +static int keyring_clear(char *keyring)
> +{
> +       FILE *fp;
> +       char buf[BUFSIZ];
> +       key_serial_t key;
> +
> +       xlog_syslog(0);
> +       if (keyring == NULL)
> +               keyring = DEFAULT_KEYRING;
> +
> +       if ((fp = fopen(PROCKEYS, "r")) == NULL) {

The same comment here: fp never closed.

Tigran.
> +               xlog_err("fopen(%s) failed: %m", PROCKEYS);
> +               return 1;
> +       }
> +
> +       while(fgets(buf, BUFSIZ, fp) != NULL) {
> +               if (strstr(buf, "keyring") == NULL)
> +                       continue;
> +               if (strstr(buf, keyring) == NULL)
> +                       continue;
> +               if (verbose) {
> +                       *(strchr(buf, '\n')) = '\0';
> +                       xlog_warn("clearing '%s'", buf);
> +               }
> +               /*
> +                * The key is the first arugment in the string
> +                */
> +               *(strchr(buf, ' ')) = '\0';
> +               sscanf(buf, "%x", &key);
> +               if (keyctl_clear(key) < 0) {
> +                       xlog_err("keyctl_clear(0x%x) failed: %m", key);
> +                       return 1;
> +               }
> +               return 0;
> +       }
> +       xlog_err("'%s' keyring was not found.", keyring);
> +       return 1;
> +}
>
>  int main(int argc, char **argv)
>  {
> @@ -96,7 +139,8 @@ int main(int argc, char **argv)
>        int rc = 1, opt;
>        int timeout = 600;
>        key_serial_t key;
> -       char *progname;
> +       char *progname, *keyring = NULL;
> +       int clearring;
>
>        /* Set the basename */
>        if ((progname = strrchr(argv[0], '/')) != NULL)
> @@ -105,11 +149,12 @@ int main(int argc, char **argv)
>                progname = argv[0];
>
>        xlog_open(progname);
> -       xlog_syslog(1);
> -       xlog_stderr(0);
>
> -       while ((opt = getopt(argc, argv, "t:v")) != -1) {
> +       while ((opt = getopt(argc, argv, "ct:v")) != -1) {
>                switch (opt) {
> +               case 'c':
> +                       clearring++;
> +                       break;
>                case 'v':
>                        verbose++;
>                        break;
> @@ -122,6 +167,13 @@ int main(int argc, char **argv)
>                }
>        }
>
> +       if (clearring) {
> +               keyring = ((argc - optind) ? argv[optind] : NULL);
> +               rc = keyring_clear(keyring);
> +               return rc;
> +       }
> +
> +       xlog_stderr(0);
>        if ((argc - optind) != 2) {
>                xlog_err("Bad arg count. Check /etc/request-key.conf");
>                xlog_warn(usage, progname);
> diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
> index c67aab6..db65a1f 100644
> --- a/utils/nfsidmap/nfsidmap.man
> +++ b/utils/nfsidmap/nfsidmap.man
> @@ -6,7 +6,7 @@
>  .SH NAME
>  nfsidmap \- The NFS idmapper upcall program
>  .SH SYNOPSIS
> -.B "nfsidmap [-v] [-t timeout] key desc"
> +.B "nfsidmap [-v] [-c [keyring]] [-t timeout] key desc"
>  .SH DESCRIPTION
>  The file
>  .I /usr/sbin/nfsidmap
> @@ -14,10 +14,20 @@ is used by the NFS idmapper to translate user and group ids into names, and to
>  translate user and group names into ids. Idmapper uses request-key to perform
>  the upcall and cache the result.
>  .I /usr/sbin/nfsidmap
> -should only be called by request-key, and will perform the translation and
> +is called by /sbin/request-key, and will perform the translation and
>  initialize a key with the resulting information.
> +.PP
> +.I nfsidmap
> +can also used to clear the keyring of all the keys.
> +This is useful when all the mappings have failed to due to an DNS outage
> +or some other error resulting in all the cached uid/gid to be invalid.
>  .SH OPTIONS
>  .TP
> +.B -c [keyring]
> +Clear the keyring of all the keys. If a
> +keyring is not supplied the default
> +keyring 'id_resolver' will be used.
> +.TP
>  .B -t timeout
>  Set the expiration timer, in seconds, on the key.
>  The default is 600 seconds (10 mins).
> --
> 1.7.7
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

2011-11-17 21:36:55

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH 1/2] nfsidmap: Allow all keys to clear on the keyring



On 11/17/2011 03:36 PM, Tigran Mkrtchyan wrote:
> On Thu, Nov 17, 2011 at 9:26 PM, Steve Dickson <[email protected]> wrote:
>> Introduce the '-c [keyring]' command line argument
>> which will clear the giving keyring of the keys.
>> If a keyring not supplied the default 'id_resolver'
>> keyring will be used.
>>
>> Signed-off-by: Steve Dickson <[email protected]>
>> ---
>> utils/nfsidmap/nfsidmap.c | 62 +++++++++++++++++++++++++++++++++++++++---
>> utils/nfsidmap/nfsidmap.man | 14 ++++++++-
>> 2 files changed, 69 insertions(+), 7 deletions(-)
>>
>> diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
>> index 6a09f38..2625dc1 100644
>> --- a/utils/nfsidmap/nfsidmap.c
>> +++ b/utils/nfsidmap/nfsidmap.c
>> @@ -13,12 +13,14 @@
>> #include "xlog.h"
>>
>> int verbose = 0;
>> -char *usage="Usage: %s [-v] [-t timeout] key desc";
>> +char *usage="Usage: %s [-v] [-c [keyring]] [-t timeout] key desc";
>>
>> #define MAX_ID_LEN 11
>> #define IDMAP_NAMESZ 128
>> #define USER 1
>> #define GROUP 0
>> +#define DEFAULT_KEYRING "id_resolver"
>> +#define PROCKEYS "/proc/keys"
>>
>> /*
>> * Find either a user or group id based on the name@domain string
>> @@ -87,6 +89,47 @@ int name_lookup(char *id, key_serial_t key, int type)
>> out:
>> return rc;
>> }
>> +/*
>> + * Clear all the keys on the given keyring
>> + */
>> +static int keyring_clear(char *keyring)
>> +{
>> + FILE *fp;
>> + char buf[BUFSIZ];
>> + key_serial_t key;
>> +
>> + xlog_syslog(0);
>> + if (keyring == NULL)
>> + keyring = DEFAULT_KEYRING;
>> +
>> + if ((fp = fopen(PROCKEYS, "r")) == NULL) {
>
> The same comment here: fp never closed.
Got it..

steved.
>
> Tigran.
>> + xlog_err("fopen(%s) failed: %m", PROCKEYS);
>> + return 1;
>> + }
>> +
>> + while(fgets(buf, BUFSIZ, fp) != NULL) {
>> + if (strstr(buf, "keyring") == NULL)
>> + continue;
>> + if (strstr(buf, keyring) == NULL)
>> + continue;
>> + if (verbose) {
>> + *(strchr(buf, '\n')) = '\0';
>> + xlog_warn("clearing '%s'", buf);
>> + }
>> + /*
>> + * The key is the first arugment in the string
>> + */
>> + *(strchr(buf, ' ')) = '\0';
>> + sscanf(buf, "%x", &key);
>> + if (keyctl_clear(key) < 0) {
>> + xlog_err("keyctl_clear(0x%x) failed: %m", key);
>> + return 1;
>> + }
>> + return 0;
>> + }
>> + xlog_err("'%s' keyring was not found.", keyring);
>> + return 1;
>> +}
>>
>> int main(int argc, char **argv)
>> {
>> @@ -96,7 +139,8 @@ int main(int argc, char **argv)
>> int rc = 1, opt;
>> int timeout = 600;
>> key_serial_t key;
>> - char *progname;
>> + char *progname, *keyring = NULL;
>> + int clearring;
>>
>> /* Set the basename */
>> if ((progname = strrchr(argv[0], '/')) != NULL)
>> @@ -105,11 +149,12 @@ int main(int argc, char **argv)
>> progname = argv[0];
>>
>> xlog_open(progname);
>> - xlog_syslog(1);
>> - xlog_stderr(0);
>>
>> - while ((opt = getopt(argc, argv, "t:v")) != -1) {
>> + while ((opt = getopt(argc, argv, "ct:v")) != -1) {
>> switch (opt) {
>> + case 'c':
>> + clearring++;
>> + break;
>> case 'v':
>> verbose++;
>> break;
>> @@ -122,6 +167,13 @@ int main(int argc, char **argv)
>> }
>> }
>>
>> + if (clearring) {
>> + keyring = ((argc - optind) ? argv[optind] : NULL);
>> + rc = keyring_clear(keyring);
>> + return rc;
>> + }
>> +
>> + xlog_stderr(0);
>> if ((argc - optind) != 2) {
>> xlog_err("Bad arg count. Check /etc/request-key.conf");
>> xlog_warn(usage, progname);
>> diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
>> index c67aab6..db65a1f 100644
>> --- a/utils/nfsidmap/nfsidmap.man
>> +++ b/utils/nfsidmap/nfsidmap.man
>> @@ -6,7 +6,7 @@
>> .SH NAME
>> nfsidmap \- The NFS idmapper upcall program
>> .SH SYNOPSIS
>> -.B "nfsidmap [-v] [-t timeout] key desc"
>> +.B "nfsidmap [-v] [-c [keyring]] [-t timeout] key desc"
>> .SH DESCRIPTION
>> The file
>> .I /usr/sbin/nfsidmap
>> @@ -14,10 +14,20 @@ is used by the NFS idmapper to translate user and group ids into names, and to
>> translate user and group names into ids. Idmapper uses request-key to perform
>> the upcall and cache the result.
>> .I /usr/sbin/nfsidmap
>> -should only be called by request-key, and will perform the translation and
>> +is called by /sbin/request-key, and will perform the translation and
>> initialize a key with the resulting information.
>> +.PP
>> +.I nfsidmap
>> +can also used to clear the keyring of all the keys.
>> +This is useful when all the mappings have failed to due to an DNS outage
>> +or some other error resulting in all the cached uid/gid to be invalid.
>> .SH OPTIONS
>> .TP
>> +.B -c [keyring]
>> +Clear the keyring of all the keys. If a
>> +keyring is not supplied the default
>> +keyring 'id_resolver' will be used.
>> +.TP
>> .B -t timeout
>> Set the expiration timer, in seconds, on the key.
>> The default is 600 seconds (10 mins).
>> --
>> 1.7.7
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>

2011-11-17 20:34:55

by Mkrtchyan, Tigran

[permalink] [raw]
Subject: Re: [PATCH 2/2] nfsidmap: Allow a particular key to be revoked.

On Thu, Nov 17, 2011 at 9:26 PM, Steve Dickson <[email protected]> wrote:
> Introducing three new command line arguments
> that allow particular keys to be revoke
>
>  -u will remove a uid key
>  -g will revoke a gid key
>  -r will revoke both the uid and gid keys
>
> The user name has also needs to be supply
> with these new flags.
>
> Signed-off-by: Steve Dickson <[email protected]>
> ---
>  utils/nfsidmap/nfsidmap.c   |   84 ++++++++++++++++++++++++++++++++++++++++--
>  utils/nfsidmap/nfsidmap.man |   23 ++++++++++--
>  2 files changed, 99 insertions(+), 8 deletions(-)
>
> diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
> index 2625dc1..7b64cd4 100644
> --- a/utils/nfsidmap/nfsidmap.c
> +++ b/utils/nfsidmap/nfsidmap.c
> @@ -13,7 +13,7 @@
>  #include "xlog.h"
>
>  int verbose = 0;
> -char *usage="Usage: %s [-v] [-c [keyring]] [-t timeout] key desc";
> +char *usage="Usage: %s [-v] [[-u|-g|-r key]] | [-c [keyring]] | [[-t timeout] key desc]";
>
>  #define MAX_ID_LEN   11
>  #define IDMAP_NAMESZ 128
> @@ -22,6 +22,9 @@ char *usage="Usage: %s [-v] [-c [keyring]] [-t timeout] key desc";
>  #define DEFAULT_KEYRING "id_resolver"
>  #define PROCKEYS "/proc/keys"
>
> +#define UIDKEYS 0x1
> +#define GIDKEYS 0x2
> +
>  /*
>  * Find either a user or group id based on the name@domain string
>  */
> @@ -130,6 +133,63 @@ static int keyring_clear(char *keyring)
>        xlog_err("'%s' keyring was not found.", keyring);
>        return 1;
>  }
> +/*
> + * Revoke a key
> + */
> +static int key_revoke(char *keystr, int keymask)
> +{
> +       FILE *fp;
> +       char buf[BUFSIZ], *ptr;
> +       key_serial_t key;
> +       int mask;
> +
> +       xlog_syslog(0);
> +
> +       if ((fp = fopen(PROCKEYS, "r")) == NULL) {

May be not critical, but you never closing fp.

Tigran.

> +               xlog_err("fopen(%s) failed: %m", PROCKEYS);
> +               return 1;
> +       }
> +
> +       while(fgets(buf, BUFSIZ, fp) != NULL) {
> +               if (strstr(buf, "keyring") != NULL)
> +                       continue;
> +
> +               mask = 0;
> +               if ((ptr = strstr(buf, "uid:")) != NULL)
> +                       mask = UIDKEYS;
> +               else if ((ptr = strstr(buf, "gid:")) != NULL)
> +                       mask = GIDKEYS;
> +               else
> +                       continue;
> +
> +               if ((keymask & mask) == 0)
> +                       continue;
> +
> +               if (strncmp(ptr+4, keystr, strlen(keystr)) != NULL)
> +                       continue;
> +
> +               if (verbose) {
> +                       *(strchr(buf, '\n')) = '\0';
> +                       xlog_warn("revoking '%s'", buf);
> +               }
> +               /*
> +                * The key is the first arugment in the string
> +                */
> +               *(strchr(buf, ' ')) = '\0';
> +               sscanf(buf, "%x", &key);
> +
> +               if (keyctl_revoke(key) < 0) {
> +                       xlog_err("keyctl_revoke(0x%x) failed: %m", key);
> +                       return 1;
> +               }
> +
> +               keymask &= ~mask;
> +               if (keymask == 0)
> +                       return 0;
> +       }
> +       xlog_err("'%s' key was not found.", keystr);
> +       return 1;
> +}
>
>  int main(int argc, char **argv)
>  {
> @@ -139,8 +199,8 @@ int main(int argc, char **argv)
>        int rc = 1, opt;
>        int timeout = 600;
>        key_serial_t key;
> -       char *progname, *keyring = NULL;
> -       int clearring;
> +       char *progname, *keyring = NULL, *keystr = NULL;
> +       int clearring, keymask = 0;
>
>        /* Set the basename */
>        if ((progname = strrchr(argv[0], '/')) != NULL)
> @@ -150,8 +210,20 @@ int main(int argc, char **argv)
>
>        xlog_open(progname);
>
> -       while ((opt = getopt(argc, argv, "ct:v")) != -1) {
> +       while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
>                switch (opt) {
> +               case 'u':
> +                       keymask = UIDKEYS;
> +                       keystr = strdup(optarg);
> +                       break;
> +               case 'g':
> +                       keymask = GIDKEYS;
> +                       keystr = strdup(optarg);
> +                       break;
> +               case 'r':
> +                       keymask = GIDKEYS|UIDKEYS;
> +                       keystr = strdup(optarg);
> +                       break;
>                case 'c':
>                        clearring++;
>                        break;
> @@ -167,6 +239,10 @@ int main(int argc, char **argv)
>                }
>        }
>
> +       if (keystr) {
> +               rc = key_revoke(keystr, keymask);
> +               return rc;
> +       }
>        if (clearring) {
>                keyring = ((argc - optind) ? argv[optind] : NULL);
>                rc = keyring_clear(keyring);
> diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
> index db65a1f..216afd1 100644
> --- a/utils/nfsidmap/nfsidmap.man
> +++ b/utils/nfsidmap/nfsidmap.man
> @@ -6,7 +6,11 @@
>  .SH NAME
>  nfsidmap \- The NFS idmapper upcall program
>  .SH SYNOPSIS
> -.B "nfsidmap [-v] [-c [keyring]] [-t timeout] key desc"
> +.B "nfsidmap [-v] [-t timeout] key desc"
> +.br
> +.B "nfsidmap [-v] [-c [keyring]]"
> +.br
> +.B "nfsidmap [-v] [-u|-g|-r user]"
>  .SH DESCRIPTION
>  The file
>  .I /usr/sbin/nfsidmap
> @@ -18,9 +22,11 @@ is called by /sbin/request-key, and will perform the translation and
>  initialize a key with the resulting information.
>  .PP
>  .I nfsidmap
> -can also used to clear the keyring of all the keys.
> -This is useful when all the mappings have failed to due to an DNS outage
> -or some other error resulting in all the cached uid/gid to be invalid.
> +can also used to clear the keyring of all the keys or
> +revoke one particular key.
> +This is useful when the id mappings have failed to due
> +to a lookup error resulting in all the cached uids/gids to be set
> +to the user id nobody.
>  .SH OPTIONS
>  .TP
>  .B -c [keyring]
> @@ -28,10 +34,19 @@ Clear the keyring of all the keys. If a
>  keyring is not supplied the default
>  keyring 'id_resolver' will be used.
>  .TP
> +.B -g user
> +Revoke the gid key of the given user.
> +.TP
> +.B -r user
> +Revoke both the uid and gid key of the given user.
> +.TP
>  .B -t timeout
>  Set the expiration timer, in seconds, on the key.
>  The default is 600 seconds (10 mins).
>  .TP
> +.B -u user
> +Revoke the uid key of the given user.
> +.TP
>  .B -v
>  Increases the verbosity of the output to syslog
>  (can be specified multiple times).
> --
> 1.7.7
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>