summaryrefslogtreecommitdiffstats
path: root/source3/utils
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2012-09-19 15:31:57 +0200
committerGünther Deschner <gd@samba.org>2012-10-02 16:22:31 +0200
commita2fec69b0958f75e31c702e25017eeae6a92be0d (patch)
tree4814d876ea5d53bf384417866c394977485b3b96 /source3/utils
parent06f3b1f0b0dcf9355a8d634cdb62f1f0a8ea4dbe (diff)
s3-net: pass down struct net_context to the dns update calls.
Guenther
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/net_ads.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index b1d55f10b0..3b671fc600 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -1131,7 +1131,8 @@ DNS_ERROR DoDNSUpdate(char *pszServerName,
const struct sockaddr_storage *sslist,
size_t num_addrs );
-static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
+static NTSTATUS net_update_dns_internal(struct net_context *c,
+ TALLOC_CTX *ctx, ADS_STRUCT *ads,
const char *machine_name,
const struct sockaddr_storage *addrs,
int num_addrs)
@@ -1242,7 +1243,8 @@ done:
return status;
}
-static NTSTATUS net_update_dns_ext(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
+static NTSTATUS net_update_dns_ext(struct net_context *c,
+ TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
const char *hostname,
struct sockaddr_storage *iplist,
int num_addrs)
@@ -1274,18 +1276,18 @@ static NTSTATUS net_update_dns_ext(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
iplist = iplist_alloc;
}
- status = net_update_dns_internal(mem_ctx, ads, machine_name,
+ status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
iplist, num_addrs);
SAFE_FREE(iplist_alloc);
return status;
}
-static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
+static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
{
NTSTATUS status;
- status = net_update_dns_ext(mem_ctx, ads, hostname, NULL, 0);
+ status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0);
return status;
}
#endif
@@ -1315,7 +1317,7 @@ static int net_ads_join_usage(struct net_context *c, int argc, const char **argv
}
-static void _net_ads_join_dns_updates(TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
+static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
{
#if defined(WITH_DNS_UPDATES)
ADS_STRUCT *ads_dns = NULL;
@@ -1389,7 +1391,7 @@ static void _net_ads_join_dns_updates(TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
goto done;
}
- status = net_update_dns(ctx, ads_dns, NULL);
+ status = net_update_dns(c, ctx, ads_dns, NULL);
if (!NT_STATUS_IS_OK(status)) {
d_fprintf( stderr, _("DNS update failed: %s\n"),
nt_errstr(status));
@@ -1545,7 +1547,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
* If the dns update fails, we still consider the join
* operation as succeeded if we came this far.
*/
- _net_ads_join_dns_updates(ctx, r);
+ _net_ads_join_dns_updates(c, ctx, r);
TALLOC_FREE(r);
TALLOC_FREE( ctx );
@@ -1641,7 +1643,7 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
return -1;
}
- ntstatus = net_update_dns_ext(ctx, ads, hostname, addrs, num_addrs);
+ ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs);
if (!NT_STATUS_IS_OK(ntstatus)) {
d_fprintf( stderr, _("DNS update failed!\n") );
ads_destroy( &ads );
n218' href='#n218'>218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 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) {
        fprintf(stderr, "Failed to load translations\n");
    }

    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"));