Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/libsmb/cliconnect.c

    r597 r740  
    44   Copyright (C) Andrew Tridgell 1994-1998
    55   Copyright (C) Andrew Bartlett 2001-2003
    6    
     6   Copyright (C) Volker Lendecke 2011
     7   Copyright (C) Jeremy Allison 2011
     8
    79   This program is free software; you can redistribute it and/or modify
    810   it under the terms of the GNU General Public License as published by
    911   the Free Software Foundation; either version 3 of the License, or
    1012   (at your option) any later version.
    11    
     13
    1214   This program is distributed in the hope that it will be useful,
    1315   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1416   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1517   GNU General Public License for more details.
    16    
     18
    1719   You should have received a copy of the GNU General Public License
    1820   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2022
    2123#include "includes.h"
     24#include "libsmb/libsmb.h"
     25#include "popt_common.h"
    2226#include "../libcli/auth/libcli_auth.h"
    2327#include "../libcli/auth/spnego.h"
    2428#include "smb_krb5.h"
     29#include "../libcli/auth/ntlmssp.h"
     30#include "libads/kerberos_proto.h"
     31#include "krb5_env.h"
     32#include "../lib/util/tevent_ntstatus.h"
     33#include "async_smb.h"
     34#include "libsmb/nmblib.h"
    2535
    2636static const struct {
     
    4252#define STAR_SMBSERVER "*SMBSERVER"
    4353
     54/********************************************************
     55 Utility function to ensure we always return at least
     56 a valid char * pointer to an empty string for the
     57 cli->server_os, cli->server_type and cli->server_domain
     58 strings.
     59*******************************************************/
     60
     61static NTSTATUS smb_bytes_talloc_string(struct cli_state *cli,
     62                                        char *inbuf,
     63                                        char **dest,
     64                                        uint8_t *src,
     65                                        size_t srclen,
     66                                        ssize_t *destlen)
     67{
     68        *destlen = clistr_pull_talloc(cli,
     69                                inbuf,
     70                                SVAL(inbuf, smb_flg2),
     71                                dest,
     72                                (char *)src,
     73                                srclen,
     74                                STR_TERMINATE);
     75        if (*destlen == -1) {
     76                return NT_STATUS_NO_MEMORY;
     77        }
     78
     79        if (*dest == NULL) {
     80                *dest = talloc_strdup(cli, "");
     81                if (*dest == NULL) {
     82                        return NT_STATUS_NO_MEMORY;
     83                }
     84        }
     85        return NT_STATUS_OK;
     86}
     87
    4488/**
    4589 * Set the user session key for a connection
     
    58102****************************************************************************/
    59103
    60 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
    61                                           const char *user,
     104struct cli_session_setup_lanman2_state {
     105        struct cli_state *cli;
     106        uint16_t vwv[10];
     107        const char *user;
     108};
     109
     110static void cli_session_setup_lanman2_done(struct tevent_req *subreq);
     111
     112static struct tevent_req *cli_session_setup_lanman2_send(
     113        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     114        struct cli_state *cli, const char *user,
     115        const char *pass, size_t passlen,
     116        const char *workgroup)
     117{
     118        struct tevent_req *req, *subreq;
     119        struct cli_session_setup_lanman2_state *state;
     120        DATA_BLOB lm_response = data_blob_null;
     121        uint16_t *vwv;
     122        uint8_t *bytes;
     123        char *tmp;
     124
     125        req = tevent_req_create(mem_ctx, &state,
     126                                struct cli_session_setup_lanman2_state);
     127        if (req == NULL) {
     128                return NULL;
     129        }
     130        state->cli = cli;
     131        state->user = user;
     132        vwv = state->vwv;
     133
     134        /*
     135         * LANMAN servers predate NT status codes and Unicode and
     136         * ignore those smb flags so we must disable the corresponding
     137         * default capabilities that would otherwise cause the Unicode
     138         * and NT Status flags to be set (and even returned by the
     139         * server)
     140         */
     141
     142        cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
     143
     144        /*
     145         * if in share level security then don't send a password now
     146         */
     147        if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
     148                passlen = 0;
     149        }
     150
     151        if (passlen > 0
     152            && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
     153            && passlen != 24) {
     154                /*
     155                 * Encrypted mode needed, and non encrypted password
     156                 * supplied.
     157                 */
     158                lm_response = data_blob(NULL, 24);
     159                if (tevent_req_nomem(lm_response.data, req)) {
     160                        return tevent_req_post(req, ev);
     161                }
     162
     163                if (!SMBencrypt(pass, cli->secblob.data,
     164                                (uint8_t *)lm_response.data)) {
     165                        DEBUG(1, ("Password is > 14 chars in length, and is "
     166                                  "therefore incompatible with Lanman "
     167                                  "authentication\n"));
     168                        tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     169                        return tevent_req_post(req, ev);
     170                }
     171        } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)
     172                   && passlen == 24) {
     173                /*
     174                 * Encrypted mode needed, and encrypted password
     175                 * supplied.
     176                 */
     177                lm_response = data_blob(pass, passlen);
     178                if (tevent_req_nomem(lm_response.data, req)) {
     179                        return tevent_req_post(req, ev);
     180                }
     181        } else if (passlen > 0) {
     182                uint8_t *buf;
     183                size_t converted_size;
     184                /*
     185                 * Plaintext mode needed, assume plaintext supplied.
     186                 */
     187                buf = talloc_array(talloc_tos(), uint8_t, 0);
     188                buf = smb_bytes_push_str(buf, cli_ucs2(cli), pass, passlen+1,
     189                                         &converted_size);
     190                if (tevent_req_nomem(buf, req)) {
     191                        return tevent_req_post(req, ev);
     192                }
     193                lm_response = data_blob(pass, passlen);
     194                TALLOC_FREE(buf);
     195                if (tevent_req_nomem(lm_response.data, req)) {
     196                        return tevent_req_post(req, ev);
     197                }
     198        }
     199
     200        SCVAL(vwv+0, 0, 0xff);
     201        SCVAL(vwv+0, 1, 0);
     202        SSVAL(vwv+1, 0, 0);
     203        SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
     204        SSVAL(vwv+3, 0, 2);
     205        SSVAL(vwv+4, 0, 1);
     206        SIVAL(vwv+5, 0, cli->sesskey);
     207        SSVAL(vwv+7, 0, lm_response.length);
     208
     209        bytes = talloc_array(state, uint8_t, lm_response.length);
     210        if (tevent_req_nomem(bytes, req)) {
     211                return tevent_req_post(req, ev);
     212        }
     213        if (lm_response.length != 0) {
     214                memcpy(bytes, lm_response.data, lm_response.length);
     215        }
     216        data_blob_free(&lm_response);
     217
     218        tmp = talloc_strdup_upper(talloc_tos(), user);
     219        if (tevent_req_nomem(tmp, req)) {
     220                return tevent_req_post(req, ev);
     221        }
     222        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
     223                                   NULL);
     224        TALLOC_FREE(tmp);
     225
     226        tmp = talloc_strdup_upper(talloc_tos(), workgroup);
     227        if (tevent_req_nomem(tmp, req)) {
     228                return tevent_req_post(req, ev);
     229        }
     230        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), tmp, strlen(tmp)+1,
     231                                   NULL);
     232        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
     233        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
     234
     235        if (tevent_req_nomem(bytes, req)) {
     236                return tevent_req_post(req, ev);
     237        }
     238
     239        subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 10, vwv,
     240                              talloc_get_size(bytes), bytes);
     241        if (tevent_req_nomem(subreq, req)) {
     242                return tevent_req_post(req, ev);
     243        }
     244        tevent_req_set_callback(subreq, cli_session_setup_lanman2_done, req);
     245        return req;
     246}
     247
     248static void cli_session_setup_lanman2_done(struct tevent_req *subreq)
     249{
     250        struct tevent_req *req = tevent_req_callback_data(
     251                subreq, struct tevent_req);
     252        struct cli_session_setup_lanman2_state *state = tevent_req_data(
     253                req, struct cli_session_setup_lanman2_state);
     254        struct cli_state *cli = state->cli;
     255        uint32_t num_bytes;
     256        uint8_t *in;
     257        char *inbuf;
     258        uint8_t *bytes;
     259        uint8_t *p;
     260        NTSTATUS status;
     261        ssize_t ret;
     262        uint8_t wct;
     263        uint16_t *vwv;
     264
     265        status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
     266                              &num_bytes, &bytes);
     267        TALLOC_FREE(subreq);
     268        if (!NT_STATUS_IS_OK(status)) {
     269                tevent_req_nterror(req, status);
     270                return;
     271        }
     272
     273        inbuf = (char *)in;
     274        p = bytes;
     275
     276        cli->vuid = SVAL(inbuf, smb_uid);
     277        cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
     278
     279        status = smb_bytes_talloc_string(cli,
     280                                        inbuf,
     281                                        &cli->server_os,
     282                                        p,
     283                                        bytes+num_bytes-p,
     284                                        &ret);
     285
     286        if (!NT_STATUS_IS_OK(status)) {
     287                tevent_req_nterror(req, status);
     288                return;
     289        }
     290        p += ret;
     291
     292        status = smb_bytes_talloc_string(cli,
     293                                        inbuf,
     294                                        &cli->server_type,
     295                                        p,
     296                                        bytes+num_bytes-p,
     297                                        &ret);
     298
     299        if (!NT_STATUS_IS_OK(status)) {
     300                tevent_req_nterror(req, status);
     301                return;
     302        }
     303        p += ret;
     304
     305        status = smb_bytes_talloc_string(cli,
     306                                        inbuf,
     307                                        &cli->server_domain,
     308                                        p,
     309                                        bytes+num_bytes-p,
     310                                        &ret);
     311
     312        if (!NT_STATUS_IS_OK(status)) {
     313                tevent_req_nterror(req, status);
     314                return;
     315        }
     316        p += ret;
     317
     318        if (strstr(cli->server_type, "Samba")) {
     319                cli->is_samba = True;
     320        }
     321        status = cli_set_username(cli, state->user);
     322        if (tevent_req_nterror(req, status)) {
     323                return;
     324        }
     325        tevent_req_done(req);
     326}
     327
     328static NTSTATUS cli_session_setup_lanman2_recv(struct tevent_req *req)
     329{
     330        return tevent_req_simple_recv_ntstatus(req);
     331}
     332
     333static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli, const char *user,
    62334                                          const char *pass, size_t passlen,
    63335                                          const char *workgroup)
    64336{
    65         DATA_BLOB session_key = data_blob_null;
    66         DATA_BLOB lm_response = data_blob_null;
    67         NTSTATUS status;
    68         fstring pword;
    69         char *p;
    70 
    71         if (passlen > sizeof(pword)-1) {
    72                 return NT_STATUS_INVALID_PARAMETER;
    73         }
    74 
    75         /* LANMAN servers predate NT status codes and Unicode and ignore those
    76            smb flags so we must disable the corresponding default capabilities 
    77            that would otherwise cause the Unicode and NT Status flags to be
    78            set (and even returned by the server) */
    79 
    80         cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
    81 
    82         /* if in share level security then don't send a password now */
    83         if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
    84                 passlen = 0;
    85 
    86         if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
    87                 /* Encrypted mode needed, and non encrypted password supplied. */
    88                 lm_response = data_blob(NULL, 24);
    89                 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
    90                         DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
    91                         return NT_STATUS_ACCESS_DENIED;
    92                 }
    93         } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
    94                 /* Encrypted mode needed, and encrypted password supplied. */
    95                 lm_response = data_blob(pass, passlen);
    96         } else if (passlen > 0) {
    97                 /* Plaintext mode needed, assume plaintext supplied. */
    98                 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
    99                 lm_response = data_blob(pass, passlen);
    100         }
    101 
    102         /* send a session setup command */
    103         memset(cli->outbuf,'\0',smb_size);
    104         cli_set_message(cli->outbuf,10, 0, True);
    105         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
    106         cli_setup_packet(cli);
    107        
    108         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    109         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
    110         SSVAL(cli->outbuf,smb_vwv3,2);
    111         SSVAL(cli->outbuf,smb_vwv4,1);
    112         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
    113         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
    114 
    115         p = smb_buf(cli->outbuf);
    116         memcpy(p,lm_response.data,lm_response.length);
    117         p += lm_response.length;
    118         p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
    119         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
    120         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
    121         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
    122         cli_setup_bcc(cli, p);
    123 
    124         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
    125                 return cli_nt_error(cli);
    126         }
    127 
    128         show_msg(cli->inbuf);
    129 
    130         if (cli_is_error(cli)) {
    131                 return cli_nt_error(cli);
    132         }
    133        
    134         /* use the returned vuid from now on */
    135         cli->vuid = SVAL(cli->inbuf,smb_uid);   
    136         status = cli_set_username(cli, user);
    137         if (!NT_STATUS_IS_OK(status)) {
    138                 return status;
    139         }
    140 
    141         if (session_key.data) {
    142                 /* Have plaintext orginal */
    143                 cli_set_session_key(cli, session_key);
    144         }
    145 
    146         return NT_STATUS_OK;
     337        TALLOC_CTX *frame = talloc_stackframe();
     338        struct event_context *ev;
     339        struct tevent_req *req;
     340        NTSTATUS status = NT_STATUS_NO_MEMORY;
     341
     342        if (cli_has_async_calls(cli)) {
     343                /*
     344                 * Can't use sync call while an async call is in flight
     345                 */
     346                status = NT_STATUS_INVALID_PARAMETER;
     347                goto fail;
     348        }
     349        ev = event_context_init(frame);
     350        if (ev == NULL) {
     351                goto fail;
     352        }
     353        req = cli_session_setup_lanman2_send(frame, ev, cli, user, pass, passlen,
     354                                             workgroup);
     355        if (req == NULL) {
     356                goto fail;
     357        }
     358        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     359                goto fail;
     360        }
     361        status = cli_session_setup_lanman2_recv(req);
     362 fail:
     363        TALLOC_FREE(frame);
     364        if (!NT_STATUS_IS_OK(status)) {
     365                cli_set_error(cli, status);
     366        }
     367        return status;
    147368}
    148369
     
    171392struct cli_session_setup_guest_state {
    172393        struct cli_state *cli;
    173         uint16_t vwv[16];
     394        uint16_t vwv[13];
    174395        struct iovec bytes;
    175396};
     
    264485        struct cli_state *cli = state->cli;
    265486        uint32_t num_bytes;
     487        uint8_t *in;
    266488        char *inbuf;
    267489        uint8_t *bytes;
    268490        uint8_t *p;
    269491        NTSTATUS status;
    270 
    271         status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
    272         if (!NT_STATUS_IS_OK(status)) {
    273                 TALLOC_FREE(subreq);
     492        ssize_t ret;
     493        uint8_t wct;
     494        uint16_t *vwv;
     495
     496        status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
     497                              &num_bytes, &bytes);
     498        TALLOC_FREE(subreq);
     499        if (!NT_STATUS_IS_OK(status)) {
    274500                tevent_req_nterror(req, status);
    275501                return;
    276502        }
    277503
    278         inbuf = (char *)cli_smb_inbuf(subreq);
     504        inbuf = (char *)in;
    279505        p = bytes;
    280506
    281507        cli->vuid = SVAL(inbuf, smb_uid);
    282 
    283         p += clistr_pull(inbuf, cli->server_os, (char *)p, sizeof(fstring),
    284                          bytes+num_bytes-p, STR_TERMINATE);
    285         p += clistr_pull(inbuf, cli->server_type, (char *)p, sizeof(fstring),
    286                          bytes+num_bytes-p, STR_TERMINATE);
    287         p += clistr_pull(inbuf, cli->server_domain, (char *)p, sizeof(fstring),
    288                          bytes+num_bytes-p, STR_TERMINATE);
     508        cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
     509
     510        status = smb_bytes_talloc_string(cli,
     511                                        inbuf,
     512                                        &cli->server_os,
     513                                        p,
     514                                        bytes+num_bytes-p,
     515                                        &ret);
     516
     517        if (!NT_STATUS_IS_OK(status)) {
     518                tevent_req_nterror(req, status);
     519                return;
     520        }
     521        p += ret;
     522
     523        status = smb_bytes_talloc_string(cli,
     524                                        inbuf,
     525                                        &cli->server_type,
     526                                        p,
     527                                        bytes+num_bytes-p,
     528                                        &ret);
     529
     530        if (!NT_STATUS_IS_OK(status)) {
     531                tevent_req_nterror(req, status);
     532                return;
     533        }
     534        p += ret;
     535
     536        status = smb_bytes_talloc_string(cli,
     537                                        inbuf,
     538                                        &cli->server_domain,
     539                                        p,
     540                                        bytes+num_bytes-p,
     541                                        &ret);
     542
     543        if (!NT_STATUS_IS_OK(status)) {
     544                tevent_req_nterror(req, status);
     545                return;
     546        }
     547        p += ret;
    289548
    290549        if (strstr(cli->server_type, "Samba")) {
    291550                cli->is_samba = True;
    292551        }
    293 
    294         TALLOC_FREE(subreq);
    295552
    296553        status = cli_set_username(cli, "");
     
    352609****************************************************************************/
    353610
    354 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
    355                                             const char *user, const char *pass,
    356                                             const char *workgroup)
    357 {
    358         uint32 capabilities = cli_session_setup_capabilities(cli);
    359         char *p;
     611struct cli_session_setup_plain_state {
     612        struct cli_state *cli;
     613        uint16_t vwv[13];
     614        const char *user;
     615};
     616
     617static void cli_session_setup_plain_done(struct tevent_req *subreq);
     618
     619static struct tevent_req *cli_session_setup_plain_send(
     620        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     621        struct cli_state *cli,
     622        const char *user, const char *pass, const char *workgroup)
     623{
     624        struct tevent_req *req, *subreq;
     625        struct cli_session_setup_plain_state *state;
     626        uint16_t *vwv;
     627        uint8_t *bytes;
     628        size_t passlen;
     629        char *version;
     630
     631        req = tevent_req_create(mem_ctx, &state,
     632                                struct cli_session_setup_plain_state);
     633        if (req == NULL) {
     634                return NULL;
     635        }
     636        state->cli = cli;
     637        state->user = user;
     638        vwv = state->vwv;
     639
     640        SCVAL(vwv+0, 0, 0xff);
     641        SCVAL(vwv+0, 1, 0);
     642        SSVAL(vwv+1, 0, 0);
     643        SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
     644        SSVAL(vwv+3, 0, 2);
     645        SSVAL(vwv+4, 0, cli->pid);
     646        SIVAL(vwv+5, 0, cli->sesskey);
     647        SSVAL(vwv+7, 0, 0);
     648        SSVAL(vwv+8, 0, 0);
     649        SSVAL(vwv+9, 0, 0);
     650        SSVAL(vwv+10, 0, 0);
     651        SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
     652
     653        bytes = talloc_array(state, uint8_t, 0);
     654        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), pass, strlen(pass)+1,
     655                                   &passlen);
     656        if (tevent_req_nomem(bytes, req)) {
     657                return tevent_req_post(req, ev);
     658        }
     659        SSVAL(vwv + (cli_ucs2(cli) ? 8 : 7), 0, passlen);
     660
     661        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     662                                   user, strlen(user)+1, NULL);
     663        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     664                                   workgroup, strlen(workgroup)+1, NULL);
     665        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     666                                   "Unix", 5, NULL);
     667
     668        version = talloc_asprintf(talloc_tos(), "Samba %s",
     669                                  samba_version_string());
     670        if (tevent_req_nomem(version, req)){
     671                return tevent_req_post(req, ev);
     672        }
     673        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     674                                   version, strlen(version)+1, NULL);
     675        TALLOC_FREE(version);
     676
     677        if (tevent_req_nomem(bytes, req)) {
     678                return tevent_req_post(req, ev);
     679        }
     680
     681        subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
     682                              talloc_get_size(bytes), bytes);
     683        if (tevent_req_nomem(subreq, req)) {
     684                return tevent_req_post(req, ev);
     685        }
     686        tevent_req_set_callback(subreq, cli_session_setup_plain_done, req);
     687        return req;
     688}
     689
     690static void cli_session_setup_plain_done(struct tevent_req *subreq)
     691{
     692        struct tevent_req *req = tevent_req_callback_data(
     693                subreq, struct tevent_req);
     694        struct cli_session_setup_plain_state *state = tevent_req_data(
     695                req, struct cli_session_setup_plain_state);
     696        struct cli_state *cli = state->cli;
     697        uint32_t num_bytes;
     698        uint8_t *in;
     699        char *inbuf;
     700        uint8_t *bytes;
     701        uint8_t *p;
    360702        NTSTATUS status;
    361         fstring lanman;
    362        
    363         fstr_sprintf( lanman, "Samba %s", samba_version_string());
    364 
    365         memset(cli->outbuf, '\0', smb_size);
    366         cli_set_message(cli->outbuf,13,0,True);
    367         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
    368         cli_setup_packet(cli);
    369                        
    370         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    371         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
    372         SSVAL(cli->outbuf,smb_vwv3,2);
    373         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
    374         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
    375         SSVAL(cli->outbuf,smb_vwv8,0);
    376         SIVAL(cli->outbuf,smb_vwv11,capabilities);
    377         p = smb_buf(cli->outbuf);
    378        
    379         /* check wether to send the ASCII or UNICODE version of the password */
    380        
    381         if ( (capabilities & CAP_UNICODE) == 0 ) {
    382                 p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
    383                 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
    384         }
    385         else {
    386                 /* For ucs2 passwords clistr_push calls ucs2_align, which causes
    387                  * the space taken by the unicode password to be one byte too
    388                  * long (as we're on an odd byte boundary here). Reduce the
    389                  * count by 1 to cope with this. Fixes smbclient against NetApp
    390                  * servers which can't cope. Fix from
    391                  * bryan.kolodziej@allenlund.com in bug #3840.
    392                  */
    393                 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
    394                 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);       
    395         }
    396        
    397         p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
    398         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
    399         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
    400         p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
    401         cli_setup_bcc(cli, p);
    402 
    403         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
    404                 return cli_nt_error(cli);
    405         }
    406        
    407         show_msg(cli->inbuf);
    408        
    409         if (cli_is_error(cli)) {
    410                 return cli_nt_error(cli);
    411         }
    412 
    413         cli->vuid = SVAL(cli->inbuf,smb_uid);
    414         p = smb_buf(cli->inbuf);
    415         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
    416                          -1, STR_TERMINATE);
    417         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
    418                          -1, STR_TERMINATE);
    419         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
    420                          -1, STR_TERMINATE);
    421         status = cli_set_username(cli, user);
    422         if (!NT_STATUS_IS_OK(status)) {
    423                 return status;
     703        ssize_t ret;
     704        uint8_t wct;
     705        uint16_t *vwv;
     706
     707        status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
     708                              &num_bytes, &bytes);
     709        TALLOC_FREE(subreq);
     710        if (tevent_req_nterror(req, status)) {
     711                return;
     712        }
     713
     714        inbuf = (char *)in;
     715        p = bytes;
     716
     717        cli->vuid = SVAL(inbuf, smb_uid);
     718        cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
     719
     720        status = smb_bytes_talloc_string(cli,
     721                                        inbuf,
     722                                        &cli->server_os,
     723                                        p,
     724                                        bytes+num_bytes-p,
     725                                        &ret);
     726
     727        if (!NT_STATUS_IS_OK(status)) {
     728                tevent_req_nterror(req, status);
     729                return;
     730        }
     731        p += ret;
     732
     733        status = smb_bytes_talloc_string(cli,
     734                                        inbuf,
     735                                        &cli->server_type,
     736                                        p,
     737                                        bytes+num_bytes-p,
     738                                        &ret);
     739
     740        if (!NT_STATUS_IS_OK(status)) {
     741                tevent_req_nterror(req, status);
     742                return;
     743        }
     744        p += ret;
     745
     746        status = smb_bytes_talloc_string(cli,
     747                                        inbuf,
     748                                        &cli->server_domain,
     749                                        p,
     750                                        bytes+num_bytes-p,
     751                                        &ret);
     752
     753        if (!NT_STATUS_IS_OK(status)) {
     754                tevent_req_nterror(req, status);
     755                return;
     756        }
     757        p += ret;
     758
     759        status = cli_set_username(cli, state->user);
     760        if (tevent_req_nterror(req, status)) {
     761                return;
    424762        }
    425763        if (strstr(cli->server_type, "Samba")) {
    426764                cli->is_samba = True;
    427765        }
    428 
    429         return NT_STATUS_OK;
     766        tevent_req_done(req);
     767}
     768
     769static NTSTATUS cli_session_setup_plain_recv(struct tevent_req *req)
     770{
     771        return tevent_req_simple_recv_ntstatus(req);
     772}
     773
     774static NTSTATUS cli_session_setup_plain(struct cli_state *cli,
     775                                        const char *user, const char *pass,
     776                                        const char *workgroup)
     777{
     778        TALLOC_CTX *frame = talloc_stackframe();
     779        struct event_context *ev;
     780        struct tevent_req *req;
     781        NTSTATUS status = NT_STATUS_NO_MEMORY;
     782
     783        if (cli_has_async_calls(cli)) {
     784                /*
     785                 * Can't use sync call while an async call is in flight
     786                 */
     787                status = NT_STATUS_INVALID_PARAMETER;
     788                goto fail;
     789        }
     790        ev = event_context_init(frame);
     791        if (ev == NULL) {
     792                goto fail;
     793        }
     794        req = cli_session_setup_plain_send(frame, ev, cli, user, pass,
     795                                           workgroup);
     796        if (req == NULL) {
     797                goto fail;
     798        }
     799        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     800                goto fail;
     801        }
     802        status = cli_session_setup_plain_recv(req);
     803 fail:
     804        TALLOC_FREE(frame);
     805        if (!NT_STATUS_IS_OK(status)) {
     806                cli_set_error(cli, status);
     807        }
     808        return status;
    430809}
    431810
     
    440819****************************************************************************/
    441820
    442 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
    443                                       const char *pass, size_t passlen,
    444                                       const char *ntpass, size_t ntpasslen,
    445                                       const char *workgroup)
    446 {
    447         uint32 capabilities = cli_session_setup_capabilities(cli);
     821struct cli_session_setup_nt1_state {
     822        struct cli_state *cli;
     823        uint16_t vwv[13];
     824        DATA_BLOB response;
     825        DATA_BLOB session_key;
     826        const char *user;
     827};
     828
     829static void cli_session_setup_nt1_done(struct tevent_req *subreq);
     830
     831static struct tevent_req *cli_session_setup_nt1_send(
     832        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     833        struct cli_state *cli, const char *user,
     834        const char *pass, size_t passlen,
     835        const char *ntpass, size_t ntpasslen,
     836        const char *workgroup)
     837{
     838        struct tevent_req *req, *subreq;
     839        struct cli_session_setup_nt1_state *state;
    448840        DATA_BLOB lm_response = data_blob_null;
    449841        DATA_BLOB nt_response = data_blob_null;
    450842        DATA_BLOB session_key = data_blob_null;
    451         NTSTATUS result;
    452         char *p;
    453         bool ok;
     843        uint16_t *vwv;
     844        uint8_t *bytes;
     845        char *workgroup_upper;
     846
     847        req = tevent_req_create(mem_ctx, &state,
     848                                struct cli_session_setup_nt1_state);
     849        if (req == NULL) {
     850                return NULL;
     851        }
     852        state->cli = cli;
     853        state->user = user;
     854        vwv = state->vwv;
    454855
    455856        if (passlen == 0) {
     
    459860                        DATA_BLOB server_chal;
    460861                        DATA_BLOB names_blob;
    461                         server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
    462 
    463                         /* note that the 'workgroup' here is a best guess - we don't know
    464                            the server's domain at this point.  The 'server name' is also
    465                            dodgy...
    466                         */
    467                         names_blob = NTLMv2_generate_names_blob(NULL, cli->called.name, workgroup);
    468 
    469                         if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass, &server_chal,
    470                                               &names_blob,
    471                                               &lm_response, &nt_response, NULL, &session_key)) {
     862
     863                        server_chal = data_blob(cli->secblob.data,
     864                                                MIN(cli->secblob.length, 8));
     865                        if (tevent_req_nomem(server_chal.data, req)) {
     866                                return tevent_req_post(req, ev);
     867                        }
     868
     869                        /*
     870                         * note that the 'workgroup' here is a best
     871                         * guess - we don't know the server's domain
     872                         * at this point.  The 'server name' is also
     873                         * dodgy...
     874                         */
     875                        names_blob = NTLMv2_generate_names_blob(
     876                                NULL, cli->called.name, workgroup);
     877
     878                        if (tevent_req_nomem(names_blob.data, req)) {
     879                                return tevent_req_post(req, ev);
     880                        }
     881
     882                        if (!SMBNTLMv2encrypt(NULL, user, workgroup, pass,
     883                                              &server_chal, &names_blob,
     884                                              &lm_response, &nt_response,
     885                                              NULL, &session_key)) {
    472886                                data_blob_free(&names_blob);
    473887                                data_blob_free(&server_chal);
    474                                 return NT_STATUS_ACCESS_DENIED;
     888                                tevent_req_nterror(
     889                                        req, NT_STATUS_ACCESS_DENIED);
     890                                return tevent_req_post(req, ev);
    475891                        }
    476892                        data_blob_free(&names_blob);
     
    485901#else
    486902                        nt_response = data_blob(NULL, 24);
    487                         SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
     903                        if (tevent_req_nomem(nt_response.data, req)) {
     904                                return tevent_req_post(req, ev);
     905                        }
     906
     907                        SMBNTencrypt(pass, cli->secblob.data,
     908                                     nt_response.data);
    488909#endif
    489910                        /* non encrypted password supplied. Ignore ntpass. */
    490911                        if (lp_client_lanman_auth()) {
     912
    491913                                lm_response = data_blob(NULL, 24);
    492                                 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
    493                                         /* Oops, the LM response is invalid, just put
    494                                            the NT response there instead */
     914                                if (tevent_req_nomem(lm_response.data, req)) {
     915                                        return tevent_req_post(req, ev);
     916                                }
     917
     918                                if (!SMBencrypt(pass,cli->secblob.data,
     919                                                lm_response.data)) {
     920                                        /*
     921                                         * Oops, the LM response is
     922                                         * invalid, just put the NT
     923                                         * response there instead
     924                                         */
    495925                                        data_blob_free(&lm_response);
    496                                         lm_response = data_blob(nt_response.data, nt_response.length);
     926                                        lm_response = data_blob(
     927                                                nt_response.data,
     928                                                nt_response.length);
    497929                                }
    498930                        } else {
    499                                 /* LM disabled, place NT# in LM field instead */
    500                                 lm_response = data_blob(nt_response.data, nt_response.length);
     931                                /*
     932                                 * LM disabled, place NT# in LM field
     933                                 * instead
     934                                 */
     935                                lm_response = data_blob(
     936                                        nt_response.data, nt_response.length);
    501937                        }
    502938
     939                        if (tevent_req_nomem(lm_response.data, req)) {
     940                                return tevent_req_post(req, ev);
     941                        }
     942
    503943                        session_key = data_blob(NULL, 16);
     944                        if (tevent_req_nomem(session_key.data, req)) {
     945                                return tevent_req_post(req, ev);
     946                        }
    504947#ifdef LANMAN_ONLY
    505948                        E_deshash(pass, session_key.data);
     
    516959
    517960                lm_response = data_blob(pass, passlen);
     961                if (tevent_req_nomem(lm_response.data, req)) {
     962                        return tevent_req_post(req, ev);
     963                }
     964
    518965                nt_response = data_blob(ntpass, ntpasslen);
    519         }
    520 
    521         /* send a session setup command */
    522         memset(cli->outbuf,'\0',smb_size);
    523 
    524         cli_set_message(cli->outbuf,13,0,True);
    525         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
    526         cli_setup_packet(cli);
    527                        
    528         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    529         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
    530         SSVAL(cli->outbuf,smb_vwv3,2);
    531         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
    532         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
    533         SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
    534         SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
    535         SIVAL(cli->outbuf,smb_vwv11,capabilities);
    536         p = smb_buf(cli->outbuf);
    537         if (lm_response.length) {
    538                 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
    539         }
    540         if (nt_response.length) {
    541                 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
    542         }
    543         p += clistr_push(cli, p, user, -1, STR_TERMINATE);
    544 
    545         /* Upper case here might help some NTLMv2 implementations */
    546         p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
    547         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
    548         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
    549         cli_setup_bcc(cli, p);
    550 
    551         if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
    552                 result = cli_nt_error(cli);
    553                 goto end;
    554         }
    555 
    556         /* show_msg(cli->inbuf); */
    557 
    558         if (cli_is_error(cli)) {
    559                 result = cli_nt_error(cli);
    560                 goto end;
     966                if (tevent_req_nomem(nt_response.data, req)) {
     967                        return tevent_req_post(req, ev);
     968                }
    561969        }
    562970
    563971#ifdef LANMAN_ONLY
    564         ok = cli_simple_set_signing(cli, session_key, lm_response);
     972        state->response = data_blob_talloc(
     973                state, lm_response.data, lm_response.length);
    565974#else
    566         ok = cli_simple_set_signing(cli, session_key, nt_response);
     975        state->response = data_blob_talloc(
     976                state, nt_response.data, nt_response.length);
    567977#endif
    568         if (ok) {
    569                 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
    570                         result = NT_STATUS_ACCESS_DENIED;
    571                         goto end;
    572                 }
    573         }
    574 
    575         /* use the returned vuid from now on */
    576         cli->vuid = SVAL(cli->inbuf,smb_uid);
    577        
    578         p = smb_buf(cli->inbuf);
    579         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
    580                          -1, STR_TERMINATE);
    581         p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
    582                          -1, STR_TERMINATE);
    583         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
    584                          -1, STR_TERMINATE);
     978        if (tevent_req_nomem(state->response.data, req)) {
     979                return tevent_req_post(req, ev);
     980        }
     981
     982        if (session_key.data) {
     983                state->session_key = data_blob_talloc(
     984                        state, session_key.data, session_key.length);
     985                if (tevent_req_nomem(state->session_key.data, req)) {
     986                        return tevent_req_post(req, ev);
     987                }
     988        }
     989        data_blob_free(&session_key);
     990
     991        SCVAL(vwv+0, 0, 0xff);
     992        SCVAL(vwv+0, 1, 0);
     993        SSVAL(vwv+1, 0, 0);
     994        SSVAL(vwv+2, 0, CLI_BUFFER_SIZE);
     995        SSVAL(vwv+3, 0, 2);
     996        SSVAL(vwv+4, 0, cli->pid);
     997        SIVAL(vwv+5, 0, cli->sesskey);
     998        SSVAL(vwv+7, 0, lm_response.length);
     999        SSVAL(vwv+8, 0, nt_response.length);
     1000        SSVAL(vwv+9, 0, 0);
     1001        SSVAL(vwv+10, 0, 0);
     1002        SIVAL(vwv+11, 0, cli_session_setup_capabilities(cli));
     1003
     1004        bytes = talloc_array(state, uint8_t,
     1005                             lm_response.length + nt_response.length);
     1006        if (tevent_req_nomem(bytes, req)) {
     1007                return tevent_req_post(req, ev);
     1008        }
     1009        if (lm_response.length != 0) {
     1010                memcpy(bytes, lm_response.data, lm_response.length);
     1011        }
     1012        if (nt_response.length != 0) {
     1013                memcpy(bytes + lm_response.length,
     1014                       nt_response.data, nt_response.length);
     1015        }
     1016        data_blob_free(&lm_response);
     1017        data_blob_free(&nt_response);
     1018
     1019        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     1020                                   user, strlen(user)+1, NULL);
     1021
     1022        /*
     1023         * Upper case here might help some NTLMv2 implementations
     1024         */
     1025        workgroup_upper = talloc_strdup_upper(talloc_tos(), workgroup);
     1026        if (tevent_req_nomem(workgroup_upper, req)) {
     1027                return tevent_req_post(req, ev);
     1028        }
     1029        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     1030                                   workgroup_upper, strlen(workgroup_upper)+1,
     1031                                   NULL);
     1032        TALLOC_FREE(workgroup_upper);
     1033
     1034        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Unix", 5, NULL);
     1035        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "Samba", 6, NULL);
     1036        if (tevent_req_nomem(bytes, req)) {
     1037                return tevent_req_post(req, ev);
     1038        }
     1039
     1040        subreq = cli_smb_send(state, ev, cli, SMBsesssetupX, 0, 13, vwv,
     1041                              talloc_get_size(bytes), bytes);
     1042        if (tevent_req_nomem(subreq, req)) {
     1043                return tevent_req_post(req, ev);
     1044        }
     1045        tevent_req_set_callback(subreq, cli_session_setup_nt1_done, req);
     1046        return req;
     1047}
     1048
     1049static void cli_session_setup_nt1_done(struct tevent_req *subreq)
     1050{
     1051        struct tevent_req *req = tevent_req_callback_data(
     1052                subreq, struct tevent_req);
     1053        struct cli_session_setup_nt1_state *state = tevent_req_data(
     1054                req, struct cli_session_setup_nt1_state);
     1055        struct cli_state *cli = state->cli;
     1056        uint32_t num_bytes;
     1057        uint8_t *in;
     1058        char *inbuf;
     1059        uint8_t *bytes;
     1060        uint8_t *p;
     1061        NTSTATUS status;
     1062        ssize_t ret;
     1063        uint8_t wct;
     1064        uint16_t *vwv;
     1065
     1066        status = cli_smb_recv(subreq, state, &in, 3, &wct, &vwv,
     1067                              &num_bytes, &bytes);
     1068        TALLOC_FREE(subreq);
     1069        if (!NT_STATUS_IS_OK(status)) {
     1070                tevent_req_nterror(req, status);
     1071                return;
     1072        }
     1073
     1074        inbuf = (char *)in;
     1075        p = bytes;
     1076
     1077        cli->vuid = SVAL(inbuf, smb_uid);
     1078        cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
     1079
     1080        status = smb_bytes_talloc_string(cli,
     1081                                        inbuf,
     1082                                        &cli->server_os,
     1083                                        p,
     1084                                        bytes+num_bytes-p,
     1085                                        &ret);
     1086        if (!NT_STATUS_IS_OK(status)) {
     1087                tevent_req_nterror(req, status);
     1088                return;
     1089        }
     1090        p += ret;
     1091
     1092        status = smb_bytes_talloc_string(cli,
     1093                                        inbuf,
     1094                                        &cli->server_type,
     1095                                        p,
     1096                                        bytes+num_bytes-p,
     1097                                        &ret);
     1098        if (!NT_STATUS_IS_OK(status)) {
     1099                tevent_req_nterror(req, status);
     1100                return;
     1101        }
     1102        p += ret;
     1103
     1104        status = smb_bytes_talloc_string(cli,
     1105                                        inbuf,
     1106                                        &cli->server_domain,
     1107                                        p,
     1108                                        bytes+num_bytes-p,
     1109                                        &ret);
     1110        if (!NT_STATUS_IS_OK(status)) {
     1111                tevent_req_nterror(req, status);
     1112                return;
     1113        }
     1114        p += ret;
    5851115
    5861116        if (strstr(cli->server_type, "Samba")) {
     
    5881118        }
    5891119
    590         result = cli_set_username(cli, user);
    591         if (!NT_STATUS_IS_OK(result)) {
    592                 goto end;
    593         }
    594 
    595         if (session_key.data) {
     1120        status = cli_set_username(cli, state->user);
     1121        if (tevent_req_nterror(req, status)) {
     1122                return;
     1123        }
     1124        if (cli_simple_set_signing(cli, state->session_key, state->response)
     1125            && !cli_check_sign_mac(cli, (char *)in, 1)) {
     1126                tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     1127                return;
     1128        }
     1129        if (state->session_key.data) {
    5961130                /* Have plaintext orginal */
    597                 cli_set_session_key(cli, session_key);
    598         }
    599 
    600         result = NT_STATUS_OK;
    601 end:   
    602         data_blob_free(&lm_response);
    603         data_blob_free(&nt_response);
    604         data_blob_free(&session_key);
    605         return result;
    606 }
    607 
    608 /****************************************************************************
    609  Send a extended security session setup blob
    610 ****************************************************************************/
    611 
    612 static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
    613 {
    614         uint32 capabilities = cli_session_setup_capabilities(cli);
    615         char *p;
    616 
    617         capabilities |= CAP_EXTENDED_SECURITY;
    618 
    619         /* send a session setup command */
    620         memset(cli->outbuf,'\0',smb_size);
    621 
    622         cli_set_message(cli->outbuf,12,0,True);
    623         SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
    624 
    625         cli_setup_packet(cli);
    626 
    627         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    628         SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
    629         SSVAL(cli->outbuf,smb_vwv3,2);
    630         SSVAL(cli->outbuf,smb_vwv4,1);
    631         SIVAL(cli->outbuf,smb_vwv5,0);
    632         SSVAL(cli->outbuf,smb_vwv7,blob.length);
    633         SIVAL(cli->outbuf,smb_vwv10,capabilities);
    634         p = smb_buf(cli->outbuf);
    635         memcpy(p, blob.data, blob.length);
    636         p += blob.length;
    637         p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
    638         p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
    639         cli_setup_bcc(cli, p);
    640         return cli_send_smb(cli);
    641 }
    642 
    643 /****************************************************************************
    644  Send a extended security session setup blob, returning a reply blob.
    645 ****************************************************************************/
    646 
    647 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
    648 {
    649         DATA_BLOB blob2 = data_blob_null;
    650         char *p;
    651         size_t len;
    652 
    653         if (!cli_receive_smb(cli))
    654                 return blob2;
    655 
    656         show_msg(cli->inbuf);
    657 
    658         if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
    659                                                   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    660                 return blob2;
    661         }
    662 
    663         /* use the returned vuid from now on */
    664         cli->vuid = SVAL(cli->inbuf,smb_uid);
    665 
    666         p = smb_buf(cli->inbuf);
    667 
    668         blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
    669 
    670         p += blob2.length;
    671         p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
    672                          -1, STR_TERMINATE);
    673 
    674         /* w2k with kerberos doesn't properly null terminate this field */
    675         len = smb_bufrem(cli->inbuf, p);
    676         if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
    677                 char *end_of_buf = p + len;
    678 
    679                 SSVAL(p, len, 0);
    680                 /* Now it's null terminated. */
    681                 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
    682                         -1, STR_TERMINATE);
     1131                cli_set_session_key(cli, state->session_key);
     1132        }
     1133        tevent_req_done(req);
     1134}
     1135
     1136static NTSTATUS cli_session_setup_nt1_recv(struct tevent_req *req)
     1137{
     1138        return tevent_req_simple_recv_ntstatus(req);
     1139}
     1140
     1141static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
     1142                                      const char *pass, size_t passlen,
     1143                                      const char *ntpass, size_t ntpasslen,
     1144                                      const char *workgroup)
     1145{
     1146        TALLOC_CTX *frame = talloc_stackframe();
     1147        struct event_context *ev;
     1148        struct tevent_req *req;
     1149        NTSTATUS status = NT_STATUS_NO_MEMORY;
     1150
     1151        if (cli_has_async_calls(cli)) {
    6831152                /*
    684                  * See if there's another string. If so it's the
    685                  * server domain (part of the 'standard' Samba
    686                  * server signature).
     1153                 * Can't use sync call while an async call is in flight
    6871154                 */
    688                 if (p < end_of_buf) {
    689                         p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
    690                                 -1, STR_TERMINATE);
    691                 }
    692         } else {
    693                 /*
    694                  * No room to null terminate so we can't see if there
    695                  * is another string (server_domain) afterwards.
    696                  */
    697                 p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
    698                                  len, 0);
    699         }
    700         return blob2;
    701 }
    702 
    703 #ifdef HAVE_KRB5
    704 /****************************************************************************
    705  Send a extended security session setup blob, returning a reply blob.
    706 ****************************************************************************/
     1155                status = NT_STATUS_INVALID_PARAMETER;
     1156                goto fail;
     1157        }
     1158        ev = event_context_init(frame);
     1159        if (ev == NULL) {
     1160                goto fail;
     1161        }
     1162        req = cli_session_setup_nt1_send(frame, ev, cli, user, pass, passlen,
     1163                                         ntpass, ntpasslen, workgroup);
     1164        if (req == NULL) {
     1165                goto fail;
     1166        }
     1167        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     1168                goto fail;
     1169        }
     1170        status = cli_session_setup_nt1_recv(req);
     1171 fail:
     1172        TALLOC_FREE(frame);
     1173        if (!NT_STATUS_IS_OK(status)) {
     1174                cli_set_error(cli, status);
     1175        }
     1176        return status;
     1177}
    7071178
    7081179/* The following is calculated from :
     
    7151186#define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
    7161187
    717 static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
    718 {
    719         int32 remaining = blob.length;
    720         int32 cur = 0;
    721         DATA_BLOB send_blob = data_blob_null;
    722         int32 max_blob_size = 0;
    723         DATA_BLOB receive_blob = data_blob_null;
     1188struct cli_sesssetup_blob_state {
     1189        struct tevent_context *ev;
     1190        struct cli_state *cli;
     1191        DATA_BLOB blob;
     1192        uint16_t max_blob_size;
     1193        uint16_t vwv[12];
     1194        uint8_t *buf;
     1195
     1196        NTSTATUS status;
     1197        char *inbuf;
     1198        DATA_BLOB ret_blob;
     1199};
     1200
     1201static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
     1202                                    struct tevent_req **psubreq);
     1203static void cli_sesssetup_blob_done(struct tevent_req *subreq);
     1204
     1205static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
     1206                                                  struct tevent_context *ev,
     1207                                                  struct cli_state *cli,
     1208                                                  DATA_BLOB blob)
     1209{
     1210        struct tevent_req *req, *subreq;
     1211        struct cli_sesssetup_blob_state *state;
     1212
     1213        req = tevent_req_create(mem_ctx, &state,
     1214                                struct cli_sesssetup_blob_state);
     1215        if (req == NULL) {
     1216                return NULL;
     1217        }
     1218        state->ev = ev;
     1219        state->blob = blob;
     1220        state->cli = cli;
    7241221
    7251222        if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
    726                 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
    727                         "(was %u, need minimum %u)\n",
    728                         (unsigned int)cli->max_xmit,
    729                         BASE_SESSSETUP_BLOB_PACKET_SIZE));
    730                 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
    731                 return False;
    732         }
    733 
    734         max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
    735 
    736         while ( remaining > 0) {
    737                 if (remaining >= max_blob_size) {
    738                         send_blob.length = max_blob_size;
    739                         remaining -= max_blob_size;
    740                 } else {
    741                         send_blob.length = remaining;
    742                         remaining = 0;
    743                 }
    744 
    745                 send_blob.data =  &blob.data[cur];
    746                 cur += send_blob.length;
    747 
    748                 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
    749                         (unsigned int)remaining,
    750                         (unsigned int)send_blob.length,
    751                         (unsigned int)cur ));
    752 
    753                 if (!cli_session_setup_blob_send(cli, send_blob)) {
    754                         DEBUG(0, ("cli_session_setup_blob: send failed\n"));
    755                         return False;
    756                 }
    757 
    758                 receive_blob = cli_session_setup_blob_receive(cli);
    759                 data_blob_free(&receive_blob);
    760 
    761                 if (cli_is_error(cli) &&
    762                                 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
    763                                         NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    764                         DEBUG(0, ("cli_session_setup_blob: receive failed "
    765                                   "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
    766                         cli->vuid = 0;
    767                         return False;
    768                 }
    769         }
    770 
    771         return True;
    772 }
     1223                DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
     1224                          "(was %u, need minimum %u)\n",
     1225                          (unsigned int)cli->max_xmit,
     1226                          BASE_SESSSETUP_BLOB_PACKET_SIZE));
     1227                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     1228                return tevent_req_post(req, ev);
     1229        }
     1230        state->max_blob_size =
     1231                MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
     1232
     1233        if (!cli_sesssetup_blob_next(state, &subreq)) {
     1234                tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     1235                return tevent_req_post(req, ev);
     1236        }
     1237        tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
     1238        return req;
     1239}
     1240
     1241static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
     1242                                    struct tevent_req **psubreq)
     1243{
     1244        struct tevent_req *subreq;
     1245        uint16_t thistime;
     1246
     1247        SCVAL(state->vwv+0, 0, 0xFF);
     1248        SCVAL(state->vwv+0, 1, 0);
     1249        SSVAL(state->vwv+1, 0, 0);
     1250        SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
     1251        SSVAL(state->vwv+3, 0, 2);
     1252        SSVAL(state->vwv+4, 0, 1);
     1253        SIVAL(state->vwv+5, 0, 0);
     1254
     1255        thistime = MIN(state->blob.length, state->max_blob_size);
     1256        SSVAL(state->vwv+7, 0, thistime);
     1257
     1258        SSVAL(state->vwv+8, 0, 0);
     1259        SSVAL(state->vwv+9, 0, 0);
     1260        SIVAL(state->vwv+10, 0,
     1261              cli_session_setup_capabilities(state->cli)
     1262              | CAP_EXTENDED_SECURITY);
     1263
     1264        state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
     1265                                              thistime);
     1266        if (state->buf == NULL) {
     1267                return false;
     1268        }
     1269        state->blob.data += thistime;
     1270        state->blob.length -= thistime;
     1271
     1272        state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
     1273                                        "Unix", 5, NULL);
     1274        state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
     1275                                        "Samba", 6, NULL);
     1276        if (state->buf == NULL) {
     1277                return false;
     1278        }
     1279        subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
     1280                              12, state->vwv,
     1281                              talloc_get_size(state->buf), state->buf);
     1282        if (subreq == NULL) {
     1283                return false;
     1284        }
     1285        *psubreq = subreq;
     1286        return true;
     1287}
     1288
     1289static void cli_sesssetup_blob_done(struct tevent_req *subreq)
     1290{
     1291        struct tevent_req *req = tevent_req_callback_data(
     1292                subreq, struct tevent_req);
     1293        struct cli_sesssetup_blob_state *state = tevent_req_data(
     1294                req, struct cli_sesssetup_blob_state);
     1295        struct cli_state *cli = state->cli;
     1296        uint8_t wct;
     1297        uint16_t *vwv;
     1298        uint32_t num_bytes;
     1299        uint8_t *bytes;
     1300        NTSTATUS status;
     1301        uint8_t *p;
     1302        uint16_t blob_length;
     1303        uint8_t *inbuf;
     1304        ssize_t ret;
     1305
     1306        status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv,
     1307                              &num_bytes, &bytes);
     1308        TALLOC_FREE(subreq);
     1309        if (!NT_STATUS_IS_OK(status)
     1310            && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     1311                tevent_req_nterror(req, status);
     1312                return;
     1313        }
     1314
     1315        state->status = status;
     1316        TALLOC_FREE(state->buf);
     1317
     1318        state->inbuf = (char *)inbuf;
     1319        cli->vuid = SVAL(state->inbuf, smb_uid);
     1320        cli->is_guestlogin = ((SVAL(vwv+2, 0) & 1) != 0);
     1321
     1322        blob_length = SVAL(vwv+3, 0);
     1323        if (blob_length > num_bytes) {
     1324                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     1325                return;
     1326        }
     1327        state->ret_blob = data_blob_const(bytes, blob_length);
     1328
     1329        p = bytes + blob_length;
     1330
     1331        status = smb_bytes_talloc_string(cli,
     1332                                        (char *)inbuf,
     1333                                        &cli->server_os,
     1334                                        p,
     1335                                        bytes+num_bytes-p,
     1336                                        &ret);
     1337
     1338        if (!NT_STATUS_IS_OK(status)) {
     1339                tevent_req_nterror(req, status);
     1340                return;
     1341        }
     1342        p += ret;
     1343
     1344        status = smb_bytes_talloc_string(cli,
     1345                                        (char *)inbuf,
     1346                                        &cli->server_type,
     1347                                        p,
     1348                                        bytes+num_bytes-p,
     1349                                        &ret);
     1350
     1351        if (!NT_STATUS_IS_OK(status)) {
     1352                tevent_req_nterror(req, status);
     1353                return;
     1354        }
     1355        p += ret;
     1356
     1357        status = smb_bytes_talloc_string(cli,
     1358                                        (char *)inbuf,
     1359                                        &cli->server_domain,
     1360                                        p,
     1361                                        bytes+num_bytes-p,
     1362                                        &ret);
     1363
     1364        if (!NT_STATUS_IS_OK(status)) {
     1365                tevent_req_nterror(req, status);
     1366                return;
     1367        }
     1368        p += ret;
     1369
     1370        if (strstr(cli->server_type, "Samba")) {
     1371                cli->is_samba = True;
     1372        }
     1373
     1374        if (state->blob.length != 0) {
     1375                /*
     1376                 * More to send
     1377                 */
     1378                if (!cli_sesssetup_blob_next(state, &subreq)) {
     1379                        tevent_req_nomem(NULL, req);
     1380                        return;
     1381                }
     1382                tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
     1383                return;
     1384        }
     1385        tevent_req_done(req);
     1386}
     1387
     1388static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
     1389                                        TALLOC_CTX *mem_ctx,
     1390                                        DATA_BLOB *pblob,
     1391                                        char **pinbuf)
     1392{
     1393        struct cli_sesssetup_blob_state *state = tevent_req_data(
     1394                req, struct cli_sesssetup_blob_state);
     1395        NTSTATUS status;
     1396        char *inbuf;
     1397
     1398        if (tevent_req_is_nterror(req, &status)) {
     1399                state->cli->vuid = 0;
     1400                return status;
     1401        }
     1402
     1403        inbuf = talloc_move(mem_ctx, &state->inbuf);
     1404        if (pblob != NULL) {
     1405                *pblob = state->ret_blob;
     1406        }
     1407        if (pinbuf != NULL) {
     1408                *pinbuf = inbuf;
     1409        }
     1410        /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
     1411        return state->status;
     1412}
     1413
     1414#ifdef HAVE_KRB5
    7731415
    7741416/****************************************************************************
     
    7841426****************************************************************************/
    7851427
    786 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
    787 {
     1428struct cli_session_setup_kerberos_state {
     1429        struct cli_state *cli;
    7881430        DATA_BLOB negTokenTarg;
    7891431        DATA_BLOB session_key_krb5;
    790         NTSTATUS nt_status;
     1432        ADS_STATUS ads_status;
     1433};
     1434
     1435static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
     1436
     1437static struct tevent_req *cli_session_setup_kerberos_send(
     1438        TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
     1439        const char *principal, const char *workgroup)
     1440{
     1441        struct tevent_req *req, *subreq;
     1442        struct cli_session_setup_kerberos_state *state;
    7911443        int rc;
    7921444
     1445        DEBUG(2,("Doing kerberos session setup\n"));
     1446
     1447        req = tevent_req_create(mem_ctx, &state,
     1448                                struct cli_session_setup_kerberos_state);
     1449        if (req == NULL) {
     1450                return NULL;
     1451        }
     1452        state->cli = cli;
     1453        state->ads_status = ADS_SUCCESS;
     1454
    7931455        cli_temp_set_signing(cli);
    7941456
    795         DEBUG(2,("Doing kerberos session setup\n"));
    796 
    797         /* generate the encapsulated kerberos5 ticket */
    798         rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
    799 
     1457        /*
     1458         * Ok, this is cheating: spnego_gen_krb5_negTokenInit can block if
     1459         * we have to acquire a ticket. To be fixed later :-)
     1460         */
     1461        rc = spnego_gen_krb5_negTokenInit(state, principal, 0, &state->negTokenTarg,
     1462                                     &state->session_key_krb5, 0, NULL);
    8001463        if (rc) {
    801                 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
    802                         error_message(rc)));
    803                 return ADS_ERROR_KRB5(rc);
     1464                DEBUG(1, ("cli_session_setup_kerberos: "
     1465                          "spnego_gen_krb5_negTokenInit failed: %s\n",
     1466                          error_message(rc)));
     1467                state->ads_status = ADS_ERROR_KRB5(rc);
     1468                tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
     1469                return tevent_req_post(req, ev);
    8041470        }
    8051471
    8061472#if 0
    807         file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
     1473        file_save("negTokenTarg.dat", state->negTokenTarg.data,
     1474                  state->negTokenTarg.length);
    8081475#endif
    8091476
    810         if (!cli_session_setup_blob(cli, negTokenTarg)) {
    811                 nt_status = cli_nt_error(cli);
    812                 goto nt_error;
    813         }
    814 
    815         if (cli_is_error(cli)) {
    816                 nt_status = cli_nt_error(cli);
    817                 if (NT_STATUS_IS_OK(nt_status)) {
    818                         nt_status = NT_STATUS_UNSUCCESSFUL;
    819                 }
    820                 goto nt_error;
    821         }
    822 
    823         cli_set_session_key(cli, session_key_krb5);
    824 
    825         if (cli_simple_set_signing(
    826                     cli, session_key_krb5, data_blob_null)) {
    827 
    828                 if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
    829                         nt_status = NT_STATUS_ACCESS_DENIED;
    830                         goto nt_error;
    831                 }
    832         }
    833 
    834         data_blob_free(&negTokenTarg);
    835         data_blob_free(&session_key_krb5);
    836 
    837         return ADS_ERROR_NT(NT_STATUS_OK);
    838 
    839 nt_error:
    840         data_blob_free(&negTokenTarg);
    841         data_blob_free(&session_key_krb5);
    842         cli->vuid = 0;
    843         return ADS_ERROR_NT(nt_status);
     1477        subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
     1478        if (tevent_req_nomem(subreq, req)) {
     1479                return tevent_req_post(req, ev);
     1480        }
     1481        tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
     1482        return req;
     1483}
     1484
     1485static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
     1486{
     1487        struct tevent_req *req = tevent_req_callback_data(
     1488                subreq, struct tevent_req);
     1489        struct cli_session_setup_kerberos_state *state = tevent_req_data(
     1490                req, struct cli_session_setup_kerberos_state);
     1491        char *inbuf = NULL;
     1492        NTSTATUS status;
     1493
     1494        status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
     1495        if (!NT_STATUS_IS_OK(status)) {
     1496                TALLOC_FREE(subreq);
     1497                tevent_req_nterror(req, status);
     1498                return;
     1499        }
     1500
     1501        cli_set_session_key(state->cli, state->session_key_krb5);
     1502
     1503        if (cli_simple_set_signing(state->cli, state->session_key_krb5,
     1504                                   data_blob_null)
     1505            && !cli_check_sign_mac(state->cli, inbuf, 1)) {
     1506                TALLOC_FREE(subreq);
     1507                tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     1508                return;
     1509        }
     1510        TALLOC_FREE(subreq);
     1511        tevent_req_done(req);
     1512}
     1513
     1514static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
     1515{
     1516        struct cli_session_setup_kerberos_state *state = tevent_req_data(
     1517                req, struct cli_session_setup_kerberos_state);
     1518        NTSTATUS status;
     1519
     1520        if (tevent_req_is_nterror(req, &status)) {
     1521                return ADS_ERROR_NT(status);
     1522        }
     1523        return state->ads_status;
     1524}
     1525
     1526static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
     1527                                             const char *principal,
     1528                                             const char *workgroup)
     1529{
     1530        struct tevent_context *ev;
     1531        struct tevent_req *req;
     1532        ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     1533
     1534        if (cli_has_async_calls(cli)) {
     1535                return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
     1536        }
     1537        ev = tevent_context_init(talloc_tos());
     1538        if (ev == NULL) {
     1539                goto fail;
     1540        }
     1541        req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
     1542                                              workgroup);
     1543        if (req == NULL) {
     1544                goto fail;
     1545        }
     1546        if (!tevent_req_poll(req, ev)) {
     1547                status = ADS_ERROR_SYSTEM(errno);
     1548                goto fail;
     1549        }
     1550        status = cli_session_setup_kerberos_recv(req);
     1551fail:
     1552        TALLOC_FREE(ev);
     1553        return status;
    8441554}
    8451555#endif  /* HAVE_KRB5 */
    846 
    8471556
    8481557/****************************************************************************
     
    8501559****************************************************************************/
    8511560
    852 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
    853                                           const char *pass, const char *domain)
    854 {
     1561struct cli_session_setup_ntlmssp_state {
     1562        struct tevent_context *ev;
     1563        struct cli_state *cli;
    8551564        struct ntlmssp_state *ntlmssp_state;
    856         NTSTATUS nt_status;
    857         int turn = 1;
    858         DATA_BLOB msg1;
    859         DATA_BLOB blob = data_blob_null;
    860         DATA_BLOB blob_in = data_blob_null;
    861         DATA_BLOB blob_out = data_blob_null;
     1565        int turn;
     1566        DATA_BLOB blob_out;
     1567};
     1568
     1569static int cli_session_setup_ntlmssp_state_destructor(
     1570        struct cli_session_setup_ntlmssp_state *state)
     1571{
     1572        if (state->ntlmssp_state != NULL) {
     1573                TALLOC_FREE(state->ntlmssp_state);
     1574        }
     1575        return 0;
     1576}
     1577
     1578static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
     1579
     1580static struct tevent_req *cli_session_setup_ntlmssp_send(
     1581        TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
     1582        const char *user, const char *pass, const char *domain)
     1583{
     1584        struct tevent_req *req, *subreq;
     1585        struct cli_session_setup_ntlmssp_state *state;
     1586        NTSTATUS status;
     1587        DATA_BLOB blob_out;
     1588        const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
     1589
     1590        req = tevent_req_create(mem_ctx, &state,
     1591                                struct cli_session_setup_ntlmssp_state);
     1592        if (req == NULL) {
     1593                return NULL;
     1594        }
     1595        state->ev = ev;
     1596        state->cli = cli;
     1597        state->turn = 1;
     1598
     1599        state->ntlmssp_state = NULL;
     1600        talloc_set_destructor(
     1601                state, cli_session_setup_ntlmssp_state_destructor);
    8621602
    8631603        cli_temp_set_signing(cli);
    8641604
    865         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
    866                 return nt_status;
    867         }
    868         ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
     1605        status = ntlmssp_client_start(state,
     1606                                      global_myname(),
     1607                                      lp_workgroup(),
     1608                                      lp_client_ntlmv2_auth(),
     1609                                      &state->ntlmssp_state);
     1610        if (!NT_STATUS_IS_OK(status)) {
     1611                goto fail;
     1612        }
     1613        ntlmssp_want_feature(state->ntlmssp_state,
     1614                             NTLMSSP_FEATURE_SESSION_KEY);
    8691615        if (cli->use_ccache) {
    870                 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_CCACHE);
    871         }
    872 
    873         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
    874                 return nt_status;
    875         }
    876         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
    877                 return nt_status;
    878         }
    879         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
    880                 return nt_status;
    881         }
    882 
    883         do {
    884                 nt_status = ntlmssp_update(ntlmssp_state,
    885                                                   blob_in, &blob_out);
    886                 data_blob_free(&blob_in);
    887                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
    888                         if (turn == 1) {
    889                                 /* and wrap it in a SPNEGO wrapper */
    890                                 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
    891                         } else {
    892                                 /* wrap it in SPNEGO */
    893                                 msg1 = spnego_gen_auth(blob_out);
     1616                ntlmssp_want_feature(state->ntlmssp_state,
     1617                                     NTLMSSP_FEATURE_CCACHE);
     1618        }
     1619        status = ntlmssp_set_username(state->ntlmssp_state, user);
     1620        if (!NT_STATUS_IS_OK(status)) {
     1621                goto fail;
     1622        }
     1623        status = ntlmssp_set_domain(state->ntlmssp_state, domain);
     1624        if (!NT_STATUS_IS_OK(status)) {
     1625                goto fail;
     1626        }
     1627        status = ntlmssp_set_password(state->ntlmssp_state, pass);
     1628        if (!NT_STATUS_IS_OK(status)) {
     1629                goto fail;
     1630        }
     1631        status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
     1632                                &blob_out);
     1633        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     1634                goto fail;
     1635        }
     1636
     1637        state->blob_out = spnego_gen_negTokenInit(state, OIDs_ntlm, &blob_out, NULL);
     1638        data_blob_free(&blob_out);
     1639
     1640        subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
     1641        if (tevent_req_nomem(subreq, req)) {
     1642                return tevent_req_post(req, ev);
     1643        }
     1644        tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
     1645        return req;
     1646fail:
     1647        tevent_req_nterror(req, status);
     1648        return tevent_req_post(req, ev);
     1649}
     1650
     1651static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
     1652{
     1653        struct tevent_req *req = tevent_req_callback_data(
     1654                subreq, struct tevent_req);
     1655        struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
     1656                req, struct cli_session_setup_ntlmssp_state);
     1657        DATA_BLOB blob_in, msg_in, blob_out;
     1658        char *inbuf = NULL;
     1659        bool parse_ret;
     1660        NTSTATUS status;
     1661
     1662        status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
     1663                                         &inbuf);
     1664        TALLOC_FREE(subreq);
     1665        data_blob_free(&state->blob_out);
     1666
     1667        if (NT_STATUS_IS_OK(status)) {
     1668                if (state->cli->server_domain[0] == '\0') {
     1669                        TALLOC_FREE(state->cli->server_domain);
     1670                        state->cli->server_domain = talloc_strdup(state->cli,
     1671                                                state->ntlmssp_state->server.netbios_domain);
     1672                        if (state->cli->server_domain == NULL) {
     1673                                TALLOC_FREE(subreq);
     1674                                tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     1675                                return;
    8941676                        }
    895 
    896                         /* now send that blob on its way */
    897                         if (!cli_session_setup_blob_send(cli, msg1)) {
    898                                 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
    899                                 nt_status = NT_STATUS_UNSUCCESSFUL;
    900                         } else {
    901                                 blob = cli_session_setup_blob_receive(cli);
    902 
    903                                 nt_status = cli_nt_error(cli);
    904                                 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
    905                                         if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
    906                                                 nt_status = NT_STATUS_ACCESS_DENIED;
    907                                         } else {
    908                                                 nt_status = NT_STATUS_UNSUCCESSFUL;
    909                                         }
    910                                 }
    911                         }
    912                         data_blob_free(&msg1);
    913                 }
    914 
    915                 if (!blob.length) {
    916                         if (NT_STATUS_IS_OK(nt_status)) {
    917                                 nt_status = NT_STATUS_UNSUCCESSFUL;
    918                         }
    919                 } else if ((turn == 1) &&
    920                            NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    921                         DATA_BLOB tmp_blob = data_blob_null;
    922                         /* the server might give us back two challenges */
    923                         if (!spnego_parse_challenge(blob, &blob_in,
    924                                                     &tmp_blob)) {
    925                                 DEBUG(3,("Failed to parse challenges\n"));
    926                                 nt_status = NT_STATUS_INVALID_PARAMETER;
    927                         }
    928                         data_blob_free(&tmp_blob);
    929                 } else {
    930                         if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
    931                                                         &blob_in)) {
    932                                 DEBUG(3,("Failed to parse auth response\n"));
    933                                 if (NT_STATUS_IS_OK(nt_status)
    934                                     || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
    935                                         nt_status = NT_STATUS_INVALID_PARAMETER;
    936                         }
    937                 }
    938                 data_blob_free(&blob);
    939                 data_blob_free(&blob_out);
    940                 turn++;
    941         } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
    942 
    943         data_blob_free(&blob_in);
    944 
    945         if (NT_STATUS_IS_OK(nt_status)) {
    946 
    947                 if (cli->server_domain[0] == '\0') {
    948                         fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
    949                 }
    950                 cli_set_session_key(cli, ntlmssp_state->session_key);
     1677                }
     1678                cli_set_session_key(
     1679                        state->cli, state->ntlmssp_state->session_key);
    9511680
    9521681                if (cli_simple_set_signing(
    953                             cli, ntlmssp_state->session_key, data_blob_null)) {
    954 
    955                         if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
    956                                 nt_status = NT_STATUS_ACCESS_DENIED;
    957                         }
    958                 }
    959         }
    960 
    961         /* we have a reference conter on ntlmssp_state, if we are signing
    962            then the state will be kept by the signing engine */
    963 
    964         ntlmssp_end(&ntlmssp_state);
    965 
    966         if (!NT_STATUS_IS_OK(nt_status)) {
    967                 cli->vuid = 0;
    968         }
    969         return nt_status;
     1682                            state->cli, state->ntlmssp_state->session_key,
     1683                            data_blob_null)
     1684                    && !cli_check_sign_mac(state->cli, inbuf, 1)) {
     1685                        TALLOC_FREE(subreq);
     1686                        tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
     1687                        return;
     1688                }
     1689                TALLOC_FREE(subreq);
     1690                TALLOC_FREE(state->ntlmssp_state);
     1691                tevent_req_done(req);
     1692                return;
     1693        }
     1694        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     1695                tevent_req_nterror(req, status);
     1696                return;
     1697        }
     1698
     1699        if (blob_in.length == 0) {
     1700                tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
     1701                return;
     1702        }
     1703
     1704        if ((state->turn == 1)
     1705            && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     1706                DATA_BLOB tmp_blob = data_blob_null;
     1707                /* the server might give us back two challenges */
     1708                parse_ret = spnego_parse_challenge(state, blob_in, &msg_in,
     1709                                                   &tmp_blob);
     1710                data_blob_free(&tmp_blob);
     1711        } else {
     1712                parse_ret = spnego_parse_auth_response(state, blob_in, status,
     1713                                                       OID_NTLMSSP, &msg_in);
     1714        }
     1715        state->turn += 1;
     1716
     1717        if (!parse_ret) {
     1718                DEBUG(3,("Failed to parse auth response\n"));
     1719                if (NT_STATUS_IS_OK(status)
     1720                    || NT_STATUS_EQUAL(status,
     1721                                       NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     1722                        tevent_req_nterror(
     1723                                req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     1724                        return;
     1725                }
     1726        }
     1727
     1728        status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
     1729
     1730        if (!NT_STATUS_IS_OK(status)
     1731            && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     1732                TALLOC_FREE(subreq);
     1733                TALLOC_FREE(state->ntlmssp_state);
     1734                tevent_req_nterror(req, status);
     1735                return;
     1736        }
     1737
     1738        state->blob_out = spnego_gen_auth(state, blob_out);
     1739        TALLOC_FREE(subreq);
     1740        if (tevent_req_nomem(state->blob_out.data, req)) {
     1741                return;
     1742        }
     1743
     1744        subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
     1745                                         state->blob_out);
     1746        if (tevent_req_nomem(subreq, req)) {
     1747                return;
     1748        }
     1749        tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
     1750}
     1751
     1752static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
     1753{
     1754        struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
     1755                req, struct cli_session_setup_ntlmssp_state);
     1756        NTSTATUS status;
     1757
     1758        if (tevent_req_is_nterror(req, &status)) {
     1759                state->cli->vuid = 0;
     1760                return status;
     1761        }
     1762        return NT_STATUS_OK;
     1763}
     1764
     1765static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
     1766                                          const char *user,
     1767                                          const char *pass,
     1768                                          const char *domain)
     1769{
     1770        struct tevent_context *ev;
     1771        struct tevent_req *req;
     1772        NTSTATUS status = NT_STATUS_NO_MEMORY;
     1773
     1774        if (cli_has_async_calls(cli)) {
     1775                return NT_STATUS_INVALID_PARAMETER;
     1776        }
     1777        ev = tevent_context_init(talloc_tos());
     1778        if (ev == NULL) {
     1779                goto fail;
     1780        }
     1781        req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
     1782        if (req == NULL) {
     1783                goto fail;
     1784        }
     1785        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     1786                goto fail;
     1787        }
     1788        status = cli_session_setup_ntlmssp_recv(req);
     1789fail:
     1790        TALLOC_FREE(ev);
     1791        if (!NT_STATUS_IS_OK(status)) {
     1792                cli_set_error(cli, status);
     1793        }
     1794        return status;
    9701795}
    9711796
     
    10081833         * negprot reply, but right now we do it. If we don't receive one,
    10091834         * we try to best guess, then fall back to NTLM.  */
    1010         if (!spnego_parse_negTokenInit(blob, OIDs, &principal) ||
     1835        if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &principal, NULL) ||
    10111836                        OIDs[0] == NULL) {
    10121837                data_blob_free(&blob);
     
    10321857        status = cli_set_username(cli, user);
    10331858        if (!NT_STATUS_IS_OK(status)) {
     1859                TALLOC_FREE(principal);
    10341860                return ADS_ERROR_NT(status);
    10351861        }
     
    10751901                        if (dest_realm) {
    10761902                                realm = SMB_STRDUP(dest_realm);
     1903                                if (!realm) {
     1904                                        return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     1905                                }
    10771906                                strupper_m(realm);
    10781907                        } else {
     
    10861915                        }
    10871916
    1088                         if (realm && *realm) {
    1089                                 principal = talloc_asprintf(talloc_tos(),
    1090                                                             "cifs/%s@%s",
    1091                                                             cli->desthost,
    1092                                                             realm);
    1093                                 if (!principal) {
    1094                                         SAFE_FREE(realm);
     1917                        if (realm == NULL || *realm == '\0') {
     1918                                realm = SMB_STRDUP(lp_realm());
     1919                                if (!realm) {
    10951920                                        return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
    10961921                                }
    1097                                 DEBUG(3,("cli_session_setup_spnego: guessed "
    1098                                         "server principal=%s\n",
    1099                                         principal ? principal : "<null>"));
     1922                                strupper_m(realm);
     1923                                DEBUG(3,("cli_session_setup_spnego: cannot "
     1924                                        "get realm from dest_realm %s, "
     1925                                        "desthost %s. Using default "
     1926                                        "smb.conf realm %s\n",
     1927                                        dest_realm ? dest_realm : "<null>",
     1928                                        cli->desthost,
     1929                                        realm));
    11001930                        }
     1931
     1932                        principal = talloc_asprintf(talloc_tos(),
     1933                                                    "cifs/%s@%s",
     1934                                                    cli->desthost,
     1935                                                    realm);
     1936                        if (!principal) {
     1937                                SAFE_FREE(realm);
     1938                                return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     1939                        }
     1940                        DEBUG(3,("cli_session_setup_spnego: guessed "
     1941                                "server principal=%s\n",
     1942                                principal ? principal : "<null>"));
     1943
    11011944                        SAFE_FREE(realm);
    11021945                }
     
    11451988{
    11461989        char *p;
    1147         fstring user2;
     1990        char *user2;
    11481991
    11491992        if (user) {
    1150                 fstrcpy(user2, user);
     1993                user2 = talloc_strdup(talloc_tos(), user);
    11511994        } else {
    1152                 user2[0] ='\0';
     1995                user2 = talloc_strdup(talloc_tos(), "");
     1996        }
     1997        if (user2 == NULL) {
     1998                return NT_STATUS_NO_MEMORY;
    11531999        }
    11542000
     
    11622008                *p = 0;
    11632009                user = p+1;
     2010                strupper_m(user2);
    11642011                workgroup = user2;
    11652012        }
     
    11772024        if (cli->protocol < PROTOCOL_NT1) {
    11782025                if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
    1179                         DEBUG(1, ("Server requested LM password but 'client lanman auth'"
    1180                                   " is disabled\n"));
     2026                        DEBUG(1, ("Server requested LM password but 'client lanman auth = no'"
     2027                                  " or 'client ntlmv2 auth = yes'\n"));
    11812028                        return NT_STATUS_ACCESS_DENIED;
    11822029                }
     
    11842031                if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
    11852032                    !lp_client_plaintext_auth() && (*pass)) {
    1186                         DEBUG(1, ("Server requested plaintext password but "
    1187                                   "'client plaintext auth' is disabled\n"));
     2033                        DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
     2034                                  " or 'client ntlmv2 auth = yes'\n"));
    11882035                        return NT_STATUS_ACCESS_DENIED;
    11892036                }
     
    12042051
    12052052        if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
    1206                 return cli_session_setup_plaintext(cli, user, "", workgroup);
     2053                return cli_session_setup_plain(cli, user, "", workgroup);
    12072054
    12082055        /* if the server doesn't support encryption then we have to use
     
    12112058        if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
    12122059                if (!lp_client_plaintext_auth() && (*pass)) {
    1213                         DEBUG(1, ("Server requested plaintext password but "
    1214                                   "'client plaintext auth' is disabled\n"));
     2060                        DEBUG(1, ("Server requested LM password but 'client plaintext auth = no'"
     2061                                  " or 'client ntlmv2 auth = yes'\n"));
    12152062                        return NT_STATUS_ACCESS_DENIED;
    12162063                }
    1217                 return cli_session_setup_plaintext(cli, user, pass, workgroup);
     2064                return cli_session_setup_plain(cli, user, pass, workgroup);
    12182065        }
    12192066
     
    12512098*****************************************************************************/
    12522099
    1253 bool cli_ulogoff(struct cli_state *cli)
    1254 {
    1255         memset(cli->outbuf,'\0',smb_size);
    1256         cli_set_message(cli->outbuf,2,0,True);
    1257         SCVAL(cli->outbuf,smb_com,SMBulogoffX);
    1258         cli_setup_packet(cli);
    1259         SSVAL(cli->outbuf,smb_vwv0,0xFF);
    1260         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
    1261 
    1262         cli_send_smb(cli);
    1263         if (!cli_receive_smb(cli))
    1264                 return False;
    1265 
    1266         if (cli_is_error(cli)) {
    1267                 return False;
    1268         }
    1269 
    1270         cli->vuid = -1;
    1271         return True;
     2100struct cli_ulogoff_state {
     2101        struct cli_state *cli;
     2102        uint16_t vwv[3];
     2103};
     2104
     2105static void cli_ulogoff_done(struct tevent_req *subreq);
     2106
     2107struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
     2108                                    struct tevent_context *ev,
     2109                                    struct cli_state *cli)
     2110{
     2111        struct tevent_req *req, *subreq;
     2112        struct cli_ulogoff_state *state;
     2113
     2114        req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
     2115        if (req == NULL) {
     2116                return NULL;
     2117        }
     2118        state->cli = cli;
     2119
     2120        SCVAL(state->vwv+0, 0, 0xFF);
     2121        SCVAL(state->vwv+1, 0, 0);
     2122        SSVAL(state->vwv+2, 0, 0);
     2123
     2124        subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
     2125                              0, NULL);
     2126        if (tevent_req_nomem(subreq, req)) {
     2127                return tevent_req_post(req, ev);
     2128        }
     2129        tevent_req_set_callback(subreq, cli_ulogoff_done, req);
     2130        return req;
     2131}
     2132
     2133static void cli_ulogoff_done(struct tevent_req *subreq)
     2134{
     2135        struct tevent_req *req = tevent_req_callback_data(
     2136                subreq, struct tevent_req);
     2137        struct cli_ulogoff_state *state = tevent_req_data(
     2138                req, struct cli_ulogoff_state);
     2139        NTSTATUS status;
     2140
     2141        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
     2142        if (!NT_STATUS_IS_OK(status)) {
     2143                tevent_req_nterror(req, status);
     2144                return;
     2145        }
     2146        state->cli->vuid = -1;
     2147        tevent_req_done(req);
     2148}
     2149
     2150NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
     2151{
     2152        return tevent_req_simple_recv_ntstatus(req);
     2153}
     2154
     2155NTSTATUS cli_ulogoff(struct cli_state *cli)
     2156{
     2157        struct tevent_context *ev;
     2158        struct tevent_req *req;
     2159        NTSTATUS status = NT_STATUS_NO_MEMORY;
     2160
     2161        if (cli_has_async_calls(cli)) {
     2162                return NT_STATUS_INVALID_PARAMETER;
     2163        }
     2164        ev = tevent_context_init(talloc_tos());
     2165        if (ev == NULL) {
     2166                goto fail;
     2167        }
     2168        req = cli_ulogoff_send(ev, ev, cli);
     2169        if (req == NULL) {
     2170                goto fail;
     2171        }
     2172        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     2173                goto fail;
     2174        }
     2175        status = cli_ulogoff_recv(req);
     2176fail:
     2177        TALLOC_FREE(ev);
     2178        if (!NT_STATUS_IS_OK(status)) {
     2179                cli_set_error(cli, status);
     2180        }
     2181        return status;
    12722182}
    12732183
     
    12932203        struct tevent_req *req, *subreq;
    12942204        struct cli_tcon_andx_state *state;
    1295         fstring pword;
     2205        uint8_t p24[24];
    12962206        uint16_t *vwv;
    12972207        char *tmp = NULL;
     
    13072217        vwv = state->vwv;
    13082218
    1309         fstrcpy(cli->share, share);
     2219        cli->share = talloc_strdup(cli, share);
     2220        if (!cli->share) {
     2221                return NULL;
     2222        }
    13102223
    13112224        /* in user level security don't send a password now */
     
    13242237                        DEBUG(1, ("Server requested LANMAN password "
    13252238                                  "(share-level security) but "
    1326                                   "'client lanman auth' is disabled\n"));
     2239                                  "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
    13272240                        goto access_denied;
    13282241                }
     
    13322245                 * encryption.
    13332246                 */
     2247                SMBencrypt(pass, cli->secblob.data, p24);
    13342248                passlen = 24;
    1335                 SMBencrypt(pass, cli->secblob.data, (uchar *)pword);
     2249                pass = (const char *)p24;
    13362250        } else {
    13372251                if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL
    13382252                                     |NEGOTIATE_SECURITY_CHALLENGE_RESPONSE))
    13392253                   == 0) {
     2254                        char *tmp_pass;
     2255
    13402256                        if (!lp_client_plaintext_auth() && (*pass)) {
    13412257                                DEBUG(1, ("Server requested plaintext "
    1342                                           "password but 'client plaintext "
    1343                                           "auth' is disabled\n"));
     2258                                          "password but "
     2259                                          "'client lanman auth = no' or 'client ntlmv2 auth = yes'\n"));
    13442260                                goto access_denied;
    13452261                        }
     
    13492265                         * before using.
    13502266                         */
    1351                         passlen = clistr_push(cli, pword, pass, sizeof(pword),
    1352                                               STR_TERMINATE);
     2267                        tmp_pass = talloc_array(talloc_tos(), char, 128);
     2268                        if (tmp_pass == NULL) {
     2269                                tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     2270                                return tevent_req_post(req, ev);
     2271                        }
     2272                        passlen = clistr_push(cli,
     2273                                        tmp_pass,
     2274                                        pass,
     2275                                        talloc_get_size(tmp_pass),
     2276                                        STR_TERMINATE);
    13532277                        if (passlen == -1) {
    1354                                 DEBUG(1, ("clistr_push(pword) failed\n"));
    1355                                 goto access_denied;
     2278                                tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     2279                                return tevent_req_post(req, ev);
    13562280                        }
    1357                 } else {
    1358                         if (passlen) {
    1359                                 memcpy(pword, pass, passlen);
    1360                         }
     2281                        pass = tmp_pass;
    13612282                }
    13622283        }
     
    13682289        SSVAL(vwv+3, 0, passlen);
    13692290
    1370         if (passlen) {
    1371                 bytes = (uint8_t *)talloc_memdup(state, pword, passlen);
     2291        if (passlen && pass) {
     2292                bytes = (uint8_t *)talloc_memdup(state, pass, passlen);
    13722293        } else {
    13732294                bytes = talloc_array(state, uint8_t, 0);
     
    14532374                req, struct cli_tcon_andx_state);
    14542375        struct cli_state *cli = state->cli;
    1455         char *inbuf = (char *)cli_smb_inbuf(subreq);
     2376        uint8_t *in;
     2377        char *inbuf;
    14562378        uint8_t wct;
    14572379        uint16_t *vwv;
     
    14602382        NTSTATUS status;
    14612383
    1462         status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
    1463         if (!NT_STATUS_IS_OK(status)) {
    1464                 TALLOC_FREE(subreq);
     2384        status = cli_smb_recv(subreq, state, &in, 0, &wct, &vwv,
     2385                              &num_bytes, &bytes);
     2386        TALLOC_FREE(subreq);
     2387        if (!NT_STATUS_IS_OK(status)) {
    14652388                tevent_req_nterror(req, status);
    14662389                return;
    14672390        }
    14682391
    1469         clistr_pull(inbuf, cli->dev, bytes, sizeof(fstring), num_bytes,
    1470                     STR_TERMINATE|STR_ASCII);
     2392        inbuf = (char *)in;
     2393
     2394        if (num_bytes) {
     2395                if (clistr_pull_talloc(cli,
     2396                                inbuf,
     2397                                SVAL(inbuf, smb_flg2),
     2398                                &cli->dev,
     2399                                bytes,
     2400                                num_bytes,
     2401                                STR_TERMINATE|STR_ASCII) == -1) {
     2402                        tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     2403                        return;
     2404                }
     2405        } else {
     2406                cli->dev = talloc_strdup(cli, "");
     2407                if (cli->dev == NULL) {
     2408                        tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
     2409                        return;
     2410                }
     2411        }
    14712412
    14722413        if ((cli->protocol >= PROTOCOL_NT1) && (num_bytes == 3)) {
     
    15412482****************************************************************************/
    15422483
    1543 bool cli_tdis(struct cli_state *cli)
    1544 {
    1545         memset(cli->outbuf,'\0',smb_size);
    1546         cli_set_message(cli->outbuf,0,0,True);
    1547         SCVAL(cli->outbuf,smb_com,SMBtdis);
    1548         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    1549         cli_setup_packet(cli);
    1550 
    1551         cli_send_smb(cli);
    1552         if (!cli_receive_smb(cli))
    1553                 return False;
    1554 
    1555         if (cli_is_error(cli)) {
    1556                 return False;
    1557         }
    1558 
    1559         cli->cnum = -1;
    1560         return True;
    1561 }
    1562 
    1563 /****************************************************************************
    1564  Send a negprot command.
    1565 ****************************************************************************/
    1566 
    1567 void cli_negprot_sendsync(struct cli_state *cli)
    1568 {
    1569         char *p;
    1570         int numprots;
    1571 
    1572         if (cli->protocol < PROTOCOL_NT1)
    1573                 cli->use_spnego = False;
    1574 
    1575         memset(cli->outbuf,'\0',smb_size);
    1576 
    1577         /* setup the protocol strings */
    1578         cli_set_message(cli->outbuf,0,0,True);
    1579 
    1580         p = smb_buf(cli->outbuf);
    1581         for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) {
    1582                 if (prots[numprots].prot > cli->protocol) {
    1583                         break;
    1584                 }
    1585                 *p++ = 2;
    1586                 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
    1587         }
    1588 
    1589         SCVAL(cli->outbuf,smb_com,SMBnegprot);
    1590         cli_setup_bcc(cli, p);
    1591         cli_setup_packet(cli);
    1592 
    1593         SCVAL(smb_buf(cli->outbuf),0,2);
    1594 
    1595         cli_send_smb(cli);
     2484struct cli_tdis_state {
     2485        struct cli_state *cli;
     2486};
     2487
     2488static void cli_tdis_done(struct tevent_req *subreq);
     2489
     2490struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
     2491                                 struct tevent_context *ev,
     2492                                 struct cli_state *cli)
     2493{
     2494        struct tevent_req *req, *subreq;
     2495        struct cli_tdis_state *state;
     2496
     2497        req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
     2498        if (req == NULL) {
     2499                return NULL;
     2500        }
     2501        state->cli = cli;
     2502
     2503        subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
     2504        if (tevent_req_nomem(subreq, req)) {
     2505                return tevent_req_post(req, ev);
     2506        }
     2507        tevent_req_set_callback(subreq, cli_tdis_done, req);
     2508        return req;
     2509}
     2510
     2511static void cli_tdis_done(struct tevent_req *subreq)
     2512{
     2513        struct tevent_req *req = tevent_req_callback_data(
     2514                subreq, struct tevent_req);
     2515        struct cli_tdis_state *state = tevent_req_data(
     2516                req, struct cli_tdis_state);
     2517        NTSTATUS status;
     2518
     2519        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
     2520        TALLOC_FREE(subreq);
     2521        if (!NT_STATUS_IS_OK(status)) {
     2522                tevent_req_nterror(req, status);
     2523                return;
     2524        }
     2525        state->cli->cnum = -1;
     2526        tevent_req_done(req);
     2527}
     2528
     2529NTSTATUS cli_tdis_recv(struct tevent_req *req)
     2530{
     2531        return tevent_req_simple_recv_ntstatus(req);
     2532}
     2533
     2534NTSTATUS cli_tdis(struct cli_state *cli)
     2535{
     2536        struct tevent_context *ev;
     2537        struct tevent_req *req;
     2538        NTSTATUS status = NT_STATUS_NO_MEMORY;
     2539
     2540        if (cli_has_async_calls(cli)) {
     2541                return NT_STATUS_INVALID_PARAMETER;
     2542        }
     2543        ev = tevent_context_init(talloc_tos());
     2544        if (ev == NULL) {
     2545                goto fail;
     2546        }
     2547        req = cli_tdis_send(ev, ev, cli);
     2548        if (req == NULL) {
     2549                goto fail;
     2550        }
     2551        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     2552                goto fail;
     2553        }
     2554        status = cli_tdis_recv(req);
     2555fail:
     2556        TALLOC_FREE(ev);
     2557        if (!NT_STATUS_IS_OK(status)) {
     2558                cli_set_error(cli, status);
     2559        }
     2560        return status;
    15962561}
    15972562
     
    16722637        NTSTATUS status;
    16732638        uint16_t protnum;
    1674 
    1675         status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
    1676         if (!NT_STATUS_IS_OK(status)) {
    1677                 TALLOC_FREE(subreq);
     2639        uint8_t *inbuf;
     2640
     2641        status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv,
     2642                              &num_bytes, &bytes);
     2643        TALLOC_FREE(subreq);
     2644        if (!NT_STATUS_IS_OK(status)) {
    16782645                tevent_req_nterror(req, status);
    16792646                return;
     
    17192686                /* work out if they sent us a workgroup */
    17202687                if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
    1721                     smb_buflen(cli->inbuf) > 8) {
    1722                         clistr_pull(cli->inbuf, cli->server_domain,
    1723                                     bytes+8, sizeof(cli->server_domain),
    1724                                     num_bytes-8,
    1725                                     STR_UNICODE|STR_NOALIGN);
     2688                    smb_buflen(inbuf) > 8) {
     2689                        ssize_t ret;
     2690                        status = smb_bytes_talloc_string(
     2691                                cli, (char *)inbuf, &cli->server_domain,
     2692                                bytes + 8, num_bytes - 8, &ret);
     2693                        if (tevent_req_nterror(req, status)) {
     2694                                return;
     2695                        }
    17262696                }
    17272697
     
    17622732                        cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
    17632733                        cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
     2734                        if (!cli->outbuf || !cli->inbuf) {
     2735                                tevent_req_nterror(req,
     2736                                                NT_STATUS_NO_MEMORY);
     2737                                return;
     2738                        }
    17642739                        cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
    17652740                }
     
    17742749                cli->serverzone *= 60;
    17752750                /* this time is converted to GMT by make_unix_date */
    1776                 cli->servertime = cli_make_unix_date(
    1777                         cli, (char *)(vwv + 8));
     2751                cli->servertime = make_unix_date(
     2752                        (char *)(vwv + 8), cli->serverzone);
    17782753                cli->readbraw_supported = ((SVAL(vwv + 5, 0) & 0x1) != 0);
    17792754                cli->writebraw_supported = ((SVAL(vwv + 5, 0) & 0x2) != 0);
     
    20703045        }
    20713046
    2072         fstrcpy(cli->desthost, host);
     3047        cli->desthost = talloc_strdup(cli, host);
     3048        if (cli->desthost == NULL) {
     3049                return NT_STATUS_NO_MEMORY;
     3050        }
    20733051
    20743052        /* allow hostnames of the form NAME#xx and do a netbios lookup */
     
    20783056        }
    20793057
    2080         if (!dest_ss || is_zero_addr((struct sockaddr *)dest_ss)) {
     3058        if (!dest_ss || is_zero_addr(dest_ss)) {
    20813059                NTSTATUS status =resolve_name_list(frame,
    20823060                                        cli->desthost,
     
    21433121   @param dest_ss (optional) The the destination IP, NULL for name based lookup
    21443122   @param port (optional) The destination port (0 for default)
    2145    @param retry bool. Did this connection fail with a retryable error ?
    2146 
    21473123*/
    21483124NTSTATUS cli_start_connection(struct cli_state **output_cli,
     
    21503126                              const char *dest_host,
    21513127                              struct sockaddr_storage *dest_ss, int port,
    2152                               int signing_state, int flags,
    2153                               bool *retry)
     3128                              int signing_state, int flags)
    21543129{
    21553130        NTSTATUS nt_status;
     
    21583133        struct cli_state *cli;
    21593134        struct sockaddr_storage ss;
    2160 
    2161         if (retry)
    2162                 *retry = False;
    21633135
    21643136        if (!my_name)
     
    21943166                return nt_status;
    21953167        }
    2196 
    2197         if (retry)
    2198                 *retry = True;
    21993168
    22003169        if (!cli_session_request(cli, &calling, &called)) {
     
    22493218   @param domain User's domain
    22503219   @param password User's password, unencrypted unix string.
    2251    @param retry bool. Did this connection fail with a retryable error ?
    22523220*/
    22533221
     
    22593227                             const char *user, const char *domain,
    22603228                             const char *password, int flags,
    2261                              int signing_state,
    2262                              bool *retry)
     3229                             int signing_state)
    22633230{
    22643231        NTSTATUS nt_status;
     
    22743241        nt_status = cli_start_connection(&cli, my_name, dest_host,
    22753242                                         dest_ss, port, signing_state,
    2276                                          flags, retry);
     3243                                         flags);
    22773244
    22783245        if (!NT_STATUS_IS_OK(nt_status)) {
     
    23993366                      uint16 *max_xmit, uint16 *tid)
    24003367{
    2401         char *p;
     3368        struct tevent_req *req;
     3369        uint16_t *ret_vwv;
     3370        uint8_t *bytes;
     3371        NTSTATUS status;
    24023372
    24033373        if (!lp_client_plaintext_auth() && (*pass)) {
     
    24073377        }
    24083378
    2409         memset(cli->outbuf,'\0',smb_size);
    2410         memset(cli->inbuf,'\0',smb_size);
    2411 
    2412         cli_set_message(cli->outbuf, 0, 0, True);
    2413         SCVAL(cli->outbuf,smb_com,SMBtcon);
    2414         cli_setup_packet(cli);
    2415 
    2416         p = smb_buf(cli->outbuf);
    2417         *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
    2418         *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
    2419         *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
    2420 
    2421         cli_setup_bcc(cli, p);
    2422 
    2423         cli_send_smb(cli);
    2424         if (!cli_receive_smb(cli)) {
    2425                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    2426         }
    2427 
    2428         if (cli_is_error(cli)) {
    2429                 return cli_nt_error(cli);
    2430         }
    2431 
    2432         *max_xmit = SVAL(cli->inbuf, smb_vwv0);
    2433         *tid = SVAL(cli->inbuf, smb_vwv1);
     3379        bytes = talloc_array(talloc_tos(), uint8_t, 0);
     3380        bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
     3381        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     3382                                   service, strlen(service)+1, NULL);
     3383        bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
     3384        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     3385                                   pass, strlen(pass)+1, NULL);
     3386        bytes = smb_bytes_push_bytes(bytes, 4, NULL, 0);
     3387        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
     3388                                   dev, strlen(dev)+1, NULL);
     3389
     3390        status = cli_smb(talloc_tos(), cli, SMBtcon, 0, 0, NULL,
     3391                         talloc_get_size(bytes), bytes, &req,
     3392                         2, NULL, &ret_vwv, NULL, NULL);
     3393        if (!NT_STATUS_IS_OK(status)) {
     3394                return status;
     3395        }
     3396
     3397        *max_xmit = SVAL(ret_vwv + 0, 0);
     3398        *tid = SVAL(ret_vwv + 1, 0);
    24343399
    24353400        return NT_STATUS_OK;
     
    24553420                                        user_info->password ? user_info->password : "",
    24563421                                        flags,
    2457                                         Undefined, NULL);
     3422                                        Undefined);
    24583423
    24593424        if (NT_STATUS_IS_OK(nt_status)) {
     
    24853450
    24863451struct cli_state *get_ipc_connect_master_ip(TALLOC_CTX *ctx,
    2487                                 struct ip_service *mb_ip,
     3452                                struct sockaddr_storage *mb_ip,
    24883453                                const struct user_auth_info *user_info,
    24893454                                char **pp_workgroup_out)
     
    24963461        *pp_workgroup_out = NULL;
    24973462
    2498         print_sockaddr(addr, sizeof(addr), &mb_ip->ss);
     3463        print_sockaddr(addr, sizeof(addr), mb_ip);
    24993464        DEBUG(99, ("Looking up name of master browser %s\n",
    25003465                   addr));
     
    25113476         * MSBROWSE if the wildcard query fails.
    25123477         */
    2513         if (!name_status_find("*", 0, 0x1d, &mb_ip->ss, name) &&
    2514             !name_status_find(MSBROWSE, 1, 0x1d, &mb_ip->ss, name)) {
     3478        if (!name_status_find("*", 0, 0x1d, mb_ip, name) &&
     3479            !name_status_find(MSBROWSE, 1, 0x1d, mb_ip, name)) {
    25153480
    25163481                DEBUG(99, ("Could not retrieve name status for %s\n",
     
    25433508                                        char **pp_workgroup_out)
    25443509{
    2545         struct ip_service *ip_list;
     3510        struct sockaddr_storage *ip_list;
    25463511        struct cli_state *cli;
    25473512        int i, count;
     3513        NTSTATUS status;
    25483514
    25493515        *pp_workgroup_out = NULL;
     
    25533519        /* Go looking for workgroups by broadcasting on the local network */
    25543520
    2555         if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
    2556                                                 &count))) {
    2557                 DEBUG(99, ("No master browsers responded\n"));
     3521        status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
     3522                                    &ip_list, &count);
     3523        if (!NT_STATUS_IS_OK(status)) {
     3524                DEBUG(99, ("No master browsers responded: %s\n",
     3525                           nt_errstr(status)));
    25583526                return False;
    25593527        }
     
    25613529        for (i = 0; i < count; i++) {
    25623530                char addr[INET6_ADDRSTRLEN];
    2563                 print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
     3531                print_sockaddr(addr, sizeof(addr), &ip_list[i]);
    25643532                DEBUG(99, ("Found master browser %s\n", addr));
    25653533
Note: See TracChangeset for help on using the changeset viewer.