diff options
author | Petr Viktorin <pviktori@redhat.com> | 2016-01-14 14:15:49 +0100 |
---|---|---|
committer | Jan Cholasta <jcholast@redhat.com> | 2016-01-27 12:09:02 +0100 |
commit | 840de9bb48b37508e11fc0514761161e7cd0f9ef (patch) | |
tree | 2be322c04c238096923b2216a48249afa5d52bd7 /client/ipa-rmkeytab.c | |
parent | 7dae5c09d5a6bf084661511bef4811223da64252 (diff) | |
download | freeipa-840de9bb48b37508e11fc0514761161e7cd0f9ef.tar.gz freeipa-840de9bb48b37508e11fc0514761161e7cd0f9ef.tar.xz freeipa-840de9bb48b37508e11fc0514761161e7cd0f9ef.zip |
Split ipa-client/ into ipaclient/ (Python library) and client/ (C, scripts)
Make ipaclient a Python library like ipapython, ipalib, etc.
Use setup.py instead of autotools for installing it.
Move C client tools, Python scripts, and man pages, to client/.
Remove old, empty or outdated, boilerplate files (NEWS, README, AUTHORS).
Remove /setup-client.py (ipalib/setup.py should be used instead).
Update Makefiles and the spec file accordingly.
https://fedorahosted.org/freeipa/ticket/5638
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Diffstat (limited to 'client/ipa-rmkeytab.c')
-rw-r--r-- | client/ipa-rmkeytab.c | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/client/ipa-rmkeytab.c b/client/ipa-rmkeytab.c new file mode 100644 index 000000000..3687b1dc7 --- /dev/null +++ b/client/ipa-rmkeytab.c @@ -0,0 +1,268 @@ +/* Authors: Rob Crittenden <rcritten@redhat.com> + * + * Copyright (C) 2009 Red Hat + * see file 'COPYING' for use and warranty information + * + * This program is free software you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define _GNU_SOURCE +#include <stdlib.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <krb5.h> +#include <popt.h> +#include <errno.h> + +#include "ipa-client-common.h" +#include "config.h" + +int +remove_principal(krb5_context context, krb5_keytab ktid, const char *principal, int debug) +{ + krb5_error_code krberr; + krb5_keytab_entry entry, entry2; + int rval = 0; + int removed = 0; + + memset(&entry, 0, sizeof(entry)); + krberr = krb5_parse_name(context, principal, &entry.principal); + if (krberr) { + fprintf(stderr, _("Unable to parse principal name\n")); + if (debug) + fprintf(stderr, _("krb5_parse_name %1$d: %2$s\n"), + krberr, error_message(krberr)); + rval = 4; + goto done; + } + + /* Loop through the keytab and remove all entries with this principal name + * irrespective of the encryption type. A failure to find one after the + * first means we're done. + */ + fprintf(stderr, _("Removing principal %s\n"), principal); + while (1) { + memset(&entry2, 0, sizeof(entry2)); + krberr = krb5_kt_get_entry(context, ktid, + entry.principal, + 0, + 0, + &entry2); + if (krberr) { + if (removed > 0) + /* not found but we've removed some, we're done */ + break; + if (krberr == ENOENT) { + fprintf(stderr, _("Failed to open keytab\n")); + rval = 3; + goto done; + } + fprintf(stderr, _("principal not found\n")); + if (debug) + fprintf(stderr, _("krb5_kt_get_entry %1$d: %2$s\n"), + krberr, error_message(krberr)); + rval = 5; + break; + } + + krberr = krb5_kt_remove_entry(context, ktid, &entry2); + if (krberr) { + fprintf(stderr, _("Unable to remove entry\n")); + if (debug) { + fprintf(stdout, _("kvno %d\n"), entry2.vno); + fprintf(stderr, _("krb5_kt_remove_entry %1$d: %2$s\n"), + krberr, error_message(krberr)); + } + rval = 6; + break; + } + + krb5_free_keytab_entry_contents(context, &entry2); + removed++; + } + + if (entry2.principal) + krb5_free_keytab_entry_contents(context, &entry2); + +done: + + return rval; +} + +int +remove_realm(krb5_context context, krb5_keytab ktid, const char *realm, int debug) +{ + krb5_error_code krberr; + krb5_keytab_entry entry; + krb5_kt_cursor kt_cursor; + char * entry_princ_s = NULL; + int rval = 0; + bool realm_found = false; + + krberr = krb5_kt_start_seq_get(context, ktid, &kt_cursor); + memset(&entry, 0, sizeof(entry)); + while (krb5_kt_next_entry(context, ktid, &entry, &kt_cursor) == 0) { + krberr = krb5_unparse_name(context, entry.principal, &entry_princ_s); + if (krberr) { + fprintf(stderr, _("Unable to parse principal\n")); + if (debug) { + fprintf(stderr, _("krb5_unparse_name %1$d: %2$s\n"), + krberr, error_message(krberr)); + } + rval = 4; + goto done; + } + + /* keytab entries are locked when looping. Temporarily suspend + * the looping. */ + krb5_kt_end_seq_get(context, ktid, &kt_cursor); + + if (strstr(entry_princ_s, realm) != NULL) { + realm_found = true; + rval = remove_principal(context, ktid, entry_princ_s, debug); + if (rval != 0) + goto done; + /* Have to reset the cursor */ + krberr = krb5_kt_start_seq_get(context, ktid, &kt_cursor); + } + } + + if (!realm_found) { + fprintf(stderr, _("realm not found\n")); + return 5; + } + +done: + + return rval; +} + +int +main(int argc, const char **argv) +{ + krb5_context context; + krb5_error_code krberr; + krb5_keytab ktid; + krb5_kt_cursor cursor; + char * ktname = NULL; + char * atrealm = NULL; + poptContext pc; + static const char *keytab = NULL; + static const char *principal = NULL; + static const char *realm = NULL; + int debug = 0; + int ret, rval = 0; + struct poptOption options[] = { + { "debug", 'd', POPT_ARG_NONE, &debug, 0, + _("Print debugging information"), _("Debugging output") }, + { "principal", 'p', POPT_ARG_STRING, &principal, 0, + _("The principal to remove from the keytab (ex: ftp/ftp.example.com@EXAMPLE.COM)"), + _("Kerberos Service Principal Name") }, + { "keytab", 'k', POPT_ARG_STRING, &keytab, 0, + _("The keytab file to remove the principcal(s) from"), _("Keytab File Name") }, + { "realm", 'r', POPT_ARG_STRING, &realm, 0, + _("Remove all principals in this realm"), _("Realm name") }, + POPT_AUTOHELP + POPT_TABLEEND + }; + + ret = init_gettext(); + if (ret) { + exit(1); + } + + memset(&ktid, 0, sizeof(ktid)); + + krberr = krb5_init_context(&context); + if (krberr) { + fprintf(stderr, _("Kerberos context initialization failed\n")); + exit(1); + } + + pc = poptGetContext("ipa-rmkeytab", argc, (const char **)argv, options, 0); + ret = poptGetNextOpt(pc); + if (ret != -1 || (!principal && !realm) || !keytab) { + poptPrintUsage(pc, stderr, 0); + rval = 1; + goto cleanup; + } + + ret = asprintf(&ktname, "WRFILE:%s", keytab); + if (ret == -1) { + rval = 2; + goto cleanup; + } + + /* The remove_realm function just does a substring match. Ensure that + * the string we pass in looks like a realm. + */ + if (realm) { + if (realm[0] != '@') { + ret = asprintf(&atrealm, "@%s", realm); + if (ret == -1) { + rval = 2; + goto cleanup; + } + } else { + atrealm = strdup(realm); + + if (NULL == atrealm) { + rval = 2; + goto cleanup; + } + } + } + + krberr = krb5_kt_resolve(context, ktname, &ktid); + if (krberr) { + fprintf(stderr, _("Failed to open keytab '%1$s': %2$s\n"), keytab, + error_message(krberr)); + rval = 3; + goto cleanup; + } + krberr = krb5_kt_start_seq_get(context, ktid, &cursor); + if (krberr) { + fprintf(stderr, _("Failed to open keytab '%1$s': %2$s\n"), keytab, + error_message(krberr)); + rval = 3; + goto cleanup; + } + krb5_kt_end_seq_get(context, ktid, &cursor); + + if (principal) + rval = remove_principal(context, ktid, principal, debug); + else if (realm) + rval = remove_realm(context, ktid, atrealm, debug); + +cleanup: + if (rval == 0 || rval > 3) { + krberr = krb5_kt_close(context, ktid); + if (krberr) { + fprintf(stderr, _("Closing keytab failed\n")); + if (debug) + fprintf(stderr, _("krb5_kt_close %1$d: %2$s\n"), + krberr, error_message(krberr)); + } + } + + krb5_free_context(context); + + poptFreeContext(pc); + + free(atrealm); + free(ktname); + + return rval; +} |