s3: make cli_resolve_path return NTSTATUS
[kai/samba.git] / source3 / libsmb / cliconnect.c
index 1383978c9177c634cf6d6141cf63cb198d254914..62e3a35a3693605250d75cd69997d3a56ab5572b 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 #include "includes.h"
+#include "libsmb/libsmb.h"
 #include "popt_common.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "../libcli/auth/spnego.h"
@@ -31,6 +32,7 @@
 #include "../lib/util/tevent_ntstatus.h"
 #include "async_smb.h"
 #include "libsmb/nmblib.h"
+#include "read_smb.h"
 
 static const struct {
        int prot;
@@ -258,8 +260,10 @@ static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
        uint8_t *p;
        NTSTATUS status;
        ssize_t ret;
+       uint8_t wct;
+       uint16_t *vwv;
 
-       status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+       status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
                              &num_bytes, &bytes);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
@@ -271,6 +275,7 @@ static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
        p = bytes;
 
        cli->vuid = SVAL(inbuf, smb_uid);
+       cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
 
        status = smb_bytes_talloc_string(cli,
                                        inbuf,
@@ -357,9 +362,6 @@ static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *use
        status = cli_session_setup_lanman2_recv(req);
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -486,8 +488,10 @@ static void cli_session_setup_guest_done(struct tevent_req *subreq)
        uint8_t *p;
        NTSTATUS status;
        ssize_t ret;
+       uint8_t wct;
+       uint16_t *vwv;
 
-       status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+       status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
                              &num_bytes, &bytes);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
@@ -499,6 +503,7 @@ static void cli_session_setup_guest_done(struct tevent_req *subreq)
        p = bytes;
 
        cli->vuid = SVAL(inbuf, smb_uid);
+       cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
 
        status = smb_bytes_talloc_string(cli,
                                        inbuf,
@@ -591,9 +596,6 @@ static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
        status = cli_session_setup_guest_recv(req);
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -694,8 +696,10 @@ static void cli_session_setup_plain_done(struct tevent_req *subreq)
        uint8_t *p;
        NTSTATUS status;
        ssize_t ret;
+       uint8_t wct;
+       uint16_t *vwv;
 
-       status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+       status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
                              &num_bytes, &bytes);
        TALLOC_FREE(subreq);
        if (tevent_req_nterror(req, status)) {
@@ -706,6 +710,7 @@ static void cli_session_setup_plain_done(struct tevent_req *subreq)
        p = bytes;
 
        cli->vuid = SVAL(inbuf, smb_uid);
+       cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
 
        status = smb_bytes_talloc_string(cli,
                                        inbuf,
@@ -792,9 +797,6 @@ static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
        status = cli_session_setup_plain_recv(req);
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -1050,8 +1052,10 @@ static void cli_session_setup_nt1_done(struct tevent_req *subreq)
        uint8_t *p;
        NTSTATUS status;
        ssize_t ret;
+       uint8_t wct;
+       uint16_t *vwv;
 
-       status = cli_smb_recv(subreq, state, &in, 0, NULL, NULL,
+       status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
                              &num_bytes, &bytes);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1063,6 +1067,7 @@ static void cli_session_setup_nt1_done(struct tevent_req *subreq)
        p = bytes;
 
        cli->vuid = SVAL(inbuf, smb_uid);
+       cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
 
        status = smb_bytes_talloc_string(cli,
                                        inbuf,
@@ -1157,9 +1162,6 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
        status = cli_session_setup_nt1_recv(req);
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -1290,7 +1292,7 @@ static void cli_sesssetup_blob_done(struct tevent_req *subreq)
        uint8_t *inbuf;
        ssize_t ret;
 
-       status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
+       status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
                              &num_bytes, &bytes);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)
@@ -1304,6 +1306,7 @@ static void cli_sesssetup_blob_done(struct tevent_req *subreq)
 
        state->inbuf = (char *)inbuf;
        cli->vuid = SVAL(state->inbuf, smb_uid);
+       cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
 
        blob_length = SVAL(vwv+3, 0);
        if (blob_length > num_bytes) {
@@ -1362,7 +1365,7 @@ static void cli_sesssetup_blob_done(struct tevent_req *subreq)
                 * More to send
                 */
                if (!cli_sesssetup_blob_next(state, &subreq)) {
-                       tevent_req_nomem(NULL, req);
+                       tevent_req_oom(req);
                        return;
                }
                tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
@@ -1422,7 +1425,7 @@ static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
 
 static struct tevent_req *cli_session_setup_kerberos_send(
        TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
-       const char *principal, const char *workgroup)
+       const char *principal)
 {
        struct tevent_req *req, *subreq;
        struct cli_session_setup_kerberos_state *state;
@@ -1510,8 +1513,7 @@ static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
 }
 
 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
-                                            const char *principal,
-                                            const char *workgroup)
+                                            const char *principal)
 {
        struct tevent_context *ev;
        struct tevent_req *req;
@@ -1524,8 +1526,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
        if (ev == NULL) {
                goto fail;
        }
-       req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
-                                             workgroup);
+       req = cli_session_setup_kerberos_send(ev, ev, cli, principal);
        if (req == NULL) {
                goto fail;
        }
@@ -1589,7 +1590,7 @@ static struct tevent_req *cli_session_setup_ntlmssp_send(
        cli_temp_set_signing(cli);
 
        status = ntlmssp_client_start(state,
-                                     global_myname(),
+                                     lp_netbios_name(),
                                      lp_workgroup(),
                                      lp_client_ntlmv2_auth(),
                                      &state->ntlmssp_state);
@@ -1774,9 +1775,6 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
        status = cli_session_setup_ntlmssp_recv(req);
 fail:
        TALLOC_FREE(ev);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -1886,6 +1884,9 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
                        host = strchr_m(cli->desthost, '.');
                        if (dest_realm) {
                                realm = SMB_STRDUP(dest_realm);
+                               if (!realm) {
+                                       return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+                               }
                                strupper_m(realm);
                        } else {
                                if (host) {
@@ -1897,25 +1898,38 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
                                }
                        }
 
-                       if (realm && *realm) {
-                               principal = talloc_asprintf(talloc_tos(),
-                                                           "cifs/%s@%s",
-                                                           cli->desthost,
-                                                           realm);
-                               if (!principal) {
-                                       SAFE_FREE(realm);
+                       if (realm == NULL || *realm == '\0') {
+                               realm = SMB_STRDUP(lp_realm());
+                               if (!realm) {
                                        return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
                                }
-                               DEBUG(3,("cli_session_setup_spnego: guessed "
-                                       "server principal=%s\n",
-                                       principal ? principal : "<null>"));
+                               strupper_m(realm);
+                               DEBUG(3,("cli_session_setup_spnego: cannot "
+                                       "get realm from dest_realm %s, "
+                                       "desthost %s. Using default "
+                                       "smb.conf realm %s\n",
+                                       dest_realm ? dest_realm : "<null>",
+                                       cli->desthost,
+                                       realm));
                        }
+
+                       principal = talloc_asprintf(talloc_tos(),
+                                                   "cifs/%s@%s",
+                                                   cli->desthost,
+                                                   realm);
+                       if (!principal) {
+                               SAFE_FREE(realm);
+                               return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+                       }
+                       DEBUG(3,("cli_session_setup_spnego: guessed "
+                               "server principal=%s\n",
+                               principal ? principal : "<null>"));
+
                        SAFE_FREE(realm);
                }
 
                if (principal) {
-                       rc = cli_session_setup_kerberos(cli, principal,
-                               dest_realm);
+                       rc = cli_session_setup_kerberos(cli, principal);
                        if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
                                TALLOC_FREE(principal);
                                return rc;
@@ -1976,6 +1990,7 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
            (p=strchr_m(user2,*lp_winbind_separator()))) {
                *p = 0;
                user = p+1;
+               strupper_m(user2);
                workgroup = user2;
        }
 
@@ -2143,9 +2158,6 @@ NTSTATUS cli_ulogoff(struct cli_state *cli)
        status = cli_ulogoff_recv(req);
 fail:
        TALLOC_FREE(ev);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -2439,9 +2451,6 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
        status = cli_tcon_andx_recv(req);
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -2522,9 +2531,6 @@ NTSTATUS cli_tdis(struct cli_state *cli)
        status = cli_tdis_recv(req);
 fail:
        TALLOC_FREE(ev);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
@@ -2653,11 +2659,14 @@ static void cli_negprot_done(struct tevent_req *subreq)
                }
                /* work out if they sent us a workgroup */
                if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
-                   smb_buflen(cli->inbuf) > 8) {
-                       clistr_pull(cli->inbuf, cli->server_domain,
-                                   bytes+8, sizeof(cli->server_domain),
-                                   num_bytes-8,
-                                   STR_UNICODE|STR_NOALIGN);
+                   smb_buflen(inbuf) > 8) {
+                       ssize_t ret;
+                       status = smb_bytes_talloc_string(
+                               cli, (char *)inbuf, &cli->server_domain,
+                               bytes + 8, num_bytes - 8, &ret);
+                       if (tevent_req_nterror(req, status)) {
+                               return;
+                       }
                }
 
                /*
@@ -2774,309 +2783,141 @@ NTSTATUS cli_negprot(struct cli_state *cli)
        status = cli_negprot_recv(req);
  fail:
        TALLOC_FREE(frame);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_set_error(cli, status);
-       }
        return status;
 }
 
-/****************************************************************************
- Send a session request. See rfc1002.txt 4.3 and 4.3.2.
-****************************************************************************/
-
-bool cli_session_request(struct cli_state *cli,
-                        struct nmb_name *calling, struct nmb_name *called)
+static NTSTATUS cli_connect_sock(const char *host, int name_type,
+                                const struct sockaddr_storage *pss,
+                                const char *myname, uint16_t port,
+                                int sec_timeout, int *pfd, uint16_t *pport)
 {
-       char *p;
-       int len = 4;
-       int namelen = 0;
-       char *tmp;
-
-       /* 445 doesn't have session request */
-       if (cli->port == 445)
-               return True;
-
-       memcpy(&(cli->calling), calling, sizeof(*calling));
-       memcpy(&(cli->called ), called , sizeof(*called ));
-
-       /* put in the destination name */
-
-       tmp = name_mangle(talloc_tos(), cli->called.name,
-                         cli->called.name_type);
-       if (tmp == NULL) {
-               return false;
-       }
-
-       p = cli->outbuf+len;
-       namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
-       if (namelen > 0) {
-               memcpy(p, tmp, namelen);
-               len += namelen;
-       }
-       TALLOC_FREE(tmp);
-
-       /* and my name */
-
-       tmp = name_mangle(talloc_tos(), cli->calling.name,
-                         cli->calling.name_type);
-       if (tmp == NULL) {
-               return false;
-       }
-
-       p = cli->outbuf+len;
-       namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
-       if (namelen > 0) {
-               memcpy(p, tmp, namelen);
-               len += namelen;
-       }
-       TALLOC_FREE(tmp);
-
-       /* send a session request (RFC 1002) */
-       /* setup the packet length
-         * Remove four bytes from the length count, since the length
-         * field in the NBT Session Service header counts the number
-         * of bytes which follow.  The cli_send_smb() function knows
-         * about this and accounts for those four bytes.
-         * CRH.
-         */
-        len -= 4;
-       _smb_setlen(cli->outbuf,len);
-       SCVAL(cli->outbuf,0,0x81);
-
-       cli_send_smb(cli);
-       DEBUG(5,("Sent session request\n"));
-
-       if (!cli_receive_smb(cli))
-               return False;
-
-       if (CVAL(cli->inbuf,0) == 0x84) {
-               /* C. Hoch  9/14/95 Start */
-               /* For information, here is the response structure.
-                * We do the byte-twiddling to for portability.
-               struct RetargetResponse{
-               unsigned char type;
-               unsigned char flags;
-               int16 length;
-               int32 ip_addr;
-               int16 port;
-               };
-               */
-               uint16_t port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
-               struct in_addr dest_ip;
-               NTSTATUS status;
-
-               /* SESSION RETARGET */
-               putip((char *)&dest_ip,cli->inbuf+4);
-               in_addr_to_sockaddr_storage(&cli->dest_ss, dest_ip);
-
-               status = open_socket_out(&cli->dest_ss, port,
-                                        LONG_CONNECT_TIMEOUT, &cli->fd);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return False;
-               }
-
-               DEBUG(3,("Retargeted\n"));
-
-               set_socket_options(cli->fd, lp_socket_options());
-
-               /* Try again */
-               {
-                       static int depth;
-                       bool ret;
-                       if (depth > 4) {
-                               DEBUG(0,("Retarget recursion - failing\n"));
-                               return False;
-                       }
-                       depth++;
-                       ret = cli_session_request(cli, calling, called);
-                       depth--;
-                       return ret;
-               }
-       } /* C. Hoch 9/14/95 End */
-
-       if (CVAL(cli->inbuf,0) != 0x82) {
-                /* This is the wrong place to put the error... JRA. */
-               cli->rap_error = CVAL(cli->inbuf,4);
-               return False;
-       }
-       return(True);
-}
-
-struct fd_struct {
-       int fd;
-};
-
-static void smb_sock_connected(struct tevent_req *req)
-{
-       struct fd_struct *pfd = tevent_req_callback_data(
-               req, struct fd_struct);
-       int fd;
+       TALLOC_CTX *frame = talloc_stackframe();
+       const char *prog;
+       unsigned int i, num_addrs;
+       const char **called_names;
+       const char **calling_names;
+       int *called_types;
        NTSTATUS status;
+       int fd;
 
-       status = open_socket_out_defer_recv(req, &fd);
-       if (NT_STATUS_IS_OK(status)) {
-               pfd->fd = fd;
-       }
-}
-
-static NTSTATUS open_smb_socket(const struct sockaddr_storage *pss,
-                               uint16_t *port, int timeout, int *pfd)
-{
-       struct event_context *ev;
-       struct tevent_req *r139, *r445;
-       struct fd_struct *fd139, *fd445;
-       NTSTATUS status = NT_STATUS_NO_MEMORY;
-
-       if (*port != 0) {
-               return open_socket_out(pss, *port, timeout, pfd);
-       }
-
-       ev = event_context_init(talloc_tos());
-       if (ev == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       fd139 = talloc(ev, struct fd_struct);
-       if (fd139 == NULL) {
+       prog = getenv("LIBSMB_PROG");
+       if (prog != NULL) {
+               fd = sock_exec(prog);
+               if (fd == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
+               port = 0;
                goto done;
        }
-       fd139->fd = -1;
 
-       fd445 = talloc(ev, struct fd_struct);
-       if (fd445 == NULL) {
-               goto done;
+       if ((pss == NULL) || is_zero_addr(pss)) {
+               struct sockaddr_storage *addrs;
+               status = resolve_name_list(talloc_tos(), host, name_type,
+                                          &addrs, &num_addrs);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto fail;
+               }
+               pss = addrs;
+       } else {
+               num_addrs = 1;
        }
-       fd445->fd = -1;
 
-       r445 = open_socket_out_defer_send(ev, ev, timeval_set(0, 0),
-                                         pss, 445, timeout);
-       r139 = open_socket_out_defer_send(ev, ev, timeval_set(0, 3000),
-                                         pss, 139, timeout);
-       if ((r445 == NULL) || (r139 == NULL)) {
-               goto done;
+       called_names = talloc_array(talloc_tos(), const char *, num_addrs);
+       if (called_names == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
        }
-       tevent_req_set_callback(r445, smb_sock_connected, fd445);
-       tevent_req_set_callback(r139, smb_sock_connected, fd139);
-
-       while ((fd445->fd == -1) && (fd139->fd == -1)
-              && (tevent_req_is_in_progress(r139)
-                  || tevent_req_is_in_progress(r445))) {
-               event_loop_once(ev);
+       called_types = talloc_array(talloc_tos(), int, num_addrs);
+       if (called_types == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
        }
-
-       if ((fd139->fd != -1) && (fd445->fd != -1)) {
-               close(fd139->fd);
-               fd139->fd = -1;
+       calling_names = talloc_array(talloc_tos(), const char *, num_addrs);
+       if (calling_names == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto fail;
        }
-
-       if (fd445->fd != -1) {
-               *port = 445;
-               *pfd = fd445->fd;
-               status = NT_STATUS_OK;
-               goto done;
+       for (i=0; i<num_addrs; i++) {
+               called_names[i] = host;
+               called_types[i] = name_type;
+               calling_names[i] = myname;
        }
-       if (fd139->fd != -1) {
-               *port = 139;
-               *pfd = fd139->fd;
-               status = NT_STATUS_OK;
-               goto done;
+       status = smbsock_any_connect(pss, called_names, called_types,
+                                    calling_names, NULL, num_addrs, port,
+                                    sec_timeout, &fd, NULL, &port);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto fail;
        }
-
-       status = open_socket_out_defer_recv(r445, &fd445->fd);
- done:
-       TALLOC_FREE(ev);
+       set_socket_options(fd, lp_socket_options());
+done:
+       *pfd = fd;
+       *pport = port;
+       status = NT_STATUS_OK;
+fail:
+       TALLOC_FREE(frame);
        return status;
 }
 
-/****************************************************************************
- Open the client sockets.
-****************************************************************************/
-
-NTSTATUS cli_connect(struct cli_state *cli,
-               const char *host,
-               struct sockaddr_storage *dest_ss)
-
+NTSTATUS cli_connect_nb(const char *host, struct sockaddr_storage *pss,
+                       uint16_t port, int name_type, const char *myname,
+                       int signing_state, struct cli_state **pcli)
 {
-       int name_type = 0x20;
        TALLOC_CTX *frame = talloc_stackframe();
-       unsigned int num_addrs = 0;
-       unsigned int i = 0;
-       struct sockaddr_storage *ss_arr = NULL;
-       char *p = NULL;
-
-       /* reasonable default hostname */
-       if (!host) {
-               host = STAR_SMBSERVER;
-       }
+       struct cli_state *cli;
+       NTSTATUS status = NT_STATUS_NO_MEMORY;
+       int fd = -1;
+       char *desthost;
+       char *p;
+       socklen_t length;
+       int ret;
 
-       cli->desthost = talloc_strdup(cli, host);
-       if (cli->desthost == NULL) {
-               return NT_STATUS_NO_MEMORY;
+       desthost = talloc_strdup(talloc_tos(), host);
+       if (desthost == NULL) {
+               goto fail;
        }
 
-       /* allow hostnames of the form NAME#xx and do a netbios lookup */
-       if ((p = strchr(cli->desthost, '#'))) {
+       p = strchr(host, '#');
+       if (p != NULL) {
                name_type = strtol(p+1, NULL, 16);
-               *p = 0;
-       }
-
-       if (!dest_ss || is_zero_addr(dest_ss)) {
-               NTSTATUS status =resolve_name_list(frame,
-                                       cli->desthost,
-                                       name_type,
-                                       &ss_arr,
-                                       &num_addrs);
-               if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(frame);
-                       return NT_STATUS_BAD_NETWORK_NAME;
-                }
-       } else {
-               num_addrs = 1;
-               ss_arr = TALLOC_P(frame, struct sockaddr_storage);
-               if (!ss_arr) {
-                       TALLOC_FREE(frame);
-                       return NT_STATUS_NO_MEMORY;
+               host = talloc_strndup(talloc_tos(), host, p - host);
+               if (host == NULL) {
+                       goto fail;
                }
-               *ss_arr = *dest_ss;
        }
 
-       for (i = 0; i < num_addrs; i++) {
-               cli->dest_ss = ss_arr[i];
-               if (getenv("LIBSMB_PROG")) {
-                       cli->fd = sock_exec(getenv("LIBSMB_PROG"));
-               } else {
-                       uint16_t port = cli->port;
-                       NTSTATUS status;
-                       status = open_smb_socket(&cli->dest_ss, &port,
-                                                cli->timeout, &cli->fd);
-                       if (NT_STATUS_IS_OK(status)) {
-                               cli->port = port;
-                       }
-               }
-               if (cli->fd == -1) {
-                       char addr[INET6_ADDRSTRLEN];
-                       print_sockaddr(addr, sizeof(addr), &ss_arr[i]);
-                       DEBUG(2,("Error connecting to %s (%s)\n",
-                                dest_ss?addr:host,strerror(errno)));
-               } else {
-                       /* Exit from loop on first connection. */
-                       break;
-               }
+       cli = cli_initialise_ex(signing_state);
+       if (cli == NULL) {
+               goto fail;
        }
+       cli->desthost = talloc_move(cli, &desthost);
 
-       if (cli->fd == -1) {
-               TALLOC_FREE(frame);
-               return map_nt_error_from_unix(errno);
+       status = cli_connect_sock(host, name_type, pss, myname, port, 20, &fd,
+                                 &port);
+       if (!NT_STATUS_IS_OK(status)) {
+               cli_shutdown(cli);
+               goto fail;
        }
+       cli->fd = fd;
+       cli->port = port;
 
-       if (dest_ss) {
-               *dest_ss = cli->dest_ss;
+       length = sizeof(cli->dest_ss);
+       ret = getpeername(fd, (struct sockaddr *)(void *)&cli->dest_ss,
+                         &length);
+       if (ret == -1) {
+               status = map_nt_error_from_unix(errno);
+               cli_shutdown(cli);
+               goto fail;
        }
 
-       set_socket_options(cli->fd, lp_socket_options());
+       if (pss != NULL) {
+               *pss = cli->dest_ss;
+       }
 
+       *pcli = cli;
+       status = NT_STATUS_OK;
+fail:
        TALLOC_FREE(frame);
-       return NT_STATUS_OK;
+       return status;
 }
 
 /**
@@ -3093,59 +2934,16 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli,
                              int signing_state, int flags)
 {
        NTSTATUS nt_status;
-       struct nmb_name calling;
-       struct nmb_name called;
        struct cli_state *cli;
-       struct sockaddr_storage ss;
-
-       if (!my_name) 
-               my_name = global_myname();
-
-       if (!(cli = cli_initialise_ex(signing_state))) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       make_nmb_name(&calling, my_name, 0x0);
-       make_nmb_name(&called , dest_host, 0x20);
-
-       cli_set_port(cli, port);
-       cli_set_timeout(cli, 10000); /* 10 seconds. */
-
-       if (dest_ss) {
-               ss = *dest_ss;
-       } else {
-               zero_sockaddr(&ss);
-       }
-
-again:
-
-       DEBUG(3,("Connecting to host=%s\n", dest_host));
 
-       nt_status = cli_connect(cli, dest_host, &ss);
+       nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
+                                  signing_state, &cli);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               char addr[INET6_ADDRSTRLEN];
-               print_sockaddr(addr, sizeof(addr), &ss);
-               DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
-                        nmb_namestr(&called), addr, nt_errstr(nt_status) ));
-               cli_shutdown(cli);
+               DEBUG(10, ("cli_connect_nb failed: %s\n",
+                          nt_errstr(nt_status)));
                return nt_status;
        }
 
-       if (!cli_session_request(cli, &calling, &called)) {
-               char *p;
-               DEBUG(1,("session request to %s failed (%s)\n",
-                        called.name, cli_errstr(cli)));
-               if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
-                       *p = 0;
-                       goto again;
-               }
-               if (strcmp(called.name, STAR_SMBSERVER)) {
-                       make_nmb_name(&called , STAR_SMBSERVER, 0x20);
-                       goto again;
-               }
-               return NT_STATUS_BAD_NETWORK_NAME;
-       }
-
        if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
                cli->use_spnego = False;
        else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
@@ -3258,71 +3056,6 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
        return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Attempt a NetBIOS session request, falling back to *SMBSERVER if needed.
-****************************************************************************/
-
-bool attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
-                                     struct sockaddr_storage *pdest_ss)
-{
-       struct nmb_name calling, called;
-
-       make_nmb_name(&calling, srchost, 0x0);
-
-       /*
-        * If the called name is an IP address
-        * then use *SMBSERVER immediately.
-        */
-
-       if(is_ipaddress(desthost)) {
-               make_nmb_name(&called, STAR_SMBSERVER, 0x20);
-       } else {
-               make_nmb_name(&called, desthost, 0x20);
-       }
-
-       if (!cli_session_request(*ppcli, &calling, &called)) {
-               NTSTATUS status;
-               struct nmb_name smbservername;
-
-               make_nmb_name(&smbservername, STAR_SMBSERVER, 0x20);
-
-               /*
-                * If the name wasn't *SMBSERVER then
-                * try with *SMBSERVER if the first name fails.
-                */
-
-               if (nmb_name_equal(&called, &smbservername)) {
-
-                       /*
-                        * The name used was *SMBSERVER, don't bother with another name.
-                        */
-
-                       DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
-with error %s.\n", desthost, cli_errstr(*ppcli) ));
-                       return False;
-               }
-
-               /* Try again... */
-               cli_shutdown(*ppcli);
-
-               *ppcli = cli_initialise();
-               if (!*ppcli) {
-                       /* Out of memory... */
-                       return False;
-               }
-
-               status = cli_connect(*ppcli, desthost, pdest_ss);
-               if (!NT_STATUS_IS_OK(status) ||
-                               !cli_session_request(*ppcli, &calling, &smbservername)) {
-                       DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
-name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
-                       return False;
-               }
-       }
-
-       return True;
-}
-
 /****************************************************************************
  Send an old style tcon.
 ****************************************************************************/