r26676: libcli: Fill in lp_workgroup() again, should fix my breakage of cifsdd tests...
[ira/wip.git] / source / libcli / raw / clisession.c
index c5d4888089cbef828eb2e146e2bf1b72bb0efcf7..617131c53c7a07163b3b71d103b2db6a834c320b 100644 (file)
@@ -1,12 +1,13 @@
 /* 
    Unix SMB/CIFS implementation.
    SMB client session context management functions
-   Copyright (C) Andrew Tridgell 1994-1998
+
+   Copyright (C) Andrew Tridgell 1994-2005
    Copyright (C) James Myers 2003 <myersjj@samba.org>
    
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "libcli/raw/libcliraw.h"
+#include "system/filesys.h"
 
 #define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \
-       req = cli_request_setup_session(session, cmd, wct, buflen); \
+       req = smbcli_request_setup_session(session, cmd, wct, buflen); \
        if (!req) return NULL; \
 } while (0)
 
+
 /****************************************************************************
  Initialize the session context
 ****************************************************************************/
-struct cli_session *cli_session_init(struct cli_transport *transport)
+struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport, 
+                                          TALLOC_CTX *parent_ctx, bool primary)
 {
-       struct cli_session *session;
-       TALLOC_CTX *mem_ctx = talloc_init("cli_session");
-       if (mem_ctx == NULL) {
-               return NULL;
-       }
+       struct smbcli_session *session;
+       uint16_t flags2;
+       uint32_t capabilities;
 
-       session = talloc_zero(mem_ctx, sizeof(*session));
+       session = talloc_zero(parent_ctx, struct smbcli_session);
        if (!session) {
-               talloc_destroy(mem_ctx);
                return NULL;
        }
 
-       session->mem_ctx = mem_ctx;
-       session->transport = transport;
-       session->pid = (uint16)getpid();
+       if (primary) {
+               session->transport = talloc_steal(session, transport);
+       } else {
+               session->transport = talloc_reference(session, transport);
+       }
+       session->pid = (uint16_t)getpid();
        session->vuid = UID_FIELD_INVALID;
-       session->transport->reference_count++;
+       
+       capabilities = transport->negotiate.capabilities;
 
-       return session;
-}
+       flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
 
-/****************************************************************************
-reduce reference_count and destroy is <= 0
-****************************************************************************/
-void cli_session_close(struct cli_session *session)
-{
-       session->reference_count--;
-       if (session->reference_count <= 0) {
-               cli_transport_close(session->transport);
-               talloc_destroy(session->mem_ctx);
+       if (capabilities & CAP_UNICODE) {
+               flags2 |= FLAGS2_UNICODE_STRINGS;
        }
+       if (capabilities & CAP_STATUS32) {
+               flags2 |= FLAGS2_32_BIT_ERROR_CODES;
+       }
+       if (capabilities & CAP_EXTENDED_SECURITY) {
+               flags2 |= FLAGS2_EXTENDED_SECURITY;
+       }
+       if (session->transport->negotiate.sign_info.doing_signing) {
+               flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
+       }
+
+       session->flags2 = flags2;
+
+       return session;
 }
 
 /****************************************************************************
  Perform a session setup (async send)
 ****************************************************************************/
-struct cli_request *smb_raw_session_setup_send(struct cli_session *session, union smb_sesssetup *parms) 
+struct smbcli_request *smb_raw_sesssetup_send(struct smbcli_session *session, 
+                                             union smb_sesssetup *parms) 
 {
-       struct cli_request *req;
-
-       switch (parms->generic.level) {
-       case RAW_SESSSETUP_GENERIC:
-               /* handled elsewhere */
-               return NULL;
+       struct smbcli_request *req = NULL;
 
+       switch (parms->old.level) {
        case RAW_SESSSETUP_OLD:
                SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
                SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
@@ -85,11 +92,12 @@ struct cli_request *smb_raw_session_setup_send(struct cli_session *session, unio
                SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num);
                SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey);
                SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length);
-               cli_req_append_blob(req, &parms->old.in.password);
-               cli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
-               cli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
-               cli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
-               cli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
+               SIVAL(req->out.vwv,VWV(8), 0); /* reserved */
+               smbcli_req_append_blob(req, &parms->old.in.password);
+               smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
+               smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
+               smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
+               smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
                break;
 
        case RAW_SESSSETUP_NT1:
@@ -104,12 +112,12 @@ struct cli_request *smb_raw_session_setup_send(struct cli_session *session, unio
                SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length);
                SIVAL(req->out.vwv, VWV(9), 0); /* reserved */
                SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities);
-               cli_req_append_blob(req, &parms->nt1.in.password1);
-               cli_req_append_blob(req, &parms->nt1.in.password2);
-               cli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
-               cli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
-               cli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
-               cli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
+               smbcli_req_append_blob(req, &parms->nt1.in.password1);
+               smbcli_req_append_blob(req, &parms->nt1.in.password2);
+               smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
+               smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
+               smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
+               smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
                break;
 
        case RAW_SESSSETUP_SPNEGO:
@@ -121,15 +129,20 @@ struct cli_request *smb_raw_session_setup_send(struct cli_session *session, unio
                SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num);
                SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey);
                SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length);
+               SIVAL(req->out.vwv, VWV(8), 0); /* reserved */
                SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities);
-               cli_req_append_blob(req, &parms->spnego.in.secblob);
-               cli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
-               cli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
+               smbcli_req_append_blob(req, &parms->spnego.in.secblob);
+               smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
+               smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
+               smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE);
                break;
+
+       case RAW_SESSSETUP_SMB2:
+               return NULL;
        }
 
-       if (!cli_request_send(req)) {
-               cli_request_destroy(req);
+       if (!smbcli_request_send(req)) {
+               smbcli_request_destroy(req);
                return NULL;
        }
 
@@ -140,57 +153,53 @@ struct cli_request *smb_raw_session_setup_send(struct cli_session *session, unio
 /****************************************************************************
  Perform a session setup (async recv)
 ****************************************************************************/
-NTSTATUS smb_raw_session_setup_recv(struct cli_request *req, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   union smb_sesssetup *parms) 
+NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, 
+                               TALLOC_CTX *mem_ctx, 
+                               union smb_sesssetup *parms) 
 {
-       uint16 len;
-       char *p;
+       uint16_t len;
+       uint8_t *p;
 
-       if (!cli_request_receive(req)) {
-               return cli_request_destroy(req);
+       if (!smbcli_request_receive(req)) {
+               return smbcli_request_destroy(req);
        }
        
        if (!NT_STATUS_IS_OK(req->status) &&
            !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               return cli_request_destroy(req);
+               return smbcli_request_destroy(req);
        }
 
-       switch (parms->generic.level) {
-       case RAW_SESSSETUP_GENERIC:
-               /* handled elsewhere */
-               return NT_STATUS_INVALID_LEVEL;
-
+       switch (parms->old.level) {
        case RAW_SESSSETUP_OLD:
-               CLI_CHECK_WCT(req, 3);
+               SMBCLI_CHECK_WCT(req, 3);
                ZERO_STRUCT(parms->old.out);
                parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
                parms->old.out.action = SVAL(req->in.vwv, VWV(2));
                p = req->in.data;
                if (p) {
-                       p += cli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
-                       p += cli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
-                       p += cli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
+                       p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
+                       p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
+                       p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
                }
                break;
 
        case RAW_SESSSETUP_NT1:
-               CLI_CHECK_WCT(req, 3);
+               SMBCLI_CHECK_WCT(req, 3);
                ZERO_STRUCT(parms->nt1.out);
                parms->nt1.out.vuid   = SVAL(req->in.hdr, HDR_UID);
                parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
                p = req->in.data;
                if (p) {
-                       p += cli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
-                       p += cli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
+                       p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
+                       p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
                        if (p < (req->in.data + req->in.data_size)) {
-                               p += cli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
+                               p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
                        }
                }
                break;
 
        case RAW_SESSSETUP_SPNEGO:
-               CLI_CHECK_WCT(req, 4);
+               SMBCLI_CHECK_WCT(req, 4);
                ZERO_STRUCT(parms->spnego.out);
                parms->spnego.out.vuid   = SVAL(req->in.hdr, HDR_UID);
                parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
@@ -200,224 +209,75 @@ NTSTATUS smb_raw_session_setup_recv(struct cli_request *req,
                        break;
                }
 
-               parms->spnego.out.secblob = cli_req_pull_blob(req, mem_ctx, p, len);
+               parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len);
                p += parms->spnego.out.secblob.length;
-               p += cli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
-               p += cli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
-               p += cli_req_pull_string(req, mem_ctx, &parms->spnego.out.domain, p, -1, STR_TERMINATE);
+               p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
+               p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
+               p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE);
+               break;
+
+       case RAW_SESSSETUP_SMB2:
+               req->status = NT_STATUS_INTERNAL_ERROR;
                break;
        }
 
 failed:
-       return cli_request_destroy(req);
-}
-
-/*
-  form an encrypted lanman password from a plaintext password
-  and the server supplied challenge
-*/
-static DATA_BLOB lanman_blob(const char *pass, DATA_BLOB challenge)
-{
-       DATA_BLOB blob = data_blob(NULL, 24);
-       SMBencrypt(pass, challenge.data, blob.data);
-       return blob;
+       return smbcli_request_destroy(req);
 }
 
-/*
-  form an encrypted NT password from a plaintext password
-  and the server supplied challenge
-*/
-static DATA_BLOB nt_blob(const char *pass, DATA_BLOB challenge)
-{
-       DATA_BLOB blob = data_blob(NULL, 24);
-       SMBNTencrypt(pass, challenge.data, blob.data);
-       return blob;
-}
 
 /*
-  setup signing for a NT1 style session setup
+ Perform a session setup (sync interface)
 */
-static void setup_nt1_signing(struct cli_transport *transport, const char *password)
+NTSTATUS smb_raw_sesssetup(struct smbcli_session *session, 
+                          TALLOC_CTX *mem_ctx, union smb_sesssetup *parms) 
 {
-       uchar nt_hash[16];
-       uchar session_key[16];
-       DATA_BLOB nt_response;
-
-       E_md4hash(password, nt_hash);
-       SMBsesskeygen_ntv1(nt_hash, NULL, session_key);
-       nt_response = nt_blob(password, transport->negotiate.secblob);
-
-       cli_transport_simple_set_signing(transport, session_key, nt_response);
+       struct smbcli_request *req = smb_raw_sesssetup_send(session, parms);
+       return smb_raw_sesssetup_recv(req, mem_ctx, parms);
 }
 
-/****************************************************************************
- Perform a session setup (sync interface) using generic interface and the old
- style sesssetup call
-****************************************************************************/
-static NTSTATUS smb_raw_session_setup_generic_old(struct cli_session *session, 
-                                                 TALLOC_CTX *mem_ctx, 
-                                                 union smb_sesssetup *parms) 
-{
-       NTSTATUS status;
-       union smb_sesssetup s2;
-
-       /* use the old interface */
-       s2.generic.level = RAW_SESSSETUP_OLD;
-       s2.old.in.bufsize = ~0;
-       s2.old.in.mpx_max = 50;
-       s2.old.in.vc_num = 1;
-       s2.old.in.sesskey = parms->generic.in.sesskey;
-       s2.old.in.domain = parms->generic.in.domain;
-       s2.old.in.user = parms->generic.in.user;
-       s2.old.in.os = "Unix";
-       s2.old.in.lanman = "Samba";
-       
-       if (!parms->generic.in.password) {
-               s2.old.in.password = data_blob(NULL, 0);
-       } else if (session->transport->negotiate.sec_mode & 
-                  NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
-               s2.old.in.password = lanman_blob(parms->generic.in.password, 
-                                                session->transport->negotiate.secblob);
-       } else {
-               s2.old.in.password = data_blob(parms->generic.in.password, 
-                                              strlen(parms->generic.in.password));
-       }
-       
-       status = smb_raw_session_setup(session, mem_ctx, &s2);
-       
-       data_blob_free(&s2.old.in.password);
-       
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-       
-       parms->generic.out.vuid = s2.old.out.vuid;
-       parms->generic.out.os = s2.old.out.os;
-       parms->generic.out.lanman = s2.old.out.lanman;
-       parms->generic.out.domain = s2.old.out.domain;
-       
-       return NT_STATUS_OK;
-}
 
 /****************************************************************************
- Perform a session setup (sync interface) using generic interface and the NT1
- style sesssetup call
-****************************************************************************/
-static NTSTATUS smb_raw_session_setup_generic_nt1(struct cli_session *session, 
-                                                 TALLOC_CTX *mem_ctx,
-                                                 union smb_sesssetup *parms) 
+ Send a ulogoff (async send)
+*****************************************************************************/
+struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
 {
-       NTSTATUS status;
-       union smb_sesssetup s2;
-
-       s2.generic.level = RAW_SESSSETUP_NT1;
-       s2.nt1.in.bufsize = ~0;
-       s2.nt1.in.mpx_max = 50;
-       s2.nt1.in.vc_num = 1;
-       s2.nt1.in.sesskey = parms->generic.in.sesskey;
-       s2.nt1.in.capabilities = parms->generic.in.capabilities;
-       s2.nt1.in.domain = parms->generic.in.domain;
-       s2.nt1.in.user = parms->generic.in.user;
-       s2.nt1.in.os = "Unix";
-       s2.nt1.in.lanman = "Samba";
-
-       if (!parms->generic.in.password) {
-               s2.nt1.in.password1 = data_blob(NULL, 0);
-               s2.nt1.in.password2 = data_blob(NULL, 0);
-       } else if (session->transport->negotiate.sec_mode & 
-                  NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
-               s2.nt1.in.password1 = lanman_blob(parms->generic.in.password, 
-                                                 session->transport->negotiate.secblob);
-               s2.nt1.in.password2 = nt_blob(parms->generic.in.password, 
-                                             session->transport->negotiate.secblob);
-               setup_nt1_signing(session->transport, parms->generic.in.password);
-       } else {
-               s2.nt1.in.password1 = data_blob(parms->generic.in.password, 
-                                               strlen(parms->generic.in.password));
-               s2.nt1.in.password2 = data_blob(NULL, 0);
-       }
-
-       status = smb_raw_session_setup(session, mem_ctx, &s2);
-               
-       data_blob_free(&s2.nt1.in.password1);
-       data_blob_free(&s2.nt1.in.password2);
-               
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       parms->generic.out.vuid = s2.nt1.out.vuid;
-       parms->generic.out.os = s2.nt1.out.os;
-       parms->generic.out.lanman = s2.nt1.out.lanman;
-       parms->generic.out.domain = s2.nt1.out.domain;
+       struct smbcli_request *req;
 
-       return NT_STATUS_OK;
-}
-
-
-/****************************************************************************
- Perform a session setup (sync interface) using generic interface
-****************************************************************************/
-static NTSTATUS smb_raw_session_setup_generic(struct cli_session *session, 
-                                             TALLOC_CTX *mem_ctx,
-                                             union smb_sesssetup *parms) 
-{
-       if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) {
-               /* no session setup at all in earliest protocols */
-               ZERO_STRUCT(parms->generic.out);
-               return NT_STATUS_OK;
-       }
+       SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
 
-       /* see if we need to use the original session setup interface */
-       if (session->transport->negotiate.protocol < PROTOCOL_NT1) {
-               return smb_raw_session_setup_generic_old(session, mem_ctx, parms);
-       }
+       SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
+       SSVAL(req->out.vwv, VWV(1), 0);
 
-       /* see if we should use the NT1 interface */
-       if (!(session->transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) ||
-           !session->transport->options.use_spnego) {
-               return smb_raw_session_setup_generic_nt1(session, mem_ctx, parms);
+       if (!smbcli_request_send(req)) {
+               smbcli_request_destroy(req);
+               return NULL;
        }
 
-       /* default to using SPNEGO/NTLMSSP */
-       DEBUG(0,("Need to add client SPNEGO code back in\n"));
-       return NT_STATUS_UNSUCCESSFUL;
+       return req;
 }
 
-
 /****************************************************************************
- Perform a session setup (sync interface)
-this interface allows for RAW_SESSSETUP_GENERIC to auto-select session
-setup varient based on negotiated protocol options
-****************************************************************************/
-NTSTATUS smb_raw_session_setup(struct cli_session *session, TALLOC_CTX *mem_ctx, 
-                              union smb_sesssetup *parms) 
+ Send a ulogoff (sync interface)
+*****************************************************************************/
+NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
 {
-       struct cli_request *req;
-
-       if (parms->generic.level == RAW_SESSSETUP_GENERIC) {
-               return smb_raw_session_setup_generic(session, mem_ctx, parms);
-       }
-
-       req = smb_raw_session_setup_send(session, parms);
-       return smb_raw_session_setup_recv(req, mem_ctx, parms);
+       struct smbcli_request *req = smb_raw_ulogoff_send(session);
+       return smbcli_request_simple_recv(req);
 }
 
 
 /****************************************************************************
- Send a uloggoff (async send)
+ Send a exit (async send)
 *****************************************************************************/
-struct cli_request *smb_raw_ulogoff_send(struct cli_session *session)
+struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
 {
-       struct cli_request *req;
+       struct smbcli_request *req;
 
-       SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
+       SETUP_REQUEST_SESSION(SMBexit, 0, 0);
 
-       SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
-       SSVAL(req->out.vwv, VWV(1), 0);
-
-       if (!cli_request_send(req)) {
-               cli_request_destroy(req);
+       if (!smbcli_request_send(req)) {
+               smbcli_request_destroy(req);
                return NULL;
        }
 
@@ -425,26 +285,10 @@ struct cli_request *smb_raw_ulogoff_send(struct cli_session *session)
 }
 
 /****************************************************************************
- Send a uloggoff (sync interface)
+ Send a exit (sync interface)
 *****************************************************************************/
-NTSTATUS smb_raw_ulogoff(struct cli_session *session)
+NTSTATUS smb_raw_exit(struct smbcli_session *session)
 {
-       struct cli_request *req = smb_raw_ulogoff_send(session);
-       return cli_request_simple_recv(req);
-}
-
-
-/****************************************************************************
- Send a SMBexit
-****************************************************************************/
-NTSTATUS smb_raw_exit(struct cli_session *session)
-{
-       struct cli_request *req;
-
-       req = cli_request_setup_session(session, SMBexit, 0, 0);
-
-       if (cli_request_send(req)) {
-               cli_request_receive(req);
-       }
-       return cli_request_destroy(req);
+       struct smbcli_request *req = smb_raw_exit_send(session);
+       return smbcli_request_simple_recv(req);
 }