nsupdate: get the default realm from the users kerberos ticket
authorAndrew Tridgell <tridge@samba.org>
Tue, 21 Dec 2010 07:19:11 +0000 (18:19 +1100)
committerAndrew Tridgell <tridge@samba.org>
Tue, 21 Dec 2010 07:22:27 +0000 (18:22 +1100)
If available, look in the users kerberos ticket to find the right
kerberos realm. This avoids the need to setup a temporary krb5.conf as
we can then use the DNS/name@REALM form of principal

bin/nsupdate/nsupdate.c
lib/dns/gssapictx.c

index 01fea441a16edfefa8e6c406cc768088a425c06d..a5f4cd0c25a4a8b75a30092b43e51f28a87916a1 100644 (file)
@@ -2431,6 +2431,58 @@ sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
 }
 
 #ifdef GSSAPI
+
+/*
+ * Get the realm from the users kerberos ticket if possible
+ */
+static void
+get_ticket_realm(isc_mem_t *mctx)
+{
+       krb5_context ctx;
+       krb5_error_code rc;
+       krb5_ccache ccache;
+       krb5_principal princ;
+       char *name, *ticket_realm;
+       
+       rc = krb5_init_context(&ctx);
+       if (rc != 0)
+               return;
+
+       rc = krb5_cc_default(ctx, &ccache);
+       if (rc != 0) {
+               krb5_free_context(ctx);
+               return;
+       }
+               
+       rc = krb5_cc_get_principal(ctx, ccache, &princ);
+       if (rc != 0) {
+               krb5_cc_close(ctx, ccache);
+               krb5_free_context(ctx);
+               return;
+       }
+
+       rc = krb5_unparse_name(ctx, princ, &name);
+       if (rc != 0) {
+               krb5_free_principal(ctx, princ);
+               krb5_cc_close(ctx, ccache);
+               krb5_free_context(ctx);
+               return;
+       }
+
+       ticket_realm = strrchr(name, '@');
+       if (ticket_realm != NULL) {
+               realm = isc_mem_strdup(mctx, ticket_realm);
+       }
+
+       free(name);
+       krb5_free_principal(ctx, princ);
+       krb5_cc_close(ctx, ccache);
+       krb5_free_context(ctx);
+       if (realm != NULL && debugging)
+               fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
+}
+
+
 static void
 start_gssrequest(dns_name_t *master, dns_name_t *zone)
 {
@@ -2472,6 +2524,9 @@ start_gssrequest(dns_name_t *master, dns_name_t *zone)
        dns_fixedname_init(&fname);
        servname = dns_fixedname_name(&fname);
 
+       if (realm == NULL)
+               get_ticket_realm(mctx);
+
        result = isc_string_printf(servicename, sizeof(servicename),
                                   "DNS/%s%s", namestr, realm ? realm : "");
        if (result != ISC_R_SUCCESS)
index 29b2af0a3d9dfb6fff8f01efe04afa88d848769c..d63bee575f4f2ea10390bb88207e835e437b74d5 100644 (file)
@@ -516,82 +516,6 @@ dst_gssapi_releasecred(gss_cred_id_t *cred) {
 }
 
 #ifdef GSSAPI
-/*
- * GSSAPI with krb5 doesn't have a way to set the default realm, as it
- * doesn't offer any access to the krb5 context that it uses. The only
- * way to do an nsupdate call on a realm that isn't the default realm in
- * /etc/krb5.conf is to create a temporary krb5.conf and put the right
- * realm in there as the default realm, then set KRB5_CONFIG to point
- * at that temporary krb5.conf. This is a disgusting hack, but it is
- * the best we can do with GSSAPI.
- *
- * To try to reduce the impact, this routine checks if the default
- * realm is already correct. If it is, then we don't need to do
- * anything. If not, then we create the temporary krb5.conf.
- */
-static void
-check_zone(dns_name_t *zone, isc_mem_t *mctx, char **tmpfile) {
-       krb5_context ctx;
-       int kret;
-       char *realm;
-       char buf[1024];
-       isc_result_t ret;
-       FILE *fp = NULL;
-       char *p, *template;
-
-       if (getenv("KRB5_CONFIG") != NULL) {
-               /* the user has specifically set a KRB5_CONFIG to
-                  use. Don't override it, as they may know what they are
-                  doing */
-               return;
-       }
-
-       dns_name_format(zone, buf, sizeof(buf));
-
-       /* gssapi wants the realm in upper case */
-       for (p=buf; *p; p++) {
-               if (islower((int)*p))
-                       *p = toupper((int)*p);
-       }
-
-       kret = krb5_init_context(&ctx);
-       if (kret != 0)
-               return;
-
-       kret = krb5_get_default_realm(ctx, &realm);
-       if (kret == 0 && strcmp(buf, realm) == 0) {
-               /* the krb5.conf is correct. */
-               krb5_free_context(ctx);
-               return;
-       }
-
-       gss_log(3, "zone '%s' doesn't match KRB5 default realm '%s'",
-               buf, realm);
-
-       template = isc_mem_strdup(mctx, "/tmp/krb5.conf.XXXXXX");
-       if (template == NULL) {
-               krb5_free_context(ctx);
-               return;
-       }
-
-       ret = isc_file_openunique(template, &fp);
-       if (ret != ISC_R_SUCCESS) {
-               krb5_free_context(ctx);
-               return;
-       }
-
-       fprintf(fp, "[libdefaults]\n");
-       fprintf(fp, "\tdefault_realm = %s\n", buf);
-       fprintf(fp, "\tdns_lookup_kdc = true\n");
-       fclose(fp);
-
-       setenv("KRB5_CONFIG", template, 1);
-
-       *tmpfile = template;
-
-       krb5_free_context(ctx);
-}
-
 /*
  * Format a gssapi error message info into a char ** on the given memory
  * context. This is used to return gssapi error messages back up the
@@ -635,10 +559,6 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
        REQUIRE(gssctx != NULL);
        REQUIRE(mctx != NULL);
 
-       if (zone != NULL && mctx != NULL) {
-               check_zone(zone, mctx, &tmpfile);
-       }
-
        isc_buffer_init(&namebuf, array, sizeof(array));
        name_to_gbuffer(name, &namebuf, &gnamebuf);