krb5 commit: Add kdestroy -p option

Greg Hudson ghudson at mit.edu
Thu Aug 9 11:10:42 EDT 2018


https://github.com/krb5/krb5/commit/35efaa5494c3c6d6c5e7cd5ffb73c48589110025
commit 35efaa5494c3c6d6c5e7cd5ffb73c48589110025
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Aug 8 11:45:28 2018 -0400

    Add kdestroy -p option
    
    Add an option to destroy a cache within a collection by principal
    name.  This option can be used together with -c to specify the
    collection.  Also document that kdestroy -A and -c can be used
    together (ticket 8602).
    
    ticket: 8724 (new)

 doc/user/user_commands/kdestroy.rst |    8 +++++-
 src/clients/kdestroy/kdestroy.c     |   47 +++++++++++++++++++++++++++++-----
 src/tests/t_ccache.py               |   15 ++++++++---
 3 files changed, 58 insertions(+), 12 deletions(-)

diff --git a/doc/user/user_commands/kdestroy.rst b/doc/user/user_commands/kdestroy.rst
index b8c67ab..37dcae9 100644
--- a/doc/user/user_commands/kdestroy.rst
+++ b/doc/user/user_commands/kdestroy.rst
@@ -26,7 +26,8 @@ OPTIONS
 
 **-A**
     Destroys all caches in the collection, if a cache collection is
-    available.
+    available.  May be used with the **-c** option to specify the
+    collection to be destroyed.
 
 **-q**
     Run quietly.  Normally kdestroy beeps if it fails to destroy the
@@ -41,6 +42,11 @@ OPTIONS
     **KRB5CCNAME** environment variable is set, its value is used to
     name the default ticket cache.
 
+**-p** *princ_name*
+    If a cache collection is available, destroy the cache for
+    *princ_name* instead of the primary cache.  May be used with the
+    **-c** option to specify the collection to be searched.
+
 
 NOTE
 ----
diff --git a/src/clients/kdestroy/kdestroy.c b/src/clients/kdestroy/kdestroy.c
index 4e16bec..774b729 100644
--- a/src/clients/kdestroy/kdestroy.c
+++ b/src/clients/kdestroy/kdestroy.c
@@ -49,10 +49,12 @@ char *progname;
 static void
 usage()
 {
-    fprintf(stderr, _("Usage: %s [-A] [-q] [-c cache_name]\n"), progname);
+    fprintf(stderr, _("Usage: %s [-A] [-q] [-c cache_name] [-p princ_name]\n"),
+            progname);
     fprintf(stderr, _("\t-A destroy all credential caches in collection\n"));
     fprintf(stderr, _("\t-q quiet mode\n"));
     fprintf(stderr, _("\t-c specify name of credentials cache\n"));
+    fprintf(stderr, _("\t-p specify principal name within collection\n"));
     exit(2);
 }
 
@@ -87,13 +89,15 @@ main(int argc, char *argv[])
     krb5_error_code ret;
     krb5_ccache cache = NULL;
     krb5_cccol_cursor cursor;
+    krb5_principal princ;
     char *cache_name = NULL;
+    const char *princ_name = NULL;
     int code = 0, errflg = 0, quiet = 0, all = 0, c;
 
     setlocale(LC_ALL, "");
     progname = GET_PROGNAME(argv[0]);
 
-    while ((c = getopt(argc, argv, "54Aqc:")) != -1) {
+    while ((c = getopt(argc, argv, "54Aqc:p:")) != -1) {
         switch (c) {
         case 'A':
             all = 1;
@@ -109,6 +113,14 @@ main(int argc, char *argv[])
                 cache_name = optarg;
             }
             break;
+        case 'p':
+            if (princ_name != NULL) {
+                fprintf(stderr, _("Only one -p option allowed\n"));
+                errflg++;
+            } else {
+                princ_name = optarg;
+            }
+            break;
         case '4':
             fprintf(stderr, _("Kerberos 4 is no longer supported\n"));
             exit(3);
@@ -122,6 +134,11 @@ main(int argc, char *argv[])
         }
     }
 
+    if (all && princ_name != NULL) {
+        fprintf(stderr, _("-A option is exclusive with -p option\n"));
+        errflg++;
+    }
+
     if (optind != argc)
         errflg++;
 
@@ -167,10 +184,26 @@ main(int argc, char *argv[])
         return 0;
     }
 
-    code = krb5_cc_default(context, &cache);
-    if (code) {
-        com_err(progname, code, _("while resolving ccache"));
-        exit(1);
+    if (princ_name != NULL) {
+        code = krb5_parse_name(context, princ_name, &princ);
+        if (code) {
+            com_err(progname, code, _("while parsing principal name %s"),
+                    princ_name);
+            exit(1);
+        }
+        code = krb5_cc_cache_match(context, princ, &cache);
+        if (code) {
+            com_err(progname, code, _("while finding cache for %s"),
+                    princ_name);
+            exit(1);
+        }
+        krb5_free_principal(context, princ);
+    } else {
+        code = krb5_cc_default(context, &cache);
+        if (code) {
+            com_err(progname, code, _("while resolving ccache"));
+            exit(1);
+        }
     }
 
     code = krb5_cc_destroy(context, cache);
@@ -187,7 +220,7 @@ main(int argc, char *argv[])
         }
     }
 
-    if (!quiet && !errflg)
+    if (!quiet && !errflg && princ_name == NULL)
         print_remaining_cc_warning(context);
 
     krb5_free_context(context);
diff --git a/src/tests/t_ccache.py b/src/tests/t_ccache.py
index 4802260..fcf1a61 100755
--- a/src/tests/t_ccache.py
+++ b/src/tests/t_ccache.py
@@ -56,6 +56,7 @@ realm.run([klist, '-s'], expected_code=1)
 realm.addprinc('alice', password('alice'))
 realm.addprinc('bob', password('bob'))
 realm.addprinc('carol', password('carol'))
+realm.addprinc('doug', password('doug'))
 
 def collection_test(realm, ccname):
     cctype = ccname.partition(':')[0]
@@ -86,14 +87,16 @@ def collection_test(realm, ccname):
     output = realm.run([klist, '-l'])
     if '---\nalice@' not in output or output.count('\n') != 4:
         fail('klist -l did not show expected output after re-kinit for alice.')
+    realm.kinit('doug', password('doug'))
     realm.kinit('bob', password('bob'))
     output = realm.run([klist, '-A', ccname])
     if 'bob@' not in output.splitlines()[1] or 'alice@' not in output or \
-            'carol' not in output or output.count('Default principal:') != 3:
-        fail('klist -A did not show expected output after kinit for bob.')
+       'carol@' not in output or 'doug@' not in output or \
+       output.count('Default principal:') != 4:
+        fail('klist -A did not show expected output after kinit doug+bob.')
     realm.run([kswitch, '-p', 'carol'])
     output = realm.run([klist, '-l'])
-    if '---\ncarol@' not in output or output.count('\n') != 5:
+    if '---\ncarol@' not in output or output.count('\n') != 6:
         fail('klist -l did not show expected output after kswitch to carol.')
 
     # Switch to specifying the collection name on the command line
@@ -103,10 +106,14 @@ def collection_test(realm, ccname):
     mark('%s collection, command-line specifier' % cctype)
     realm.run([kdestroy, '-c', ccname])
     output = realm.run([klist, '-l', ccname])
-    if 'carol@' in output or 'bob@' not in output or output.count('\n') != 4:
+    if 'carol@' in output or 'bob@' not in output or output.count('\n') != 5:
         fail('kdestroy failed to remove only primary ccache.')
     realm.run([klist, '-s', ccname], expected_code=1)
     realm.run([klist, '-A', '-s', ccname])
+    realm.run([kdestroy, '-p', 'alice', '-c', ccname])
+    output = realm.run([klist, '-l', ccname])
+    if 'alice@' in output or 'bob@' not in output or output.count('\n') != 4:
+        fail('kdestroy -p failed to remove alice')
     realm.run([kdestroy, '-A', '-c', ccname])
     output = realm.run([klist, '-l', ccname], expected_code=1)
     if not output.endswith('---\n') or output.count('\n') != 2:


More information about the cvs-krb5 mailing list