lib/addns: rewrite signed dns update code to use gensec instead of plain gssapi
authorStefan Metzmacher <metze@samba.org>
Thu, 7 Mar 2024 11:03:05 +0000 (12:03 +0100)
committerStefan Metzmacher <metze@samba.org>
Tue, 14 May 2024 10:18:31 +0000 (10:18 +0000)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
lib/addns/dns.h
lib/addns/dnsgss.c
lib/addns/wscript_build
source3/utils/net_ads.c
source3/utils/net_ads_join_dns.c
source3/utils/net_dns.c
source3/utils/net_dns.h
source3/utils/net_proto.h

index 2c311e72a00da01464fa389e6719bb8e37c03828..abf0906fdabe0705daaefb6b79f51445b02a03de 100644 (file)
@@ -347,20 +347,16 @@ const char *dns_errstr(DNS_ERROR err);
 
 /* from dnsgss.c */
 
-#ifdef HAVE_GSSAPI
-
-void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat ); 
-DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
-                                const char *servername,
-                                const char *keyname,
-                                gss_ctx_id_t *gss_ctx,
-                                enum dns_ServerType srv_type );
+struct gensec_security;
+
+DNS_ERROR dns_negotiate_sec_ctx(const char *servername,
+                               const char *keyname,
+                               struct gensec_security *gensec,
+                               enum dns_ServerType srv_type);
 DNS_ERROR dns_sign_update(struct dns_update_request *req,
-                         gss_ctx_id_t gss_ctx,
+                         struct gensec_security *gensec,
                          const char *keyname,
                          const char *algorithmname,
                          time_t time_signed, uint16_t fudge);
 
-#endif /* HAVE_GSSAPI */
-
 #endif /* _DNS_H */
index a315b804df4774465f67fc7552e453eb59a1c2e1..8800ac24c8aea2f68b0ff76b27f130e245ecf515 100644 (file)
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
-#include "dns.h"
-#include <ctype.h>
-
-
-#ifdef HAVE_GSSAPI
-
-/*********************************************************************
-*********************************************************************/
-
-#ifndef HAVE_STRUPR
-static int strupr( char *szDomainName )
-{
-       if ( !szDomainName ) {
-               return ( 0 );
-       }
-       while ( *szDomainName != '\0' ) {
-               *szDomainName = toupper( *szDomainName );
-               szDomainName++;
-       }
-       return ( 0 );
-}
-#endif
-
-#if 0
-/*********************************************************************
-*********************************************************************/
-
-static void display_status_1( const char *m, OM_uint32 code, int type )
-{
-       OM_uint32 maj_stat, min_stat;
-       gss_buffer_desc msg;
-       OM_uint32 msg_ctx;
-
-       msg_ctx = 0;
-       while ( 1 ) {
-               maj_stat = gss_display_status( &min_stat, code,
-                                              type, GSS_C_NULL_OID,
-                                              &msg_ctx, &msg );
-               fprintf( stdout, "GSS-API error %s: %s\n", m,
-                        ( char * ) msg.value );
-               ( void ) gss_release_buffer( &min_stat, &msg );
-
-               if ( !msg_ctx )
-                       break;
-       }
-}
+#include "replace.h"
+#include <talloc.h>
+#include "lib/util/talloc_stack.h"
+#include "lib/util/data_blob.h"
+#include "lib/util/time.h"
+#include "lib/util/charset/charset.h"
+#include "libcli/util/ntstatus.h"
+#include "auth/gensec/gensec.h"
 
-/*********************************************************************
-*********************************************************************/
+#include "dns.h"
 
-void display_status( const char *msg, OM_uint32 maj_stat, OM_uint32 min_stat )
-{
-       display_status_1( msg, maj_stat, GSS_C_GSS_CODE );
-       display_status_1( msg, min_stat, GSS_C_MECH_CODE );
-}
-#endif
-
-static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
-                                           struct dns_connection *conn,
-                                           const char *keyname,
-                                           const gss_name_t target_name,
-                                           gss_ctx_id_t *ctx, 
-                                           enum dns_ServerType srv_type )
+static DNS_ERROR dns_negotiate_gss_ctx_int(struct dns_connection *conn,
+                                          const char *keyname,
+                                          struct gensec_security *gensec,
+                                          enum dns_ServerType srv_type)
 {
-       struct gss_buffer_desc_struct input_desc, *input_ptr, output_desc;
-       OM_uint32 major, minor;
-       OM_uint32 ret_flags;
+       TALLOC_CTX *frame = talloc_stackframe();
        struct dns_request *req = NULL;
        struct dns_buffer *buf = NULL;
+       DATA_BLOB in = { .length = 0, };
+       DATA_BLOB out = { .length = 0, };
+       NTSTATUS status;
        DNS_ERROR err;
 
-       gss_OID_desc krb5_oid_desc =
-               { 9, discard_const("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
-
-       *ctx = GSS_C_NO_CONTEXT;
-       input_ptr = NULL;
-
        do {
-               major = gss_init_sec_context(
-                       &minor, NULL, ctx, target_name, &krb5_oid_desc,
-                       GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG |
-                       GSS_C_CONF_FLAG |
-                       GSS_C_INTEG_FLAG,
-                       0, NULL, input_ptr, NULL, &output_desc,
-                       &ret_flags, NULL );
-
-               if (input_ptr != NULL) {
-                       TALLOC_FREE(input_desc.value);
+               status = gensec_update(gensec, frame, in, &out);
+               data_blob_free(&in);
+               if (GENSEC_UPDATE_IS_NTERROR(status)) {
+                       err = ERROR_DNS_GSS_ERROR;
+                       goto error;
                }
 
-               if (output_desc.length != 0) {
-
+               if (out.length != 0) {
                        struct dns_rrec *rec;
 
                        time_t t = time(NULL);
 
-                       err = dns_create_query(mem_ctx, keyname, QTYPE_TKEY,
+                       err = dns_create_query(frame, keyname, QTYPE_TKEY,
                                               DNS_CLASS_IN, &req);
                        if (!ERR_DNS_IS_OK(err)) goto error;
 
                        err = dns_create_tkey_record(
                                req, keyname, "gss.microsoft.com", t,
                                t + 86400, DNS_TKEY_MODE_GSSAPI, 0,
-                               output_desc.length, (uint8_t *)output_desc.value,
+                               out.length, out.data,
                                &rec );
                        if (!ERR_DNS_IS_OK(err)) goto error;
 
@@ -143,7 +84,7 @@ static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
                        
                        if (!ERR_DNS_IS_OK(err)) goto error;
 
-                       err = dns_marshall_request(mem_ctx, req, &buf);
+                       err = dns_marshall_request(frame, req, &buf);
                        if (!ERR_DNS_IS_OK(err)) goto error;
 
                        err = dns_send(conn, buf);
@@ -151,24 +92,21 @@ static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
 
                        TALLOC_FREE(buf);
                        TALLOC_FREE(req);
-               }
-
-               gss_release_buffer(&minor, &output_desc);
 
-               if ((major != GSS_S_COMPLETE) &&
-                   (major != GSS_S_CONTINUE_NEEDED)) {
-                       return ERROR_DNS_GSS_ERROR;
+                       err = dns_receive(frame, conn, &buf);
+                       if (!ERR_DNS_IS_OK(err)) goto error;
                }
 
-               if (major == GSS_S_CONTINUE_NEEDED) {
-
+               if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                        struct dns_request *resp;
                        struct dns_tkey_record *tkey;
                        struct dns_rrec *tkey_answer = NULL;
                        uint16_t i;
 
-                       err = dns_receive(mem_ctx, conn, &buf);
-                       if (!ERR_DNS_IS_OK(err)) goto error;
+                       if (buf == NULL) {
+                               err = ERROR_DNS_BAD_RESPONSE;
+                               goto error;
+                       }
 
                        err = dns_unmarshall_request(buf, buf, &resp);
                        if (!ERR_DNS_IS_OK(err)) goto error;
@@ -191,18 +129,15 @@ static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
                        }
 
                        err = dns_unmarshall_tkey_record(
-                               mem_ctx, resp->answers[0], &tkey);
+                               frame, resp->answers[0], &tkey);
                        if (!ERR_DNS_IS_OK(err)) goto error;
 
-                       input_desc.length = tkey->key_length;
-                       input_desc.value = talloc_move(mem_ctx, &tkey->key);
-
-                       input_ptr = &input_desc;
+                       in = data_blob_const(tkey->key, tkey->key_length);
 
                        TALLOC_FREE(buf);
                }
 
-       } while ( major == GSS_S_CONTINUE_NEEDED );
+       } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
 
        /* If we arrive here, we have a valid security context */
 
@@ -210,94 +145,54 @@ static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
 
       error:
 
-       TALLOC_FREE(buf);
-       TALLOC_FREE(req);
+       TALLOC_FREE(frame);
        return err;
 }
 
-DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
-                                const char *servername,
-                                const char *keyname,
-                                gss_ctx_id_t *gss_ctx,
-                                enum dns_ServerType srv_type )
+DNS_ERROR dns_negotiate_sec_ctx(const char *servername,
+                               const char *keyname,
+                               struct gensec_security *gensec,
+                               enum dns_ServerType srv_type)
 {
-       OM_uint32 major, minor;
-
-       char *upcaserealm, *targetname;
+       TALLOC_CTX *frame = talloc_stackframe();
        DNS_ERROR err;
+       struct dns_connection *conn = NULL;
 
-       gss_buffer_desc input_name;
-       struct dns_connection *conn;
-
-       gss_name_t targ_name;
-
-       gss_OID_desc nt_host_oid_desc =
-               {10, discard_const("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
-
-       TALLOC_CTX *mem_ctx;
-
-       if (!(mem_ctx = talloc_init("dns_negotiate_sec_ctx"))) {
-               return ERROR_DNS_NO_MEMORY;
-       }
-
-       err = dns_open_connection( servername, DNS_TCP, mem_ctx, &conn );
+       err = dns_open_connection( servername, DNS_TCP, frame, &conn );
        if (!ERR_DNS_IS_OK(err)) goto error;
 
-       if (!(upcaserealm = talloc_strdup(mem_ctx, target_realm))) {
-               err = ERROR_DNS_NO_MEMORY;
-               goto error;
-       }
-
-       strupr(upcaserealm);
-
-       if (!(targetname = talloc_asprintf(mem_ctx, "dns/%s@%s",
-                                          servername, upcaserealm))) {
-               err = ERROR_DNS_NO_MEMORY;
-               goto error;
-       }
-
-       input_name.value = targetname;
-       input_name.length = strlen(targetname);
-
-       major = gss_import_name( &minor, &input_name,
-                                &nt_host_oid_desc, &targ_name );
-
-       if (major) {
-               err = ERROR_DNS_GSS_ERROR;
-               goto error;
-       }
-
-       err = dns_negotiate_gss_ctx_int(mem_ctx, conn, keyname, 
-                                       targ_name, gss_ctx, srv_type );
-       
-       gss_release_name( &minor, &targ_name );
+       err = dns_negotiate_gss_ctx_int(conn, keyname,
+                                       gensec,
+                                       srv_type);
+       if (!ERR_DNS_IS_OK(err)) goto error;
 
  error:
-       TALLOC_FREE(mem_ctx);
+       TALLOC_FREE(frame);
 
        return err;
 }
 
 DNS_ERROR dns_sign_update(struct dns_update_request *req,
-                         gss_ctx_id_t gss_ctx,
+                         struct gensec_security *gensec,
                          const char *keyname,
                          const char *algorithmname,
                          time_t time_signed, uint16_t fudge)
 {
+       TALLOC_CTX *frame = talloc_stackframe();
        struct dns_buffer *buf;
        DNS_ERROR err;
        struct dns_domain_name *key, *algorithm;
-       struct gss_buffer_desc_struct msg, mic;
-       OM_uint32 major, minor;
        struct dns_rrec *rec;
+       DATA_BLOB mic = { .length = 0, };
+       NTSTATUS status;
 
-       err = dns_marshall_update_request(req, req, &buf);
+       err = dns_marshall_update_request(frame, req, &buf);
        if (!ERR_DNS_IS_OK(err)) return err;
 
-       err = dns_domain_name_from_string(buf, keyname, &key);
+       err = dns_domain_name_from_string(frame, keyname, &key);
        if (!ERR_DNS_IS_OK(err)) goto error;
 
-       err = dns_domain_name_from_string(buf, algorithmname, &algorithm);
+       err = dns_domain_name_from_string(frame, algorithmname, &algorithm);
        if (!ERR_DNS_IS_OK(err)) goto error;
 
        dns_marshall_domain_name(buf, key);
@@ -313,32 +208,31 @@ DNS_ERROR dns_sign_update(struct dns_update_request *req,
        err = buf->error;
        if (!ERR_DNS_IS_OK(buf->error)) goto error;
 
-       msg.value = (void *)buf->data;
-       msg.length = buf->offset;
-
-       major = gss_get_mic(&minor, gss_ctx, 0, &msg, &mic);
-       if (major != 0) {
+       status = gensec_sign_packet(gensec,
+                                   frame,
+                                   buf->data,
+                                   buf->offset,
+                                   buf->data,
+                                   buf->offset,
+                                   &mic);
+       if (!NT_STATUS_IS_OK(status)) {
                err = ERROR_DNS_GSS_ERROR;
                goto error;
        }
 
        if (mic.length > 0xffff) {
-               gss_release_buffer(&minor, &mic);
                err = ERROR_DNS_GSS_ERROR;
                goto error;
        }
 
-       err = dns_create_tsig_record(buf, keyname, algorithmname, time_signed,
-                                    fudge, mic.length, (uint8_t *)mic.value,
+       err = dns_create_tsig_record(frame, keyname, algorithmname, time_signed,
+                                    fudge, mic.length, mic.data,
                                     req->id, 0, &rec);
-       gss_release_buffer(&minor, &mic);
        if (!ERR_DNS_IS_OK(err)) goto error;
 
        err = dns_add_rrec(req, rec, &req->num_additionals, &req->additional);
 
  error:
-       TALLOC_FREE(buf);
+       TALLOC_FREE(frame);
        return err;
 }
-
-#endif /* HAVE_GSSAPI */
index cc72b35b437ce91294bbe5031adb19cb276d6803..694d71b732e1abc54d7868a5fca49b90eb7855bf 100644 (file)
@@ -11,6 +11,6 @@ bld.SAMBA_LIBRARY('addns',
                        error.c
                        dnsquery_srv.c
                    ''',
-                   public_deps='samba-util gssapi ndr resolv dns_lookup',
+                   public_deps='samba-util gensec ndr resolv dns_lookup',
                    private_library=True,
                    vars=locals())
index 4350e5e9b41e3069c00a8a88bf9806a671ce0c25..d7ddef60e395c6622093df214b00abe6eb6f2f5d 100644 (file)
@@ -1997,6 +1997,7 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
        ntstatus = net_update_dns_ext(c,
                                      tmp_ctx,
                                      ads,
+                                     c->creds,
                                      hostname,
                                      addrs,
                                      num_addrs,
@@ -2063,6 +2064,7 @@ static int net_ads_dns_unregister(struct net_context *c,
        ntstatus = net_update_dns_ext(c,
                                      tmp_ctx,
                                      ads,
+                                     c->creds,
                                      hostname,
                                      NULL,
                                      0,
index 97f767aba661c0c1a21e4dba8daf71fd5d78a21b..617a0d94246219d12261f989103095abc025940a 100644 (file)
@@ -23,7 +23,7 @@
 #include "includes.h"
 #include "utils/net.h"
 #include "../lib/addns/dnsquery.h"
-#include "secrets.h"
+#include "passdb.h"
 #include "krb5_env.h"
 #include "utils/net_dns.h"
 #include "lib/util/string_wrappers.h"
@@ -44,7 +44,9 @@ void use_in_memory_ccache(void) {
 }
 
 static NTSTATUS net_update_dns_internal(struct net_context *c,
-                                       TALLOC_CTX *ctx, ADS_STRUCT *ads,
+                                       TALLOC_CTX *ctx,
+                                       ADS_STRUCT *ads,
+                                       struct cli_credentials *creds,
                                        const char *machine_name,
                                        const struct sockaddr_storage *addrs,
                                        int num_addrs, bool remove_host)
@@ -85,7 +87,7 @@ static NTSTATUS net_update_dns_internal(struct net_context *c,
                ADS_STATUS ads_status;
 
                if ( !ads->ldap.ld ) {
-                       ads_status = ads_connect( ads );
+                       ads_status = ads_connect_creds(ads, creds);
                        if ( !ADS_ERR_OK(ads_status) ) {
                                DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
                                status = ads_ntstatus(ads_status);
@@ -163,6 +165,7 @@ static NTSTATUS net_update_dns_internal(struct net_context *c,
                dns_err = DoDNSUpdate(dns_server,
                                      dnsdomain,
                                      machine_name,
+                                     creds,
                                      addrs,
                                      num_addrs,
                                      flags,
@@ -195,7 +198,9 @@ done:
 }
 
 NTSTATUS net_update_dns_ext(struct net_context *c,
-                           TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
+                           TALLOC_CTX *mem_ctx,
+                           ADS_STRUCT *ads,
+                           struct cli_credentials *creds,
                            const char *hostname,
                            struct sockaddr_storage *iplist,
                            int num_addrs, bool remove_host)
@@ -231,29 +236,27 @@ NTSTATUS net_update_dns_ext(struct net_context *c,
                iplist = iplist_alloc;
        }
 
-       status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
-                                        iplist, num_addrs, remove_host);
+       status = net_update_dns_internal(c,
+                                        mem_ctx,
+                                        ads,
+                                        creds,
+                                        machine_name,
+                                        iplist,
+                                        num_addrs,
+                                        remove_host);
 
        SAFE_FREE(iplist_alloc);
        return status;
 }
 
-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(c, mem_ctx, ads, hostname, NULL, 0, false);
-       return status;
-}
 #endif
 
 void net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
 {
 #if defined(HAVE_KRB5)
        ADS_STRUCT *ads_dns = NULL;
-       int ret;
+       struct cli_credentials *creds = NULL;
        NTSTATUS status;
-       char *machine_password = NULL;
 
        /*
         * In a clustered environment, don't do dynamic dns updates:
@@ -283,7 +286,7 @@ void net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct lib
 
        ads_dns = ads_init(ctx,
                           lp_realm(),
-                          NULL,
+                          lp_workgroup(),
                           r->in.dc_name,
                           ADS_SASL_PLAIN);
        if (ads_dns == NULL) {
@@ -291,45 +294,24 @@ void net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct lib
                goto done;
        }
 
-       use_in_memory_ccache();
-
-       ads_dns->auth.user_name = talloc_asprintf(ads_dns,
-                                                 "%s$",
-                                                 lp_netbios_name());
-       if (ads_dns->auth.user_name == NULL) {
-               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
-               goto done;
-       }
-
-       machine_password = secrets_fetch_machine_password(
-               r->out.netbios_domain_name, NULL, NULL);
-       if (machine_password != NULL) {
-               ads_dns->auth.password = talloc_strdup(ads_dns,
-                                                      machine_password);
-               SAFE_FREE(machine_password);
-               if (ads_dns->auth.password == NULL) {
-                       d_fprintf(stderr,
-                                 _("DNS update failed: out of memory\n"));
-                       goto done;
-               }
-       }
-
-       ads_dns->auth.realm = talloc_asprintf_strupper_m(ads_dns, "%s", r->out.dns_domain_name);
-       if (ads_dns->auth.realm == NULL) {
-               d_fprintf(stderr, _("talloc_asprintf_strupper_m %s failed\n"),
-                                 ads_dns->auth.realm);
-               goto done;
-       }
-
-       ret = ads_kinit_password(ads_dns);
-       if (ret != 0) {
-               d_fprintf(stderr,
-                         _("DNS update failed: kinit failed: %s\n"),
-                         error_message(ret));
+       status = pdb_get_trust_credentials(ads_dns->server.workgroup,
+                                          ads_dns->server.realm,
+                                          ads_dns,
+                                          &creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "pdb_get_trust_credentials() failed: %s\n",
+                         nt_errstr(status));
                goto done;
        }
 
-       status = net_update_dns(c, ctx, ads_dns, NULL);
+       status = net_update_dns_ext(c,
+                                   ads_dns,
+                                   ads_dns,
+                                   creds,
+                                   NULL,
+                                   NULL,
+                                   0,
+                                   false);
        if (!NT_STATUS_IS_OK(status)) {
                d_fprintf( stderr, _("DNS update failed: %s\n"),
                          nt_errstr(status));
index 9850ba40299086859571c4cf0dff4469fa0ee992..486f1752b109c95bc75db9dbbfe24e204cf8920c 100644 (file)
 #include "utils/net.h"
 #include "../lib/addns/dns.h"
 #include "utils/net_dns.h"
+#include "auth/gensec/gensec.h"
+#include "auth_generic.h"
 
 #if defined(HAVE_KRB5)
 
 /*********************************************************************
 *********************************************************************/
 
+static DNS_ERROR DoDNSUpdateNegotiateGensec(const char *pszServerName,
+                                           const char *pszDomainName,
+                                           const char *keyname,
+                                           enum dns_ServerType srv_type,
+                                           struct cli_credentials *creds,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct gensec_security **_gensec)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct auth_generic_state *ans = NULL;
+       NTSTATUS status;
+       DNS_ERROR err;
+
+       status = auth_generic_client_prepare(mem_ctx, &ans);
+       if (!NT_STATUS_IS_OK(status)) {
+               err = ERROR_DNS_GSS_ERROR;
+               goto error;
+       }
+       talloc_steal(frame, ans);
+
+       status = auth_generic_set_creds(ans, creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               err = ERROR_DNS_GSS_ERROR;
+               goto error;
+       }
+
+       status = gensec_set_target_service(ans->gensec_security,
+                                          "dns");
+       if (!NT_STATUS_IS_OK(status)) {
+               err = ERROR_DNS_GSS_ERROR;
+               goto error;
+       }
+
+       status = gensec_set_target_hostname(ans->gensec_security,
+                                           pszServerName);
+       if (!NT_STATUS_IS_OK(status)) {
+               err = ERROR_DNS_GSS_ERROR;
+               goto error;
+       }
+
+       gensec_want_feature(ans->gensec_security, GENSEC_FEATURE_SIGN);
+
+       status = auth_generic_client_start(ans, GENSEC_OID_KERBEROS5);
+       if (!NT_STATUS_IS_OK(status)) {
+               err = ERROR_DNS_GSS_ERROR;
+               goto error;
+       }
+
+       err = dns_negotiate_sec_ctx(pszServerName,
+                                   keyname,
+                                   ans->gensec_security,
+                                   srv_type);
+       if (!ERR_DNS_IS_OK(err)) {
+               goto error;
+       }
+
+       *_gensec = talloc_move(mem_ctx, &ans->gensec_security);
+ error:
+       TALLOC_FREE(frame);
+
+       return err;
+}
+
 DNS_ERROR DoDNSUpdate(char *pszServerName,
                      const char *pszDomainName,
                      const char *pszHostName,
+                     struct cli_credentials *creds,
                      const struct sockaddr_storage *sslist,
                      size_t num_addrs,
                      uint32_t flags,
@@ -41,7 +107,6 @@ DNS_ERROR DoDNSUpdate(char *pszServerName,
        DNS_ERROR err;
        struct dns_connection *conn;
        TALLOC_CTX *mem_ctx;
-       OM_uint32 minor;
        struct dns_update_request *req, *resp;
 
        DEBUG(10,("DoDNSUpdate called with flags: 0x%08x\n", flags));
@@ -121,8 +186,8 @@ DNS_ERROR DoDNSUpdate(char *pszServerName,
         * Okay, we have to try with signing
         */
        if (flags & DNS_UPDATE_SIGNED) {
-               gss_ctx_id_t gss_context;
-               char *keyname;
+               struct gensec_security *gensec = NULL;
+               char *keyname = NULL;
 
                err = dns_create_update_request(mem_ctx,
                                                pszDomainName,
@@ -138,24 +203,31 @@ DNS_ERROR DoDNSUpdate(char *pszServerName,
                        goto error;
                }
 
-               err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
-                                            keyname, &gss_context, DNS_SRV_ANY );
+               err = DoDNSUpdateNegotiateGensec(pszServerName,
+                                                pszDomainName,
+                                                keyname,
+                                                DNS_SRV_ANY,
+                                                creds,
+                                                mem_ctx,
+                                                &gensec);
 
                /* retry using the Windows 2000 DNS hack */
                if (!ERR_DNS_IS_OK(err)) {
-                       err = dns_negotiate_sec_ctx( pszDomainName, pszServerName,
-                                                    keyname, &gss_context, 
-                                                    DNS_SRV_WIN2000 );
+                       err = DoDNSUpdateNegotiateGensec(pszServerName,
+                                                        pszDomainName,
+                                                        keyname,
+                                                        DNS_SRV_WIN2000,
+                                                        creds,
+                                                        mem_ctx,
+                                                        &gensec);
                }
 
                if (!ERR_DNS_IS_OK(err))
                        goto error;
 
-               err = dns_sign_update(req, gss_context, keyname,
+               err = dns_sign_update(req, gensec, keyname,
                                      "gss.microsoft.com", time(NULL), 3600);
 
-               gss_delete_sec_context(&minor, &gss_context, GSS_C_NO_BUFFER);
-
                if (!ERR_DNS_IS_OK(err)) goto error;
 
                err = dns_update_transaction(mem_ctx, conn, req, &resp);
index 4569e1c3328bd32f5121c051c468322826b6786e..508aff9d97add6e411a481dd53b4f3ab5f747a31 100644 (file)
 
 #include "../lib/addns/dns.h"
 
+struct cli_credentials;
+
 DNS_ERROR DoDNSUpdate(char *pszServerName,
                      const char *pszDomainName,
                      const char *pszHostName,
+                     struct cli_credentials *creds,
                      const struct sockaddr_storage *sslist,
                      size_t num_addrs,
                      uint32_t flags,
index ccfa89ae105487c8d10e5352bf83c0995048bf4d..cabbc751aaf21181ba22dee5e79b9737397c7a1f 100644 (file)
@@ -57,7 +57,9 @@ int net_ads(struct net_context *c, int argc, const char **argv);
 /* The following definitions come from utils/net_ads_join_dns.c  */
 void use_in_memory_ccache(void);
 NTSTATUS net_update_dns_ext(struct net_context *c,
-                           TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
+                           TALLOC_CTX *mem_ctx,
+                           ADS_STRUCT *ads,
+                           struct cli_credentials *creds,
                            const char *hostname,
                            struct sockaddr_storage *iplist,
                            int num_addrs, bool remove_host);