r19266: Add a target_hostname element to the binding struct. This allows us
authorAndrew Bartlett <abartlet@samba.org>
Fri, 13 Oct 2006 13:01:48 +0000 (13:01 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:21:00 +0000 (14:21 -0500)
to perform a lookup once, resolve the name to an IP, while still
communicating the full name to the lower layers, for kerberos etc.

This fixes 'net samdump', which was failing due to the schannel target
name being *smbserver.

Andrew Bartlett
(This used to be commit 0546f487f4cc99b5549dc1e457ea243d4bd66333)

source4/libnet/libnet_join.c
source4/libnet/libnet_rpc.c
source4/libnet/libnet_rpc.h
source4/librpc/rpc/dcerpc.h
source4/librpc/rpc/dcerpc_connect.c
source4/librpc/rpc/dcerpc_sock.c
source4/librpc/rpc/dcerpc_util.c
source4/torture/rpc/async_bind.c

index 5781bc19c28ebc3765572a080b3ce20c20175fc0..57ecddd9daaff906f2220c385ce4c30401235939 100644 (file)
@@ -229,7 +229,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J
        /* Now we know the user's DN, open with LDAP, read and modify a few things */
 
        remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", 
-                                        drsuapi_binding->host);
+                                        drsuapi_binding->target_hostname);
        if (!remote_ldb_url) {
                r->out.error_string = NULL;
                talloc_free(tmp_ctx);
index 53c8ba86a19f942afefc584e4ad16ba47de82fc7..cedd0d07c0d5842bd3995e245cab61f00973b665 100644 (file)
@@ -53,6 +53,7 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
 {
        struct composite_context *c;    
        struct rpc_connect_srv_state *s;
+       struct dcerpc_binding *b;
        struct composite_context *pipe_connect_req;
 
        /* composite context allocation and setup */
@@ -72,16 +73,21 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
 
        /* prepare binding string */
        switch (r->level) {
-       case LIBNET_RPC_CONNECT_DC:
-       case LIBNET_RPC_CONNECT_PDC:
        case LIBNET_RPC_CONNECT_SERVER:
                s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name);
                break;
+       case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
+               s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.address);
+               break;
 
        case LIBNET_RPC_CONNECT_BINDING:
                s->binding = talloc_strdup(s, r->in.binding);
                break;
 
+       case LIBNET_RPC_CONNECT_DC:
+       case LIBNET_RPC_CONNECT_PDC:
+               /* this should never happen - DC and PDC level has a separate
+                  composite function */
        case LIBNET_RPC_CONNECT_DC_INFO:
                /* this should never happen - DC_INFO level has a separate
                   composite function */
@@ -89,9 +95,23 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
                return c;
        }
 
+       /* parse binding string to the structure */
+       c->status = dcerpc_parse_binding(c, s->binding, &b);
+       if (!NT_STATUS_IS_OK(c->status)) {
+               DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", s->binding));
+               composite_error(c, c->status);
+               return c;
+       }
+
+       if (r->level == LIBNET_RPC_CONNECT_SERVER_ADDRESS) {
+               b->target_hostname = talloc_reference(b, r->in.name);
+               if (composite_nomem(b->target_hostname, c)) {
+                       return c;
+               }
+       }
+
        /* connect to remote dcerpc pipe */
-       pipe_connect_req = dcerpc_pipe_connect_send(c, &s->r.out.dcerpc_pipe,
-                                                   s->binding, r->in.dcerpc_iface,
+       pipe_connect_req = dcerpc_pipe_connect_b_send(c, b, r->in.dcerpc_iface,
                                                    ctx->cred, c->event_ctx);
        if (composite_nomem(pipe_connect_req, c)) return c;
 
@@ -112,7 +132,7 @@ static void continue_pipe_connect(struct composite_context *ctx)
        s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
 
        /* receive result of rpc pipe connection */
-       c->status = dcerpc_pipe_connect_recv(ctx, c, &s->r.out.dcerpc_pipe);
+       c->status = dcerpc_pipe_connect_b_recv(ctx, c, &s->r.out.dcerpc_pipe);
 
        s->r.out.error_string = NULL;
        composite_done(c);
@@ -237,7 +257,7 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context
 
 
 /*
-  Step 2 of RpcConnectDC: get domain controller name/address and
+  Step 2 of RpcConnectDC: get domain controller name and
   initiate RpcConnect to it
 */
 static void continue_lookup_dc(struct composite_context *ctx)
@@ -256,19 +276,7 @@ static void continue_lookup_dc(struct composite_context *ctx)
        if (!composite_is_ok(c)) return;
 
        /* decide on preferred address type depending on DC type */
-       switch (s->r.level) {
-       case LIBNET_RPC_CONNECT_PDC:
-               s->connect_name = s->f.out.dcs[0].name;
-               break;
-
-       case LIBNET_RPC_CONNECT_DC:
-               s->connect_name = s->f.out.dcs[0].address;
-               break;
-
-       default:
-               /* we shouldn't absolutely get here */
-               composite_error(c, NT_STATUS_INVALID_LEVEL);
-       }
+       s->connect_name = s->f.out.dcs[0].name;
 
        /* prepare a monitor message and post it */
        msg.type         = net_lookup_dc;
@@ -282,11 +290,12 @@ static void continue_lookup_dc(struct composite_context *ctx)
        if (s->monitor_fn) s->monitor_fn(&msg);
 
        /* ok, pdc has been found so do attempt to rpc connect */
-       s->r2.level            = s->r.level;
+       s->r2.level            = LIBNET_RPC_CONNECT_SERVER_ADDRESS;
 
        /* this will cause yet another name resolution, but at least
         * we pass the right name down the stack now */
-       s->r2.in.name          = talloc_strdup(c, s->connect_name);
+       s->r2.in.name          = talloc_strdup(s, s->connect_name);
+       s->r2.in.address       = talloc_steal(s, s->f.out.dcs[0].address);
        s->r2.in.dcerpc_iface  = s->r.in.dcerpc_iface;  
 
        /* send rpc connect request to the server */
@@ -630,7 +639,7 @@ static void continue_lsa_query_info(struct rpc_request *req)
        
        *s->final_binding = *s->lsa_pipe->binding;
        /* Ensure we keep hold of the member elements */
-       talloc_reference(s->final_binding, s->lsa_pipe->binding);
+       if (composite_nomem(talloc_reference(s->final_binding, s->lsa_pipe->binding), c)) return;
 
        epm_map_req = dcerpc_epm_map_binding_send(c, s->final_binding, s->r.in.dcerpc_iface,
                                                  s->lsa_pipe->conn->event_ctx);
@@ -735,7 +744,11 @@ static NTSTATUS libnet_RpcConnectDCInfo_recv(struct composite_context *c, struct
                }
 
        } else {
-               r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
+               if (s->r.out.error_string) {
+                       r->out.error_string = talloc_steal(mem_ctx, s->r.out.error_string);
+               } else {
+                       r->out.error_string = talloc_asprintf(mem_ctx, "Connection to DC failed: %s", nt_errstr(status));
+               }
        }
 
        talloc_free(c);
@@ -761,6 +774,7 @@ struct composite_context* libnet_RpcConnect_send(struct libnet_context *ctx,
 
        switch (r->level) {
        case LIBNET_RPC_CONNECT_SERVER:
+       case LIBNET_RPC_CONNECT_SERVER_ADDRESS:
        case LIBNET_RPC_CONNECT_BINDING:
                c = libnet_RpcConnectSrv_send(ctx, mem_ctx, r);
                break;
index 178e1cc269ed8a3958e7f312a03cde3aa88c02e8..2663cec86911e34daa30897c2afff3c209542683 100644 (file)
  */
 
 enum libnet_RpcConnect_level {
-       LIBNET_RPC_CONNECT_SERVER,       /* connect to a standalone rpc server */
-       LIBNET_RPC_CONNECT_PDC,          /* connect to a domain pdc (resolves domain
-                                           name to a pdc address before connecting) */
-       LIBNET_RPC_CONNECT_DC,           /* connect to any DC (resolves domain
-                                           name to a DC address before connecting) */
-       LIBNET_RPC_CONNECT_BINDING,      /* specified binding string */
-       LIBNET_RPC_CONNECT_DC_INFO       /* connect to a DC and provide basic domain
-                                           information (name, realm, sid, guid) */
+       LIBNET_RPC_CONNECT_SERVER,          /* connect to a standalone rpc server */
+       LIBNET_RPC_CONNECT_SERVER_ADDRESS,  /* connect to a standalone rpc server, 
+                                              knowing both name and address */
+       LIBNET_RPC_CONNECT_PDC,             /* connect to a domain pdc (resolves domain
+                                              name to a pdc address before connecting) */
+       LIBNET_RPC_CONNECT_DC,              /* connect to any DC (resolves domain
+                                              name to a DC address before connecting) */
+       LIBNET_RPC_CONNECT_BINDING,         /* specified binding string */
+       LIBNET_RPC_CONNECT_DC_INFO          /* connect to a DC and provide basic domain
+                                              information (name, realm, sid, guid) */
 };
 
 struct libnet_RpcConnect {
@@ -41,6 +43,7 @@ struct libnet_RpcConnect {
 
        struct {
                const char *name;
+               const char *address;
                const char *binding;
                const struct dcerpc_interface_table *dcerpc_iface;
        } in;
index a609d17795f770e1ccdc3b4a1da97b4bb64ac0b2..6bde842371d6d4b55c98adc50ff646165536f025 100644 (file)
@@ -193,6 +193,7 @@ struct dcerpc_binding {
        enum dcerpc_transport_t transport;
        struct dcerpc_syntax_id object;
        const char *host;
+       const char *target_hostname;
        const char *endpoint;
        const char **options;
        uint32_t flags;
index fba0ae0c02456f88bd0759032547e2b1188be542..c35da23f58c0b2590e4882a7e791c77b3fdd3759 100644 (file)
@@ -111,14 +111,11 @@ struct composite_context *dcerpc_pipe_connect_ncacn_np_smb_send(TALLOC_CTX *mem_
           remote rpc server */
        conn->in.dest_host              = s->io.binding->host;
        conn->in.port                   = 0;
-       conn->in.called_name            = strupper_talloc(mem_ctx, s->io.binding->host);
+       conn->in.called_name            = s->io.binding->target_hostname;
        conn->in.service                = "IPC$";
        conn->in.service_type           = NULL;
        conn->in.workgroup              = lp_workgroup();
 
-       /* verify if called_name has been allocated when uppercasing */
-       if (composite_nomem(conn->in.called_name, c)) return c;
-
        /*
         * provide proper credentials - user supplied, but allow a
         * fallback to anonymous if this is an schannel connection
@@ -281,6 +278,7 @@ NTSTATUS dcerpc_pipe_connect_ncacn_np_smb2(TALLOC_CTX *mem_ctx,
 struct pipe_ip_tcp_state {
        struct dcerpc_pipe_connect io;
        const char *host;
+       const char *target_hostname;
        uint32_t port;
 };
 
@@ -321,12 +319,15 @@ struct composite_context* dcerpc_pipe_connect_ncacn_ip_tcp_send(TALLOC_CTX *mem_
        c->private_data = s;
 
        /* store input parameters in state structure */
-       s->io    = *io;
-       s->host  = talloc_strdup(c, io->binding->host);
-       s->port  = atoi(io->binding->endpoint);   /* port number is a binding endpoint here */
+       s->io               = *io;
+       s->host             = talloc_reference(c, io->binding->host);
+       s->target_hostname  = talloc_reference(c, io->binding->target_hostname);
+                             /* port number is a binding endpoint here */
+       s->port             = atoi(io->binding->endpoint);   
 
        /* send pipe open request on tcp/ip */
-       pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->port);
+       pipe_req = dcerpc_pipe_open_tcp_send(s->io.pipe->conn, s->host, s->target_hostname, 
+                                            s->port);
        composite_continue(c, pipe_req, continue_pipe_open_ncacn_ip_tcp, c);
        return c;
 }
@@ -822,10 +823,11 @@ NTSTATUS dcerpc_pipe_connect_b_recv(struct composite_context *c, TALLOC_CTX *mem
        
        status = composite_wait(c);
        
-       s = talloc_get_type(c->private_data, struct pipe_connect_state);
-       talloc_steal(mem_ctx, s->pipe);
-       *p = s->pipe;
-
+       if (NT_STATUS_IS_OK(status)) {
+               s = talloc_get_type(c->private_data, struct pipe_connect_state);
+               talloc_steal(mem_ctx, s->pipe);
+               *p = s->pipe;
+       }
        talloc_free(c);
        return status;
 }
@@ -864,7 +866,6 @@ static void continue_pipe_connect_b(struct composite_context *ctx);
   The string is to be parsed to a binding structure first.
 */
 struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_ctx,
-                                                  struct dcerpc_pipe **pp,
                                                   const char *binding,
                                                   const struct dcerpc_interface_table *table,
                                                   struct cli_credentials *credentials,
@@ -966,7 +967,8 @@ NTSTATUS dcerpc_pipe_connect(TALLOC_CTX *parent_ctx,
                             struct event_context *ev)
 {
        struct composite_context *c;
-       c = dcerpc_pipe_connect_send(parent_ctx, pp, binding, table,
+       c = dcerpc_pipe_connect_send(parent_ctx, binding, 
+                                    table,
                                     credentials, ev);
        return dcerpc_pipe_connect_recv(c, parent_ctx, pp);
 }
@@ -1032,6 +1034,7 @@ struct composite_context* dcerpc_secondary_connection_send(struct dcerpc_pipe *p
        case NCACN_IP_TCP:
                pipe_tcp_req = dcerpc_pipe_open_tcp_send(s->pipe2->conn,
                                                         s->binding->host,
+                                                        s->binding->target_hostname,
                                                         atoi(s->binding->endpoint));
                composite_continue(c, pipe_tcp_req, continue_open_tcp, c);
                return c;
index 88e8381608a94067e26e73aed8835dc2ce55ac00..2cd6fcfb4c1873fecfd9a124f7a952aba583c91e 100644 (file)
@@ -206,6 +206,7 @@ struct pipe_open_socket_state {
        struct socket_context *socket_ctx;
        struct sock_private *sock;
        struct socket_address *server;
+       const char *target_hostname;
        enum dcerpc_transport_t transport;
 };
 
@@ -248,7 +249,7 @@ static void continue_socket_connect(struct composite_context *ctx)
 
        sock->sock          = s->socket_ctx;
        sock->pending_reads = 0;
-       sock->server_name   = strupper_talloc(sock, s->server->addr);
+       sock->server_name   = strupper_talloc(sock, s->target_hostname);
 
        sock->fde = event_add_fd(conn->event_ctx, sock->sock, socket_get_fd(sock->sock),
                                 0, sock_io_handler, conn);
@@ -283,6 +284,7 @@ static void continue_socket_connect(struct composite_context *ctx)
 struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,
                                                       struct dcerpc_connection *cn,
                                                       struct socket_address *server,
+                                                      const char *target_hostname,
                                                       enum dcerpc_transport_t transport)
 {
        struct composite_context *c;
@@ -300,6 +302,7 @@ struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,
        s->transport = transport;
        s->server    = talloc_reference(c, server);
        if (composite_nomem(s->server, c)) return c;
+       s->target_hostname = talloc_reference(s, target_hostname);
 
        s->sock = talloc(cn, struct sock_private);
        if (composite_nomem(s->sock, c)) return c;
@@ -328,17 +331,19 @@ NTSTATUS dcerpc_pipe_open_socket_recv(struct composite_context *c)
 */
 NTSTATUS dcerpc_pipe_open_socket(struct dcerpc_connection *conn,
                                 struct socket_address *server,
+                                const char *target_hostname,
                                 enum dcerpc_transport_t transport)
 {
        struct composite_context *c;
        
-       c = dcerpc_pipe_open_socket_send(conn, conn, server, transport);
+       c = dcerpc_pipe_open_socket_send(conn, conn, server, target_hostname, transport);
        return dcerpc_pipe_open_socket_recv(c);
 }
 
 
 struct pipe_tcp_state {
-       const char *server;
+       const char *target_hostname;
+       const char *address;
        uint32_t port;
        struct socket_address *srvaddr;
        struct dcerpc_connection *conn;
@@ -371,11 +376,13 @@ void continue_ipv6_open_socket(struct composite_context *ctx)
        talloc_free(s->srvaddr);
 
        /* prepare server address using host:ip and transport name */
-       s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->server, s->port);
+       s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->address, s->port);
        if (composite_nomem(s->srvaddr, c)) return;
 
        /* try IPv4 if IPv6 fails */
-       sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCACN_IP_TCP);
+       sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, 
+                                                    s->srvaddr, s->target_hostname, 
+                                                    NCACN_IP_TCP);
        composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c);
 }
 
@@ -395,8 +402,9 @@ void continue_ipv4_open_socket(struct composite_context *ctx)
        c->status = dcerpc_pipe_open_socket_recv(ctx);
        if (!NT_STATUS_IS_OK(c->status)) {
                /* something went wrong... */
-               DEBUG(0, ("Failed to connect host %s on port %d - %s.\n",
-                         s->server, s->port, nt_errstr(c->status)));
+               DEBUG(0, ("Failed to connect host %s (%s) on port %d - %s.\n",
+                         s->address, s->target_hostname, 
+                         s->port, nt_errstr(c->status)));
 
                composite_error(c, c->status);
                return;
@@ -411,7 +419,9 @@ void continue_ipv4_open_socket(struct composite_context *ctx)
   tcp/ip transport
 */
 struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *conn,
-                                                   const char* server, uint32_t port)
+                                                   const char *address, 
+                                                   const char *target_hostname,
+                                                   uint32_t port)
 {
        struct composite_context *c;
        struct composite_context *sock_ipv6_req;
@@ -426,16 +436,19 @@ struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *co
        c->private_data = s;
 
        /* store input parameters in state structure */
-       s->server = talloc_strdup(c, server);
-       s->port   = port;
-       s->conn   = conn;
+       s->address         = talloc_strdup(c, address);
+       s->target_hostname = talloc_strdup(c, target_hostname);
+       s->port            = port;
+       s->conn            = conn;
        
        /* prepare server address using host ip:port and transport name */
-       s->srvaddr = socket_address_from_strings(s->conn, "ipv6", s->server, s->port);
+       s->srvaddr = socket_address_from_strings(s->conn, "ipv6", address, s->port);
        if (composite_nomem(s->srvaddr, c)) return c;
 
        /* try IPv6 first - send socket open request */
-       sock_ipv6_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCACN_IP_TCP);
+       sock_ipv6_req = dcerpc_pipe_open_socket_send(c, s->conn, 
+                                                    s->srvaddr, s->target_hostname,
+                                                    NCACN_IP_TCP);
        composite_continue(c, sock_ipv6_req, continue_ipv6_open_socket, c);
        return c;
 }
@@ -458,11 +471,12 @@ NTSTATUS dcerpc_pipe_open_tcp_recv(struct composite_context *c)
   Open rpc pipe on tcp/ip transport - sync version
 */
 NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_connection *conn, const char *server,
+                             const char *target_hostname,
                              uint32_t port)
 {
        struct composite_context *c;
 
-       c = dcerpc_pipe_open_tcp_send(conn, server, port);
+       c = dcerpc_pipe_open_tcp_send(conn, server, target_hostname, port);
        return dcerpc_pipe_open_tcp_recv(c);
 }
 
@@ -521,7 +535,9 @@ struct composite_context *dcerpc_pipe_open_unix_stream_send(struct dcerpc_connec
        if (composite_nomem(s->srvaddr, c)) return c;
 
        /* send socket open request */
-       sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCALRPC);
+       sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, 
+                                                    s->srvaddr, NULL,
+                                                    NCALRPC);
        composite_continue(c, sock_unix_req, continue_unix_open_socket, c);
        return c;
 }
@@ -605,7 +621,7 @@ struct composite_context* dcerpc_pipe_open_pipe_send(struct dcerpc_connection *c
        if (composite_nomem(s->srvaddr, c)) return c;
 
        /* send socket open request */
-       sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NCALRPC);
+       sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NULL, NCALRPC);
        composite_continue(c, sock_np_req, continue_np_open_socket, c);
        return c;
 }
index 73e11f10f0c105226bfd2bc4694ddadbde5831e3..bdc0f8f6c5bed00f0ba5b72bbf6778ff47e0021e 100644 (file)
@@ -358,11 +358,12 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_
                b->host = talloc_strdup(b, s);
                options = NULL;
        }
-
        if (!b->host) {
                return NT_STATUS_NO_MEMORY;
        }
 
+       b->target_hostname = b->host;
+
        b->options = NULL;
        b->flags = 0;
        b->endpoint = NULL;
index 18ed139ac79c7ff8a80c62f4763b03e4fb7810cf..952baacbf48f434a3558ffe61808ac66cd9147ae 100644 (file)
@@ -78,7 +78,7 @@ BOOL torture_async_bind(struct torture_context *torture)
        /* send bind requests */
        for (i = 0; i < torture_numasync; i++) {
                table[i] = &dcerpc_table_lsarpc;
-               bind_req[i] = dcerpc_pipe_connect_send(mem_ctx, &pipe[i], binding_string,
+               bind_req[i] = dcerpc_pipe_connect_send(mem_ctx, binding_string,
                                                       table[i], creds, evt_ctx);
        }