krb5 commit: Add kdestroy -p option

Greg Hudson <[email protected]>
Newsgroups gmane.comp.encryption.kerberos.cvs
Message-ID <[email protected]>
https://github.com/krb5/krb5/commit/35efaa5494c3c6d6c5e7cd5ffb73c48589110025
commit 35efaa5494c3c6d6c5e7cd5ffb73c48589110025
Author: Greg Hudson <[email protected]>
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:
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.