Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

Location:
vendor/current/source4/libcli/smb2
Files:
1 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source4/libcli/smb2/cancel.c

    r740 r988  
    2121
    2222#include "includes.h"
     23#include <tevent.h>
    2324#include "libcli/raw/libcliraw.h"
    2425#include "libcli/smb2/smb2.h"
     
    3031NTSTATUS smb2_cancel(struct smb2_request *r)
    3132{
    32         NTSTATUS status;
    33         struct smb2_request *c;
    34         uint32_t old_timeout;
    35         uint64_t old_seqnum;
     33        bool ok;
    3634
    37         /*
    38          * if we don't get a pending id yet, we just
    39          * mark the request for pending, so that we directly
    40          * send the cancel after getting the pending id
    41          */
    42         if (!r->cancel.can_cancel) {
    43                 r->cancel.do_cancel++;
     35        if (r->subreq == NULL) {
    4436                return NT_STATUS_OK;
    4537        }
    4638
    47         /* we don't want a seqmun for a SMB2 Cancel */
    48         old_seqnum = r->transport->seqnum;
    49         c = smb2_request_init(r->transport, SMB2_OP_CANCEL, 0x04, false, 0);
    50         r->transport->seqnum = old_seqnum;
    51         NT_STATUS_HAVE_NO_MEMORY(c);
    52         c->seqnum = 0;
    53 
    54         SIVAL(c->out.hdr, SMB2_HDR_FLAGS,       0x00000002);
    55         SSVAL(c->out.hdr, SMB2_HDR_CREDIT,      0x0030);
    56         SBVAL(c->out.hdr, SMB2_HDR_ASYNC_ID,    r->cancel.async_id);
    57         SBVAL(c->out.hdr, SMB2_HDR_MESSAGE_ID,  c->seqnum);
    58         if (r->session) {
    59                 SBVAL(c->out.hdr, SMB2_HDR_SESSION_ID,  r->session->uid);
     39        ok = tevent_req_cancel(r->subreq);
     40        if (!ok) {
     41                return NT_STATUS_INTERNAL_ERROR;
    6042        }
    6143
    62         SSVAL(c->out.body, 0x02, 0);
    63 
    64         old_timeout = c->transport->options.request_timeout;
    65         c->transport->options.request_timeout = 0;
    66         smb2_transport_send(c);
    67         c->transport->options.request_timeout = old_timeout;
    68 
    69         if (c->state == SMB2_REQUEST_ERROR) {
    70                 status = c->status;
    71         } else {
    72                 status = NT_STATUS_OK;
    73         }
    74 
    75         talloc_free(c);
    76         return status;
     44        return NT_STATUS_OK;
    7745}
  • vendor/current/source4/libcli/smb2/connect.c

    r414 r988  
    2121
    2222#include "includes.h"
     23#include <tevent.h>
     24#include "lib/util/tevent_ntstatus.h"
    2325#include "libcli/raw/libcliraw.h"
    2426#include "libcli/raw/raw_proto.h"
     
    2830#include "libcli/resolve/resolve.h"
    2931#include "param/param.h"
     32#include "auth/credentials/credentials.h"
     33#include "../libcli/smb/smbXcli_base.h"
    3034
    3135struct smb2_connect_state {
     36        struct tevent_context *ev;
    3237        struct cli_credentials *credentials;
     38        uint64_t previous_session_id;
    3339        struct resolve_context *resolve_ctx;
    3440        const char *host;
    3541        const char *share;
     42        const char *unc;
    3643        const char **ports;
    3744        const char *socket_options;
     45        struct nbt_name calling, called;
    3846        struct gensec_settings *gensec_settings;
    3947        struct smbcli_options options;
    40         struct smb2_negprot negprot;
    41         struct smb2_tree_connect tcon;
     48        struct smb2_transport *transport;
    4249        struct smb2_session *session;
    4350        struct smb2_tree *tree;
    4451};
    4552
    46 /*
    47   continue after tcon reply
    48 */
    49 static void continue_tcon(struct smb2_request *req)
    50 {
    51         struct composite_context *c = talloc_get_type(req->async.private_data,
    52                                                       struct composite_context);
    53         struct smb2_connect_state *state = talloc_get_type(c->private_data,
    54                                                            struct smb2_connect_state);
    55 
    56         c->status = smb2_tree_connect_recv(req, &state->tcon);
    57         if (!composite_is_ok(c)) return;
    58        
    59         state->tree->tid = state->tcon.out.tid;
    60 
    61         composite_done(c);
    62 }
    63 
    64 /*
    65   continue after a session setup
    66 */
    67 static void continue_session(struct composite_context *creq)
    68 {
    69         struct composite_context *c = talloc_get_type(creq->async.private_data,
    70                                                       struct composite_context);
    71         struct smb2_connect_state *state = talloc_get_type(c->private_data,
    72                                                            struct smb2_connect_state);
    73         struct smb2_request *req;
    74 
    75         c->status = smb2_session_setup_spnego_recv(creq);
    76         if (!composite_is_ok(c)) return;
    77 
    78         state->tree = smb2_tree_init(state->session, state, true);
    79         if (composite_nomem(state->tree, c)) return;
    80 
    81         state->tcon.in.reserved = 0;
    82         state->tcon.in.path     = talloc_asprintf(state, "\\\\%s\\%s",
    83                                                   state->host, state->share);
    84         if (composite_nomem(state->tcon.in.path, c)) return;
    85        
    86         req = smb2_tree_connect_send(state->tree, &state->tcon);
    87         if (composite_nomem(req, c)) return;
    88 
    89         req->async.fn = continue_tcon;
    90         req->async.private_data = c;   
    91 }
    92 
    93 /*
    94   continue after negprot reply
    95 */
    96 static void continue_negprot(struct smb2_request *req)
    97 {
    98         struct composite_context *c = talloc_get_type(req->async.private_data,
    99                                                       struct composite_context);
    100         struct smb2_connect_state *state = talloc_get_type(c->private_data,
    101                                                            struct smb2_connect_state);
    102         struct smb2_transport *transport = req->transport;
    103         struct composite_context *creq;
    104 
    105         c->status = smb2_negprot_recv(req, c, &state->negprot);
    106         if (!composite_is_ok(c)) return;
    107 
    108         transport->negotiate.secblob = state->negprot.out.secblob;
    109         talloc_steal(transport, transport->negotiate.secblob.data);
    110         transport->negotiate.system_time = state->negprot.out.system_time;
    111         transport->negotiate.server_start_time = state->negprot.out.server_start_time;
    112         transport->negotiate.security_mode = state->negprot.out.security_mode;
    113         transport->negotiate.dialect_revision = state->negprot.out.dialect_revision;
    114 
    115         switch (transport->options.signing) {
    116         case SMB_SIGNING_OFF:
    117                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
    118                         composite_error(c, NT_STATUS_ACCESS_DENIED);
    119                         return;
    120                 }
    121                 transport->signing_required = false;
    122                 break;
    123         case SMB_SIGNING_SUPPORTED:
    124                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
    125                         transport->signing_required = true;
    126                 } else {
    127                         transport->signing_required = false;
    128                 }
    129                 break;
    130         case SMB_SIGNING_AUTO:
    131                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) {
    132                         transport->signing_required = true;
    133                 } else {
    134                         transport->signing_required = false;
    135                 }
    136                 break;
    137         case SMB_SIGNING_REQUIRED:
    138                 if (transport->negotiate.security_mode & SMB2_NEGOTIATE_SIGNING_ENABLED) {
    139                         transport->signing_required = true;
    140                 } else {
    141                         composite_error(c, NT_STATUS_ACCESS_DENIED);
    142                         return;
    143                 }
    144                 break;
    145         }
    146 
    147         state->session = smb2_session_init(transport, state->gensec_settings, state, true);
    148         if (composite_nomem(state->session, c)) return;
    149 
    150         creq = smb2_session_setup_spnego_send(state->session, state->credentials);
    151 
    152         composite_continue(c, creq, continue_session, c);
    153 }
    154 
    155 /*
    156   continue after a socket connect completes
    157 */
    158 static void continue_socket(struct composite_context *creq)
    159 {
    160         struct composite_context *c = talloc_get_type(creq->async.private_data,
    161                                                       struct composite_context);
    162         struct smb2_connect_state *state = talloc_get_type(c->private_data,
    163                                                            struct smb2_connect_state);
    164         struct smbcli_socket *sock;
    165         struct smb2_transport *transport;
    166         struct smb2_request *req;
    167         uint16_t dialects[3] = {
    168                 SMB2_DIALECT_REVISION_000,
    169                 SMB2_DIALECT_REVISION_202,
    170                 SMB2_DIALECT_REVISION_210
    171         };
    172 
    173         c->status = smbcli_sock_connect_recv(creq, state, &sock);
    174         if (!composite_is_ok(c)) return;
    175 
    176         transport = smb2_transport_init(sock, state, &state->options);
    177         if (composite_nomem(transport, c)) return;
    178 
    179         ZERO_STRUCT(state->negprot);
    180         state->negprot.in.dialect_count = sizeof(dialects) / sizeof(dialects[0]);
    181         switch (transport->options.signing) {
    182         case SMB_SIGNING_OFF:
    183                 state->negprot.in.security_mode = 0;
    184                 break;
    185         case SMB_SIGNING_SUPPORTED:
    186         case SMB_SIGNING_AUTO:
    187                 state->negprot.in.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
    188                 break;
    189         case SMB_SIGNING_REQUIRED:
    190                 state->negprot.in.security_mode =
    191                         SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED;
    192                 break;
    193         }
    194         state->negprot.in.capabilities  = 0;
    195         unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
    196         state->negprot.in.dialects = dialects;
    197 
    198         req = smb2_negprot_send(transport, &state->negprot);
    199         if (composite_nomem(req, c)) return;
    200 
    201         req->async.fn = continue_negprot;
    202         req->async.private_data = c;
    203 }
    204 
    205 
    206 /*
    207   continue after a resolve finishes
    208 */
    209 static void continue_resolve(struct composite_context *creq)
    210 {
    211         struct composite_context *c = talloc_get_type(creq->async.private_data,
    212                                                       struct composite_context);
    213         struct smb2_connect_state *state = talloc_get_type(c->private_data,
    214                                                            struct smb2_connect_state);
    215         const char *addr;
    216         const char **ports;
    217         const char *default_ports[] = { "445", NULL };
    218 
    219         c->status = resolve_name_recv(creq, state, &addr);
    220         if (!composite_is_ok(c)) return;
    221 
    222         if (state->ports == NULL) {
    223                 ports = default_ports;
    224         } else {
    225                 ports = state->ports;
    226         }
    227 
    228         creq = smbcli_sock_connect_send(state, addr, ports, state->host, state->resolve_ctx, c->event_ctx, state->socket_options);
    229 
    230         composite_continue(c, creq, continue_socket, c);
    231 }
     53static void smb2_connect_socket_done(struct composite_context *creq);
    23254
    23355/*
     
    23557  a connected smb2_tree
    23658 */
    237 struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx,
    238                                             const char *host,
    239                                                 const char **ports,
    240                                             const char *share,
    241                                             struct resolve_context *resolve_ctx,
    242                                             struct cli_credentials *credentials,
    243                                             struct tevent_context *ev,
    244                                             struct smbcli_options *options,
    245                                                 const char *socket_options,
    246                                                 struct gensec_settings *gensec_settings)
    247 {
    248         struct composite_context *c;
     59struct tevent_req *smb2_connect_send(TALLOC_CTX *mem_ctx,
     60                                     struct tevent_context *ev,
     61                                     const char *host,
     62                                     const char **ports,
     63                                     const char *share,
     64                                     struct resolve_context *resolve_ctx,
     65                                     struct cli_credentials *credentials,
     66                                     uint64_t previous_session_id,
     67                                     const struct smbcli_options *options,
     68                                     const char *socket_options,
     69                                     struct gensec_settings *gensec_settings)
     70{
     71        struct tevent_req *req;
    24972        struct smb2_connect_state *state;
    250         struct nbt_name name;
    25173        struct composite_context *creq;
    252 
    253         c = composite_create(mem_ctx, ev);
    254         if (c == NULL) return NULL;
    255 
    256         state = talloc(c, struct smb2_connect_state);
    257         if (composite_nomem(state, c)) return c;
    258         c->private_data = state;
    259 
     74        static const char *default_ports[] = { "445", "139", NULL };
     75
     76        req = tevent_req_create(mem_ctx, &state,
     77                                struct smb2_connect_state);
     78        if (req == NULL) {
     79                return NULL;
     80        }
     81
     82        state->ev = ev;
    26083        state->credentials = credentials;
     84        state->previous_session_id = previous_session_id;
    26185        state->options = *options;
    262         state->host = talloc_strdup(c, host);
    263         if (composite_nomem(state->host, c)) return c;
    264         state->ports = talloc_reference(state, ports);
    265         state->share = talloc_strdup(c, share);
    266         if (composite_nomem(state->share, c)) return c;
    267         state->resolve_ctx = talloc_reference(state, resolve_ctx);
    268         state->socket_options = talloc_reference(state, socket_options);
    269         state->gensec_settings = talloc_reference(state, gensec_settings);
    270 
    271         ZERO_STRUCT(name);
    272         name.name = host;
    273 
    274         creq = resolve_name_send(resolve_ctx, state, &name, c->event_ctx);
    275         composite_continue(c, creq, continue_resolve, c);
    276         return c;
    277 }
    278 
    279 /*
    280   receive a connect reply
    281 */
    282 NTSTATUS smb2_connect_recv(struct composite_context *c, TALLOC_CTX *mem_ctx,
     86        state->host = host;
     87        state->ports = ports;
     88        state->share = share;
     89        state->resolve_ctx = resolve_ctx;
     90        state->socket_options = socket_options;
     91        state->gensec_settings = gensec_settings;
     92
     93        if (state->ports == NULL) {
     94                state->ports = default_ports;
     95        }
     96
     97        make_nbt_name_client(&state->calling,
     98                             cli_credentials_get_workstation(credentials));
     99
     100        nbt_choose_called_name(state, &state->called,
     101                               host, NBT_NAME_SERVER);
     102
     103        state->unc = talloc_asprintf(state, "\\\\%s\\%s",
     104                                    state->host, state->share);
     105        if (tevent_req_nomem(state->unc, req)) {
     106                return tevent_req_post(req, ev);
     107        }
     108
     109        creq = smbcli_sock_connect_send(state, NULL, state->ports,
     110                                        state->host, state->resolve_ctx,
     111                                        state->ev, state->socket_options,
     112                                        &state->calling,
     113                                        &state->called);
     114        if (tevent_req_nomem(creq, req)) {
     115                return tevent_req_post(req, ev);
     116        }
     117        creq->async.fn = smb2_connect_socket_done;
     118        creq->async.private_data = req;
     119
     120        return req;
     121}
     122
     123static void smb2_connect_negprot_done(struct tevent_req *subreq);
     124
     125static void smb2_connect_socket_done(struct composite_context *creq)
     126{
     127        struct tevent_req *req =
     128                talloc_get_type_abort(creq->async.private_data,
     129                struct tevent_req);
     130        struct smb2_connect_state *state =
     131                tevent_req_data(req,
     132                struct smb2_connect_state);
     133        struct smbcli_socket *sock;
     134        struct tevent_req *subreq;
     135        NTSTATUS status;
     136        uint32_t timeout_msec;
     137        enum protocol_types min_protocol;
     138
     139        status = smbcli_sock_connect_recv(creq, state, &sock);
     140        if (tevent_req_nterror(req, status)) {
     141                return;
     142        }
     143
     144        state->transport = smb2_transport_init(sock, state, &state->options);
     145        if (tevent_req_nomem(state->transport, req)) {
     146                return;
     147        }
     148
     149        timeout_msec = state->transport->options.request_timeout * 1000;
     150        min_protocol = state->transport->options.min_protocol;
     151        if (min_protocol < PROTOCOL_SMB2_02) {
     152                min_protocol = PROTOCOL_SMB2_02;
     153        }
     154
     155        subreq = smbXcli_negprot_send(state, state->ev,
     156                                      state->transport->conn, timeout_msec,
     157                                      min_protocol,
     158                                      state->transport->options.max_protocol);
     159        if (tevent_req_nomem(subreq, req)) {
     160                return;
     161        }
     162        tevent_req_set_callback(subreq, smb2_connect_negprot_done, req);
     163}
     164
     165static void smb2_connect_session_done(struct tevent_req *subreq);
     166
     167static void smb2_connect_negprot_done(struct tevent_req *subreq)
     168{
     169        struct tevent_req *req =
     170                tevent_req_callback_data(subreq,
     171                struct tevent_req);
     172        struct smb2_connect_state *state =
     173                tevent_req_data(req,
     174                struct smb2_connect_state);
     175        struct smb2_transport *transport = state->transport;
     176        NTSTATUS status;
     177
     178        status = smbXcli_negprot_recv(subreq);
     179        TALLOC_FREE(subreq);
     180        if (tevent_req_nterror(req, status)) {
     181                return;
     182        }
     183
     184        /* This is a hack... */
     185        smb2cli_conn_set_max_credits(transport->conn, 30);
     186
     187        state->session = smb2_session_init(transport, state->gensec_settings, state);
     188        if (tevent_req_nomem(state->session, req)) {
     189                return;
     190        }
     191
     192        subreq = smb2_session_setup_spnego_send(state, state->ev,
     193                                                state->session,
     194                                                state->credentials,
     195                                                state->previous_session_id);
     196        if (tevent_req_nomem(subreq, req)) {
     197                return;
     198        }
     199        tevent_req_set_callback(subreq, smb2_connect_session_done, req);
     200}
     201
     202static void smb2_connect_tcon_done(struct tevent_req *subreq);
     203
     204static void smb2_connect_session_done(struct tevent_req *subreq)
     205{
     206        struct tevent_req *req =
     207                tevent_req_callback_data(subreq,
     208                struct tevent_req);
     209        struct smb2_connect_state *state =
     210                tevent_req_data(req,
     211                struct smb2_connect_state);
     212        NTSTATUS status;
     213        uint32_t timeout_msec;
     214
     215        status = smb2_session_setup_spnego_recv(subreq);
     216        TALLOC_FREE(subreq);
     217        if (tevent_req_nterror(req, status)) {
     218                return;
     219        }
     220
     221        state->tree = smb2_tree_init(state->session, state, true);
     222        if (tevent_req_nomem(state->tree, req)) {
     223                return;
     224        }
     225
     226        timeout_msec = state->transport->options.request_timeout * 1000;
     227
     228        subreq = smb2cli_tcon_send(state, state->ev,
     229                                   state->transport->conn,
     230                                   timeout_msec,
     231                                   state->session->smbXcli,
     232                                   state->tree->smbXcli,
     233                                   0, /* flags */
     234                                   state->unc);
     235        if (tevent_req_nomem(subreq, req)) {
     236                return;
     237        }
     238        tevent_req_set_callback(subreq, smb2_connect_tcon_done, req);
     239}
     240
     241static void smb2_connect_tcon_done(struct tevent_req *subreq)
     242{
     243        struct tevent_req *req =
     244                tevent_req_callback_data(subreq,
     245                struct tevent_req);
     246        NTSTATUS status;
     247
     248        status = smb2cli_tcon_recv(subreq);
     249        if (tevent_req_nterror(req, status)) {
     250                return;
     251        }
     252
     253        tevent_req_done(req);
     254}
     255
     256NTSTATUS smb2_connect_recv(struct tevent_req *req,
     257                           TALLOC_CTX *mem_ctx,
    283258                           struct smb2_tree **tree)
    284259{
    285         NTSTATUS status;
    286         struct smb2_connect_state *state = talloc_get_type(c->private_data,
    287                                                            struct smb2_connect_state);
    288         status = composite_wait(c);
    289         if (NT_STATUS_IS_OK(status)) {
    290                 *tree = talloc_steal(mem_ctx, state->tree);
    291         }
    292         talloc_free(c);
    293         return status;
     260        struct smb2_connect_state *state =
     261                tevent_req_data(req,
     262                struct smb2_connect_state);
     263        NTSTATUS status;
     264
     265        if (tevent_req_is_nterror(req, &status)) {
     266                tevent_req_received(req);
     267                return status;
     268        }
     269
     270        *tree = talloc_move(mem_ctx, &state->tree);
     271
     272        tevent_req_received(req);
     273        return NT_STATUS_OK;
    294274}
    295275
     
    297277  sync version of smb2_connect
    298278*/
    299 NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx,
    300                       const char *host, const char **ports,
     279NTSTATUS smb2_connect_ext(TALLOC_CTX *mem_ctx,
     280                          const char *host,
     281                          const char **ports,
    301282                          const char *share,
     283                          struct resolve_context *resolve_ctx,
     284                          struct cli_credentials *credentials,
     285                          uint64_t previous_session_id,
     286                          struct smb2_tree **tree,
     287                          struct tevent_context *ev,
     288                          const struct smbcli_options *options,
     289                          const char *socket_options,
     290                          struct gensec_settings *gensec_settings)
     291{
     292        struct tevent_req *subreq;
     293        NTSTATUS status;
     294        bool ok;
     295        TALLOC_CTX *frame = talloc_stackframe();
     296
     297        if (frame == NULL) {
     298                return NT_STATUS_NO_MEMORY;
     299        }
     300
     301        subreq = smb2_connect_send(frame,
     302                                   ev,
     303                                   host,
     304                                   ports,
     305                                   share,
     306                                   resolve_ctx,
     307                                   credentials,
     308                                   previous_session_id,
     309                                   options,
     310                                   socket_options,
     311                                   gensec_settings);
     312        if (subreq == NULL) {
     313                TALLOC_FREE(frame);
     314                return NT_STATUS_NO_MEMORY;
     315        }
     316
     317        ok = tevent_req_poll(subreq, ev);
     318        if (!ok) {
     319                status = map_nt_error_from_unix_common(errno);
     320                TALLOC_FREE(frame);
     321                return status;
     322        }
     323
     324        status = smb2_connect_recv(subreq, mem_ctx, tree);
     325        TALLOC_FREE(subreq);
     326        if (!NT_STATUS_IS_OK(status)) {
     327                TALLOC_FREE(frame);
     328                return status;
     329        }
     330
     331        TALLOC_FREE(frame);
     332        return NT_STATUS_OK;
     333}
     334
     335NTSTATUS smb2_connect(TALLOC_CTX *mem_ctx,
     336                      const char *host,
     337                      const char **ports,
     338                      const char *share,
    302339                      struct resolve_context *resolve_ctx,
    303340                      struct cli_credentials *credentials,
     
    305342                      struct tevent_context *ev,
    306343                      struct smbcli_options *options,
    307                           const char *socket_options,
    308                           struct gensec_settings *gensec_settings)
    309 {
    310         struct composite_context *c = smb2_connect_send(mem_ctx, host, ports,
    311                                                                                                         share, resolve_ctx,
    312                                                                                                         credentials, ev, options,
    313                                                                                                         socket_options,
    314                                                                                                         gensec_settings);
    315         return smb2_connect_recv(c, mem_ctx, tree);
    316 }
     344                      const char *socket_options,
     345                      struct gensec_settings *gensec_settings)
     346{
     347        NTSTATUS status;
     348
     349        status = smb2_connect_ext(mem_ctx, host, ports, share, resolve_ctx,
     350                                  credentials,
     351                                  0, /* previous_session_id */
     352                                  tree, ev, options, socket_options,
     353                                  gensec_settings);
     354
     355        return status;
     356}
  • vendor/current/source4/libcli/smb2/create.c

    r740 r988  
    107107        }
    108108
     109        if (io->in.durable_open_v2) {
     110                uint8_t data[32];
     111                uint32_t flags = 0;
     112                DATA_BLOB guid_blob;
     113
     114                SIVAL(data, 0, io->in.timeout);
     115                if (io->in.persistent_open) {
     116                        flags = SMB2_DHANDLE_FLAG_PERSISTENT;
     117                }
     118                SIVAL(data, 4, flags);
     119                SBVAL(data, 8, 0x0); /* reserved */
     120                status = GUID_to_ndr_blob(&io->in.create_guid, req, /* TALLOC_CTX */
     121                                          &guid_blob);
     122                if (!NT_STATUS_IS_OK(status)) {
     123                        talloc_free(req);
     124                        return NULL;
     125                }
     126                memcpy(data+16, guid_blob.data, 16);
     127
     128                status = smb2_create_blob_add(req, &blobs,
     129                                              SMB2_CREATE_TAG_DH2Q,
     130                                              data_blob_const(data, 32));
     131                if (!NT_STATUS_IS_OK(status)) {
     132                        talloc_free(req);
     133                        return NULL;
     134                }
     135        }
     136
    109137        if (io->in.durable_handle) {
    110138                uint8_t data[16];
     
    112140                status = smb2_create_blob_add(req, &blobs,
    113141                                              SMB2_CREATE_TAG_DHNC, data_blob_const(data, 16));
     142                if (!NT_STATUS_IS_OK(status)) {
     143                        talloc_free(req);
     144                        return NULL;
     145                }
     146        }
     147
     148        if (io->in.durable_handle_v2) {
     149                uint8_t data[36];
     150                DATA_BLOB guid_blob;
     151                uint32_t flags = 0;
     152
     153                smb2_push_handle(data, io->in.durable_handle_v2);
     154                status = GUID_to_ndr_blob(&io->in.create_guid, req, /* TALLOC_CTX */
     155                                          &guid_blob);
     156                if (!NT_STATUS_IS_OK(status)) {
     157                        talloc_free(req);
     158                        return NULL;
     159                }
     160                memcpy(data+16, guid_blob.data, 16);
     161                if (io->in.persistent_open) {
     162                        flags = SMB2_DHANDLE_FLAG_PERSISTENT;
     163                }
     164                SIVAL(data, 32, flags);
     165
     166                status = smb2_create_blob_add(req, &blobs,
     167                                              SMB2_CREATE_TAG_DH2C,
     168                                              data_blob_const(data, 36));
    114169                if (!NT_STATUS_IS_OK(status)) {
    115170                        talloc_free(req);
     
    158213                uint8_t data[32];
    159214
    160                 memcpy(&data[0], &io->in.lease_request->lease_key, 16);
    161                 SIVAL(data, 16, io->in.lease_request->lease_state);
    162                 SIVAL(data, 20, io->in.lease_request->lease_flags);
    163                 SBVAL(data, 24, io->in.lease_request->lease_duration);
    164 
    165                 status = smb2_create_blob_add(req, &blobs,
    166                                               SMB2_CREATE_TAG_RQLS,
    167                                               data_blob_const(data, 32));
     215                if (!smb2_lease_push(io->in.lease_request, data,
     216                                     sizeof(data))) {
     217                        TALLOC_FREE(req);
     218                        return NULL;
     219                }
     220
     221                status = smb2_create_blob_add(
     222                        req, &blobs, SMB2_CREATE_TAG_RQLS,
     223                        data_blob_const(data, sizeof(data)));
     224                if (!NT_STATUS_IS_OK(status)) {
     225                        talloc_free(req);
     226                        return NULL;
     227                }
     228        }
     229
     230        if (io->in.lease_request_v2) {
     231                uint8_t data[52];
     232
     233                if (!smb2_lease_push(io->in.lease_request_v2, data,
     234                                     sizeof(data))) {
     235                        TALLOC_FREE(req);
     236                        return NULL;
     237                }
     238
     239                status = smb2_create_blob_add(
     240                        req, &blobs, SMB2_CREATE_TAG_RQLS,
     241                        data_blob_const(data, sizeof(data)));
     242                if (!NT_STATUS_IS_OK(status)) {
     243                        talloc_free(req);
     244                        return NULL;
     245                }
     246        }
     247
     248        if (io->in.app_instance_id) {
     249                uint8_t data[20];
     250                DATA_BLOB guid_blob;
     251
     252                SSVAL(data, 0, 20); /* structure size */
     253                SSVAL(data, 2, 0);  /* reserved */
     254
     255                status = GUID_to_ndr_blob(io->in.app_instance_id,
     256                                          req, /* TALLOC_CTX */
     257                                          &guid_blob);
     258                if (!NT_STATUS_IS_OK(status)) {
     259                        talloc_free(req);
     260                        return NULL;
     261                }
     262                memcpy(data+4, guid_blob.data, 16);
     263
     264                status = smb2_create_blob_add(req, &blobs,
     265                                              SMB2_CREATE_TAG_APP_INSTANCE_ID,
     266                                              data_blob_const(data, 20));
    168267                if (!NT_STATUS_IS_OK(status)) {
    169268                        talloc_free(req);
     
    194293                talloc_free(req);
    195294                return NULL;
     295        }
     296
     297        if (((io->in.fname == NULL) || (strlen(io->in.fname) == 0)) &&
     298            (blob.length == 0)) {
     299                struct smb2_request_buffer *buf = &req->out;
     300
     301                status = smb2_grow_buffer(buf, 1);
     302                if (!NT_STATUS_IS_OK(status)) {
     303                        talloc_free(req);
     304                        return NULL;
     305                }
     306                buf->dynamic[0] = 0;
     307                buf->dynamic += 1;
     308                buf->body_size += 1;
     309                buf->size += 1;
    196310        }
    197311
     
    263377                }
    264378                if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_RQLS) == 0) {
     379                        struct smb2_lease *ls = NULL;
    265380                        uint8_t *data;
    266                         if (io->out.blobs.blobs[i].data.length != 32) {
     381
     382                        ZERO_STRUCT(io->out.lease_response);
     383                        ZERO_STRUCT(io->out.lease_response_v2);
     384
     385                        switch (io->out.blobs.blobs[i].data.length) {
     386                        case 32:
     387                                ls = &io->out.lease_response;
     388                                ls->lease_version = 1;
     389                                break;
     390                        case 52:
     391                                ls = &io->out.lease_response_v2;
     392                                ls->lease_version = 2;
     393                                break;
     394                        default:
    267395                                smb2_request_destroy(req);
    268396                                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     
    270398
    271399                        data = io->out.blobs.blobs[i].data.data;
    272                         memcpy(&io->out.lease_response.lease_key, data, 16);
    273                         io->out.lease_response.lease_state = IVAL(data, 16);
    274                         io->out.lease_response.lease_flags = IVAL(data, 20);
    275                         io->out.lease_response.lease_duration = BVAL(data, 24);
     400                        memcpy(&ls->lease_key, data, 16);
     401                        ls->lease_state = IVAL(data, 16);
     402                        ls->lease_flags = IVAL(data, 20);
     403                        ls->lease_duration = BVAL(data, 24);
     404
     405                        if (io->out.blobs.blobs[i].data.length == 52) {
     406                                memcpy(&ls->parent_lease_key, data+32, 16);
     407                                ls->lease_epoch = SVAL(data, 48);
     408                        }
     409                }
     410                if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 0) {
     411                        if (io->out.blobs.blobs[i].data.length != 8) {
     412                                smb2_request_destroy(req);
     413                                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     414                        }
     415                        io->out.durable_open = true;
     416                }
     417                if (strcmp(io->out.blobs.blobs[i].tag, SMB2_CREATE_TAG_DH2Q) == 0) {
     418                        uint32_t flags;
     419                        uint8_t *data;
     420
     421                        if (io->out.blobs.blobs[i].data.length != 8) {
     422                                smb2_request_destroy(req);
     423                                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     424                        }
     425
     426                        io->out.durable_open = false;
     427                        io->out.durable_open_v2 = true;
     428
     429                        data = io->out.blobs.blobs[i].data.data;
     430                        io->out.timeout = IVAL(data, 0);
     431                        flags = IVAL(data, 4);
     432                        if ((flags & SMB2_DHANDLE_FLAG_PERSISTENT) != 0) {
     433                                io->out.persistent_open = true;
     434                        }
    276435                }
    277436        }
  • vendor/current/source4/libcli/smb2/find.c

    r740 r988  
    3434        NTSTATUS status;
    3535
    36         req = smb2_request_init_tree(tree, SMB2_OP_FIND, 0x20, true, 0);
     36        req = smb2_request_init_tree(tree, SMB2_OP_QUERY_DIRECTORY, 0x20, true, 0);
    3737        if (req == NULL) return NULL;
    3838
  • vendor/current/source4/libcli/smb2/ioctl.c

    r414 r988  
    2323#include "libcli/smb2/smb2.h"
    2424#include "libcli/smb2/smb2_calls.h"
     25#include "librpc/gen_ndr/ioctl.h"
    2526
    2627/*
     
    6263}
    6364
     65/*
     66 * 3.3.4.4 Sending an Error Response
     67 */
     68static bool smb2_ioctl_is_failure(uint32_t ctl_code, NTSTATUS status,
     69                                  size_t data_size)
     70{
     71        if (NT_STATUS_IS_OK(status)) {
     72                return false;
     73        }
     74
     75        if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)
     76         && ((ctl_code == FSCTL_PIPE_TRANSCEIVE)
     77          || (ctl_code == FSCTL_PIPE_PEEK)
     78          || (ctl_code == FSCTL_DFS_GET_REFERRALS))) {
     79                return false;
     80        }
     81
     82        if (((ctl_code == FSCTL_SRV_COPYCHUNK)
     83                                || (ctl_code == FSCTL_SRV_COPYCHUNK_WRITE))
     84         && (data_size == sizeof(struct srv_copychunk_rsp))) {
     85                /*
     86                 * copychunk responses may come with copychunk data or error
     87                 * response data, independent of status.
     88                 */
     89                return false;
     90        }
     91
     92        return true;
     93}
    6494
    6595/*
    6696  recv a ioctl reply
    6797*/
    68 NTSTATUS smb2_ioctl_recv(struct smb2_request *req, 
     98NTSTATUS smb2_ioctl_recv(struct smb2_request *req,
    6999                         TALLOC_CTX *mem_ctx, struct smb2_ioctl *io)
    70100{
    71101        NTSTATUS status;
    72102
    73         if (!smb2_request_receive(req) ||
    74             smb2_request_is_error(req)) {
     103        if (!smb2_request_receive(req) ||
     104            smb2_ioctl_is_failure(io->in.function, req->status,
     105                                  req->in.bufinfo.data_size)) {
    75106                return smb2_request_destroy(req);
    76107        }
  • vendor/current/source4/libcli/smb2/logoff.c

    r414 r988  
    3636        req->session = session;
    3737
    38         SBVAL(req->out.hdr,  SMB2_HDR_SESSION_ID, session->uid);
    39 
    4038        SSVAL(req->out.body, 0x02, 0);
    4139
  • vendor/current/source4/libcli/smb2/read.c

    r414 r988  
    4545        SSVAL(req->out.body, 0x2E, io->in.channel_length);
    4646
     47        req->credit_charge = (MAX(io->in.length, 1) - 1)/ 65536 + 1;
     48
    4749        smb2_transport_send(req);
    4850
  • vendor/current/source4/libcli/smb2/request.c

    r740 r988  
    4343}
    4444
    45 
    46 /* destroy a request structure */
    47 static int smb2_request_destructor(struct smb2_request *req)
    48 {
    49         if (req->transport) {
    50                 /* remove it from the list of pending requests (a null op if
    51                    its not in the list) */
    52                 DLIST_REMOVE(req->transport->pending_recv, req);
    53         }
    54         return 0;
    55 }
    56 
    5745/*
    5846  initialise a smb2 request
     
    6351{
    6452        struct smb2_request *req;
    65         uint64_t seqnum;
    6653        uint32_t hdr_offset;
    67         uint32_t flags = 0;
    6854        bool compound = false;
    6955
     
    7662        }
    7763
    78         req = talloc(transport, struct smb2_request);
     64        req = talloc_zero(transport, struct smb2_request);
    7965        if (req == NULL) return NULL;
    80 
    81         seqnum = transport->seqnum;
    82         if (transport->credits.charge > 0) {
    83                 transport->seqnum += transport->credits.charge;
    84         } else {
    85                 transport->seqnum += 1;
    86         }
    8766
    8867        req->state     = SMB2_REQUEST_INIT;
    8968        req->transport = transport;
    90         req->session   = NULL;
    91         req->tree      = NULL;
    92         req->seqnum    = seqnum;
    93         req->status    = NT_STATUS_OK;
    94         req->async.fn  = NULL;
    95         req->next = req->prev = NULL;
    96 
    97         ZERO_STRUCT(req->cancel);
    98         ZERO_STRUCT(req->in);
    99 
    100         if (transport->compound.missing > 0) {
    101                 compound = true;
    102                 transport->compound.missing -= 1;
    103                 req->out = transport->compound.buffer;
    104                 ZERO_STRUCT(transport->compound.buffer);
    105                 if (transport->compound.related) {
    106                         flags |= SMB2_HDR_FLAG_CHAINED;
    107                 }
    108         } else {
    109                 ZERO_STRUCT(req->out);
    110         }
    111 
    112         if (req->out.size > 0) {
    113                 hdr_offset = req->out.size;
    114         } else {
    115                 hdr_offset = NBT_HDR_SIZE;
    116         }
     69
     70        hdr_offset = NBT_HDR_SIZE;
    11771
    11872        req->out.size      = hdr_offset + SMB2_HDR_BODY + body_fixed_size;
     
    13488        SIVAL(req->out.hdr, 0,                          SMB2_MAGIC);
    13589        SSVAL(req->out.hdr, SMB2_HDR_LENGTH,            SMB2_HDR_BODY);
    136         SSVAL(req->out.hdr, SMB2_HDR_EPOCH,             transport->credits.charge);
     90        SSVAL(req->out.hdr, SMB2_HDR_CREDIT_CHARGE,     0);
    13791        SIVAL(req->out.hdr, SMB2_HDR_STATUS,            0);
    13892        SSVAL(req->out.hdr, SMB2_HDR_OPCODE,            opcode);
    139         SSVAL(req->out.hdr, SMB2_HDR_CREDIT,            transport->credits.ask_num);
    140         SIVAL(req->out.hdr, SMB2_HDR_FLAGS,             flags);
     93        SSVAL(req->out.hdr, SMB2_HDR_CREDIT,            0);
     94        SIVAL(req->out.hdr, SMB2_HDR_FLAGS,             0);
    14195        SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND,      0);
    142         SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID,        req->seqnum);
     96        SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID,        0);
    14397        SIVAL(req->out.hdr, SMB2_HDR_PID,               0);
    14498        SIVAL(req->out.hdr, SMB2_HDR_TID,               0);
     
    158112        }
    159113
    160         talloc_set_destructor(req, smb2_request_destructor);
    161 
    162114        return req;
    163115}
     
    175127        if (req == NULL) return NULL;
    176128
    177         SBVAL(req->out.hdr,  SMB2_HDR_SESSION_ID, tree->session->uid);
    178         SIVAL(req->out.hdr,  SMB2_HDR_PID, tree->session->pid);
    179         SIVAL(req->out.hdr,  SMB2_HDR_TID, tree->tid);
    180129        req->session = tree->session;
    181130        req->tree = tree;
     
    215164        /* keep receiving packets until this one is replied to */
    216165        while (req->state <= SMB2_REQUEST_RECV) {
    217                 if (event_loop_once(req->transport->socket->event.ctx) != 0) {
     166                if (tevent_loop_once(req->transport->ev) != 0) {
    218167                        return false;
    219168                }
     
    687636        NTSTATUS status;
    688637        void *vstr;
     638        size_t converted_size = 0;
    689639        bool ret;
    690640
     
    706656
    707657        ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
    708                                      blob.data, blob.length, &vstr, NULL, false);
     658                                     blob.data, blob.length, &vstr, &converted_size);
    709659        data_blob_free(&blob);
    710660        (*str) = (char *)vstr;
     
    725675        NTSTATUS status;
    726676        bool ret;
     677        void *ptr = NULL;
    727678
    728679        if (str == NULL) {
     
    737688
    738689        ret = convert_string_talloc(buf->buffer, CH_UNIX, CH_UTF16,
    739                                      str, strlen(str), (void **)&blob.data, &blob.length,
    740                                          false);
     690                                    str, strlen(str), &ptr, &blob.length);
    741691        if (!ret) {
    742692                return NT_STATUS_ILLEGAL_CHARACTER;
    743693        }
     694        blob.data = (uint8_t *)ptr;
    744695
    745696        status = smb2_push_o16s16_blob(buf, ofs, blob);
  • vendor/current/source4/libcli/smb2/session.c

    r740 r988  
    2121
    2222#include "includes.h"
     23#include "system/network.h"
     24#include <tevent.h>
     25#include "lib/util/tevent_ntstatus.h"
    2326#include "libcli/raw/libcliraw.h"
    2427#include "libcli/smb2/smb2.h"
    2528#include "libcli/smb2/smb2_calls.h"
    26 #include "libcli/composite/composite.h"
    2729#include "auth/gensec/gensec.h"
    28 
    29 #include <unistd.h>
     30#include "auth/credentials/credentials.h"
     31#include "../libcli/smb/smbXcli_base.h"
    3032
    3133/**
     
    3436struct smb2_session *smb2_session_init(struct smb2_transport *transport,
    3537                                       struct gensec_settings *settings,
    36                                        TALLOC_CTX *parent_ctx, bool primary)
     38                                       TALLOC_CTX *parent_ctx)
    3739{
    3840        struct smb2_session *session;
     
    4345                return NULL;
    4446        }
    45         if (primary) {
    46                 session->transport = talloc_steal(session, transport);
    47         } else {
    48                 session->transport = talloc_reference(session, transport);
    49         }
    50 
    51         session->pid = getpid();
     47        session->transport = talloc_steal(session, transport);
     48
     49        session->smbXcli = smbXcli_session_create(session, transport->conn);
     50        if (session->smbXcli == NULL) {
     51                talloc_free(session);
     52                return NULL;
     53        }
    5254
    5355        /* prepare a gensec context for later use */
    54         status = gensec_client_start(session, &session->gensec,
    55                                      session->transport->socket->event.ctx,
     56        status = gensec_client_start(session, &session->gensec,
    5657                                     settings);
    5758        if (!NT_STATUS_IS_OK(status)) {
     
    6566}
    6667
    67 /**
    68   send a session setup request
    69 */
    70 struct smb2_request *smb2_session_setup_send(struct smb2_session *session,
    71                                              struct smb2_session_setup *io)
    72 {
    73         struct smb2_request *req;
    74         NTSTATUS status;
    75        
    76         req = smb2_request_init(session->transport, SMB2_OP_SESSSETUP,
    77                                 0x18, true, io->in.secblob.length);
    78         if (req == NULL) return NULL;
    79 
    80         SBVAL(req->out.hdr,  SMB2_HDR_SESSION_ID, session->uid);
    81         SCVAL(req->out.body, 0x02, io->in.vc_number);
    82         SCVAL(req->out.body, 0x03, io->in.security_mode);
    83         SIVAL(req->out.body, 0x04, io->in.capabilities);
    84         SIVAL(req->out.body, 0x08, io->in.channel);
    85         SBVAL(req->out.body, 0x10, io->in.previous_sessionid);
    86 
    87         req->session = session;
    88 
    89         status = smb2_push_o16s16_blob(&req->out, 0x0C, io->in.secblob);
     68/*
     69 * Note: that the caller needs to keep 'transport' around as
     70 *       long as the returned session is active!
     71 */
     72struct smb2_session *smb2_session_channel(struct smb2_transport *transport,
     73                                          struct gensec_settings *settings,
     74                                          TALLOC_CTX *parent_ctx,
     75                                          struct smb2_session *base_session)
     76{
     77        struct smb2_session *session;
     78        NTSTATUS status;
     79
     80        session = talloc_zero(parent_ctx, struct smb2_session);
     81        if (!session) {
     82                return NULL;
     83        }
     84        session->transport = transport;
     85
     86        status = smb2cli_session_create_channel(session,
     87                                                base_session->smbXcli,
     88                                                transport->conn,
     89                                                &session->smbXcli);
    9090        if (!NT_STATUS_IS_OK(status)) {
    91                 talloc_free(req);
    92                 return NULL;
    93         }
    94 
    95         smb2_transport_send(req);
    96 
    97         return req;
    98 }
    99 
    100 
    101 /**
    102   recv a session setup reply
    103 */
    104 NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
    105                                  struct smb2_session_setup *io)
    106 {
    107         NTSTATUS status;
    108 
    109         if (!smb2_request_receive(req) ||
    110             (smb2_request_is_error(req) &&
    111              !NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED))) {
    112                 return smb2_request_destroy(req);
    113         }
    114 
    115         SMB2_CHECK_PACKET_RECV(req, 0x08, true);
    116 
    117         io->out.session_flags = SVAL(req->in.body, 0x02);
    118         io->out.uid           = BVAL(req->in.hdr,  SMB2_HDR_SESSION_ID);
    119        
    120         status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x04, &io->out.secblob);
     91                talloc_free(session);
     92                return NULL;
     93        }
     94
     95        session->needs_bind = true;
     96
     97        /* prepare a gensec context for later use */
     98        status = gensec_client_start(session, &session->gensec,
     99                                     settings);
    121100        if (!NT_STATUS_IS_OK(status)) {
    122                 smb2_request_destroy(req);
    123                 return status;
    124         }
    125 
    126         return smb2_request_destroy(req);
    127 }
    128 
    129 /*
    130   sync session setup request
    131 */
    132 NTSTATUS smb2_session_setup(struct smb2_session *session,
    133                             TALLOC_CTX *mem_ctx, struct smb2_session_setup *io)
    134 {
    135         struct smb2_request *req = smb2_session_setup_send(session, io);
    136         return smb2_session_setup_recv(req, mem_ctx, io);
    137 }
    138 
    139 
    140 struct smb2_session_state {
    141         struct smb2_session_setup io;
    142         struct smb2_request *req;
     101                talloc_free(session);
     102                return NULL;
     103        }
     104
     105        gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
     106
     107        return session;
     108}
     109
     110struct smb2_session_setup_spnego_state {
     111        struct tevent_context *ev;
     112        struct smb2_session *session;
     113        struct cli_credentials *credentials;
     114        uint64_t previous_session_id;
     115        bool session_bind;
     116        bool reauth;
    143117        NTSTATUS gensec_status;
     118        DATA_BLOB in_secblob;
     119        DATA_BLOB out_secblob;
    144120};
    145121
    146 /*
    147   handle continuations of the spnego session setup
    148 */
    149 static void session_request_handler(struct smb2_request *req)
    150 {
    151         struct composite_context *c = talloc_get_type(req->async.private_data,
    152                                                       struct composite_context);
    153         struct smb2_session_state *state = talloc_get_type(c->private_data,
    154                                                            struct smb2_session_state);
    155         struct smb2_session *session = req->session;
    156         NTSTATUS session_key_err;
    157         DATA_BLOB session_key;
    158         NTSTATUS peer_status;
    159 
    160         c->status = smb2_session_setup_recv(req, c, &state->io);
    161         peer_status = c->status;
    162 
    163         if (NT_STATUS_EQUAL(peer_status, NT_STATUS_MORE_PROCESSING_REQUIRED) ||
    164             (NT_STATUS_IS_OK(peer_status) &&
    165              NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED))) {
    166                 c->status = gensec_update(session->gensec, c,
    167                                           state->io.out.secblob,
    168                                           &state->io.in.secblob);
    169                 state->gensec_status = c->status;
    170 
    171                 session->uid = state->io.out.uid;
    172         }
    173 
    174         if (!NT_STATUS_IS_OK(c->status) &&
    175             !NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    176                 composite_error(c, c->status);
    177                 return;
    178         }
    179 
    180         if (NT_STATUS_EQUAL(peer_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    181                 state->req = smb2_session_setup_send(session, &state->io);
    182                 if (state->req == NULL) {
    183                         composite_error(c, NT_STATUS_NO_MEMORY);
    184                         return;
    185                 }
    186 
    187                 state->req->async.fn = session_request_handler;
    188                 state->req->async.private_data = c;
    189                 return;
    190         }
    191 
    192         session_key_err = gensec_session_key(session->gensec, &session_key);
    193         if (NT_STATUS_IS_OK(session_key_err)) {
    194                 session->session_key = session_key;
    195         }
    196 
    197         if (session->transport->signing_required) {
    198                 if (session->session_key.length == 0) {
    199                         DEBUG(0,("Wrong session key length %u for SMB2 signing\n",
    200                                  (unsigned)session->session_key.length));
    201                         composite_error(c, NT_STATUS_ACCESS_DENIED);
    202                         return;
    203                 }
    204                 session->signing_active = true;
    205         }
    206 
    207         composite_done(c);
    208 }
     122static void smb2_session_setup_spnego_done(struct tevent_req *subreq);
    209123
    210124/*
    211125  a composite function that does a full SPNEGO session setup
    212126 */
    213 struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *session,
    214                                                          struct cli_credentials *credentials)
    215 {
    216         struct composite_context *c;
    217         struct smb2_session_state *state;
     127struct tevent_req *smb2_session_setup_spnego_send(
     128                                TALLOC_CTX *mem_ctx,
     129                                struct tevent_context *ev,
     130                                struct smb2_session *session,
     131                                struct cli_credentials *credentials,
     132                                uint64_t previous_session_id)
     133{
     134        struct tevent_req *req;
     135        struct smb2_session_setup_spnego_state *state;
     136        uint64_t current_session_id;
    218137        const char *chosen_oid;
    219 
    220         c = composite_create(session, session->transport->socket->event.ctx);
    221         if (c == NULL) return NULL;
    222 
    223         state = talloc(c, struct smb2_session_state);
    224         if (composite_nomem(state, c)) return c;
    225         c->private_data = state;
    226 
    227         ZERO_STRUCT(state->io);
    228         state->io.in.vc_number          = 0;
    229         if (session->transport->signing_required) {
    230                 state->io.in.security_mode =
    231                         SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED;
    232         }
    233         state->io.in.capabilities       = 0;
    234         state->io.in.channel            = 0;
    235         state->io.in.previous_sessionid = 0;
    236 
    237         c->status = gensec_set_credentials(session->gensec, credentials);
    238         if (!composite_is_ok(c)) return c;
    239 
    240         c->status = gensec_set_target_hostname(session->gensec,
    241                                                session->transport->socket->hostname);
    242         if (!composite_is_ok(c)) return c;
    243 
    244         c->status = gensec_set_target_service(session->gensec, "cifs");
    245         if (!composite_is_ok(c)) return c;
    246 
    247         if (session->transport->negotiate.secblob.length > 0) {
     138        struct tevent_req *subreq;
     139        NTSTATUS status;
     140        const DATA_BLOB *server_gss_blob;
     141        DATA_BLOB negprot_secblob = data_blob_null;
     142        uint32_t timeout_msec;
     143        uint8_t in_flags = 0;
     144
     145        timeout_msec = session->transport->options.request_timeout * 1000;
     146
     147        req = tevent_req_create(mem_ctx, &state,
     148                                struct smb2_session_setup_spnego_state);
     149        if (req == NULL) {
     150                return NULL;
     151        }
     152        state->ev = ev;
     153        state->session = session;
     154        state->credentials = credentials;
     155        state->previous_session_id = previous_session_id;
     156
     157        current_session_id = smb2cli_session_current_id(state->session->smbXcli);
     158        if (state->session->needs_bind) {
     159                state->session_bind = true;
     160        } else if (current_session_id != 0) {
     161                state->reauth = true;
     162        }
     163        server_gss_blob = smbXcli_conn_server_gss_blob(session->transport->conn);
     164        if (server_gss_blob) {
     165                negprot_secblob = *server_gss_blob;
     166        }
     167
     168        status = gensec_set_credentials(session->gensec, credentials);
     169        if (tevent_req_nterror(req, status)) {
     170                return tevent_req_post(req, ev);
     171        }
     172
     173        status = gensec_set_target_hostname(session->gensec,
     174                                            smbXcli_conn_remote_name(session->transport->conn));
     175        if (tevent_req_nterror(req, status)) {
     176                return tevent_req_post(req, ev);
     177        }
     178
     179        status = gensec_set_target_service(session->gensec, "cifs");
     180        if (tevent_req_nterror(req, status)) {
     181                return tevent_req_post(req, ev);
     182        }
     183
     184        if (negprot_secblob.length > 0) {
    248185                chosen_oid = GENSEC_OID_SPNEGO;
    249186        } else {
     
    251188        }
    252189
    253         c->status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
    254         if (!composite_is_ok(c)) return c;
    255 
    256         c->status = gensec_update(session->gensec, c,
    257                                   session->transport->negotiate.secblob,
    258                                   &state->io.in.secblob);
    259         if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    260                 composite_error(c, c->status);
    261                 return c;
    262         }
    263         state->gensec_status = c->status;
    264                
    265         state->req = smb2_session_setup_send(session, &state->io);
    266         composite_continue_smb2(c, state->req, session_request_handler, c);
    267         return c;
     190        status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
     191        if (tevent_req_nterror(req, status)) {
     192                return tevent_req_post(req, ev);
     193        }
     194
     195        status = gensec_update_ev(session->gensec, state,
     196                               state->ev,
     197                               negprot_secblob,
     198                               &state->in_secblob);
     199        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     200                tevent_req_nterror(req, status);
     201                return tevent_req_post(req, ev);
     202        }
     203        state->gensec_status = status;
     204
     205        if (state->session_bind) {
     206                in_flags |= SMB2_SESSION_FLAG_BINDING;
     207        }
     208
     209        subreq = smb2cli_session_setup_send(state, state->ev,
     210                                            session->transport->conn,
     211                                            timeout_msec,
     212                                            session->smbXcli,
     213                                            in_flags,
     214                                            0, /* in_capabilities */
     215                                            0, /* in_channel */
     216                                            state->previous_session_id,
     217                                            &state->in_secblob);
     218        if (tevent_req_nomem(subreq, req)) {
     219                return tevent_req_post(req, ev);
     220        }
     221        tevent_req_set_callback(subreq, smb2_session_setup_spnego_done, req);
     222
     223        return req;
     224}
     225
     226/*
     227  handle continuations of the spnego session setup
     228*/
     229static void smb2_session_setup_spnego_done(struct tevent_req *subreq)
     230{
     231        struct tevent_req *req =
     232                tevent_req_callback_data(subreq,
     233                struct tevent_req);
     234        struct smb2_session_setup_spnego_state *state =
     235                tevent_req_data(req,
     236                struct smb2_session_setup_spnego_state);
     237        struct smb2_session *session = state->session;
     238        NTSTATUS peer_status;
     239        NTSTATUS status;
     240        struct iovec *recv_iov;
     241        uint32_t timeout_msec;
     242        uint8_t in_flags = 0;
     243
     244        timeout_msec = session->transport->options.request_timeout * 1000;
     245
     246        status = smb2cli_session_setup_recv(subreq, state,
     247                                            &recv_iov,
     248                                            &state->out_secblob);
     249        if (!NT_STATUS_IS_OK(status) &&
     250            !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     251                tevent_req_nterror(req, status);
     252                return;
     253        }
     254        peer_status = status;
     255
     256        if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     257                status = gensec_update_ev(session->gensec, state,
     258                                       state->ev,
     259                                       state->out_secblob,
     260                                       &state->in_secblob);
     261                state->gensec_status = status;
     262        }
     263
     264        if (!NT_STATUS_IS_OK(status) &&
     265            !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     266                tevent_req_nterror(req, status);
     267                return;
     268        }
     269
     270        if (NT_STATUS_IS_OK(peer_status) && NT_STATUS_IS_OK(state->gensec_status)) {
     271                DATA_BLOB session_key;
     272
     273                if (state->reauth) {
     274                        tevent_req_done(req);
     275                        return;
     276                }
     277
     278                if (cli_credentials_is_anonymous(state->credentials)) {
     279                        /*
     280                         * Windows server does not set the
     281                         * SMB2_SESSION_FLAG_IS_GUEST nor
     282                         * SMB2_SESSION_FLAG_IS_NULL flag.
     283                         *
     284                         * This fix makes sure we do not try
     285                         * to verify a signature on the final
     286                         * session setup response.
     287                         */
     288                        tevent_req_done(req);
     289                        return;
     290                }
     291
     292                status = gensec_session_key(session->gensec, state,
     293                                            &session_key);
     294                if (tevent_req_nterror(req, status)) {
     295                        return;
     296                }
     297
     298                if (state->session_bind) {
     299                        status = smb2cli_session_set_channel_key(session->smbXcli,
     300                                                                 session_key,
     301                                                                 recv_iov);
     302                        if (tevent_req_nterror(req, status)) {
     303                                return;
     304                        }
     305                        session->needs_bind = false;
     306                } else {
     307                        status = smb2cli_session_set_session_key(session->smbXcli,
     308                                                                 session_key,
     309                                                                 recv_iov);
     310                        if (tevent_req_nterror(req, status)) {
     311                                return;
     312                        }
     313                }
     314                tevent_req_done(req);
     315                return;
     316        }
     317
     318        if (state->session_bind) {
     319                in_flags |= SMB2_SESSION_FLAG_BINDING;
     320        }
     321
     322        subreq = smb2cli_session_setup_send(state, state->ev,
     323                                            session->transport->conn,
     324                                            timeout_msec,
     325                                            session->smbXcli,
     326                                            in_flags,
     327                                            0, /* in_capabilities */
     328                                            0, /* in_channel */
     329                                            state->previous_session_id,
     330                                            &state->in_secblob);
     331        if (tevent_req_nomem(subreq, req)) {
     332                return;
     333        }
     334        tevent_req_set_callback(subreq, smb2_session_setup_spnego_done, req);
    268335}
    269336
     
    271338  receive a composite session setup reply
    272339*/
    273 NTSTATUS smb2_session_setup_spnego_recv(struct composite_context *c)
    274 {
    275         NTSTATUS status;
    276         status = composite_wait(c);
    277         talloc_free(c);
    278         return status;
     340NTSTATUS smb2_session_setup_spnego_recv(struct tevent_req *req)
     341{
     342        return tevent_req_simple_recv_ntstatus(req);
    279343}
    280344
     
    283347*/
    284348NTSTATUS smb2_session_setup_spnego(struct smb2_session *session,
    285                                    struct cli_credentials *credentials)
    286 {
    287         struct composite_context *c = smb2_session_setup_spnego_send(session, credentials);
    288         return smb2_session_setup_spnego_recv(c);
    289 }
     349                                   struct cli_credentials *credentials,
     350                                   uint64_t previous_session_id)
     351{
     352        struct tevent_req *subreq;
     353        NTSTATUS status;
     354        bool ok;
     355        TALLOC_CTX *frame = talloc_stackframe();
     356        struct tevent_context *ev = session->transport->ev;
     357
     358        if (frame == NULL) {
     359                return NT_STATUS_NO_MEMORY;
     360        }
     361
     362        subreq = smb2_session_setup_spnego_send(frame, ev,
     363                                                session, credentials,
     364                                                previous_session_id);
     365        if (subreq == NULL) {
     366                TALLOC_FREE(frame);
     367                return NT_STATUS_NO_MEMORY;
     368        }
     369
     370        ok = tevent_req_poll(subreq, ev);
     371        if (!ok) {
     372                status = map_nt_error_from_unix_common(errno);
     373                TALLOC_FREE(frame);
     374                return status;
     375        }
     376
     377        status = smb2_session_setup_spnego_recv(subreq);
     378        TALLOC_FREE(subreq);
     379        if (!NT_STATUS_IS_OK(status)) {
     380                TALLOC_FREE(frame);
     381                return status;
     382        }
     383
     384        TALLOC_FREE(frame);
     385        return NT_STATUS_OK;
     386}
  • vendor/current/source4/libcli/smb2/smb2.h

    r740 r988  
    2828struct smb2_handle;
    2929struct smb2_lease_break;
    30 
    31 /*
    32   information returned from the negotiate process
    33 */
    34 struct smb2_negotiate {
    35         DATA_BLOB secblob;
    36         NTTIME system_time;
    37         NTTIME server_start_time;
    38         uint16_t security_mode;
    39         uint16_t dialect_revision;
    40 };
    4130
    4231struct smb2_request_buffer {
     
    7160/* this is the context for the smb2 transport layer */
    7261struct smb2_transport {
    73         /* socket level info */
    74         struct smbcli_socket *socket;
    75 
    76         struct smb2_negotiate negotiate;
    77 
    78         /* next seqnum to allocate */
    79         uint64_t seqnum;
     62        struct tevent_context *ev; /* TODO: remove this !!! */
     63        struct smbXcli_conn *conn;
    8064
    8165        /* the details for coumpounded requests */
    8266        struct {
    83                 uint32_t missing;
    8467                bool related;
    85                 struct smb2_request_buffer buffer;
     68                struct tevent_req **reqs;
    8669        } compound;
    87 
    88         struct {
    89                 uint16_t charge;
    90                 uint16_t ask_num;
    91         } credits;
    92 
    93         /* a list of requests that are pending for receive on this
    94            connection */
    95         struct smb2_request *pending_recv;
    96 
    97         /* context of the stream -> packet parser */
    98         struct packet_context *packet;
    9970
    10071        /* an idle function - if this is defined then it will be
     
    10576                void *private_data;
    10677                unsigned int period;
     78                struct tevent_timer *te;
    10779        } idle;
    10880
     
    12496                void *private_data;
    12597        } lease;
     98        struct tevent_req *break_subreq;
    12699
    127100        struct smbcli_options options;
    128 
    129         bool signing_required;
    130101};
    131102
     
    136107struct smb2_tree {
    137108        struct smb2_session *session;
    138         uint32_t tid;
     109        struct smbXcli_tcon *smbXcli;
    139110};
    140111
     
    145116        struct smb2_transport *transport;
    146117        struct gensec_security *gensec;
    147         uint64_t uid;
    148         uint32_t pid;
    149         DATA_BLOB session_key;
    150         bool signing_active;
     118        struct smbXcli_session *smbXcli;
     119        bool needs_bind;
    151120};
    152121
     
    163132/* the context for a single SMB2 request */
    164133struct smb2_request {
    165         /* allow a request to be part of a list of requests */
    166         struct smb2_request *next, *prev;
    167 
    168134        /* each request is in one of 3 possible states */
    169135        enum smb2_request_state state;
     136
     137        struct tevent_req *subreq;
    170138
    171139        struct smb2_transport *transport;
     
    173141        struct smb2_tree      *tree;
    174142
    175         uint64_t seqnum;
    176 
    177143        struct {
    178                 bool do_cancel;
    179144                bool can_cancel;
    180                 uint64_t async_id;
    181145        } cancel;
    182146
     
    187151        struct smb2_request_buffer in;
    188152        struct smb2_request_buffer out;
     153        struct iovec *recv_iov;
     154
     155        uint16_t credit_charge;
    189156
    190157        /* information on what to do with a reply when it is received
  • vendor/current/source4/libcli/smb2/tcon.c

    r414 r988  
    2323#include "libcli/smb2/smb2.h"
    2424#include "libcli/smb2/smb2_calls.h"
     25#include "../libcli/smb/smbXcli_base.h"
    2526
    2627/*
     
    4142                tree->session = talloc_reference(tree, session);
    4243        }
    43         return tree;
    44 }
    4544
    46 /*
    47   send a tree connect
    48 */
    49 struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree,
    50                                             struct smb2_tree_connect *io)
    51 {
    52         struct smb2_request *req;
    53         NTSTATUS status;
    54 
    55         req = smb2_request_init(tree->session->transport, SMB2_OP_TCON,
    56                                 0x08, true, 0);
    57         if (req == NULL) return NULL;
    58 
    59         SBVAL(req->out.hdr,  SMB2_HDR_SESSION_ID, tree->session->uid);
    60         req->session = tree->session;
    61 
    62         SSVAL(req->out.body, 0x02, io->in.reserved);
    63         status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path);
    64         if (!NT_STATUS_IS_OK(status)) {
    65                 talloc_free(req);
     45        tree->smbXcli = smbXcli_tcon_create(tree);
     46        if (tree->smbXcli == NULL) {
     47                talloc_free(tree);
    6648                return NULL;
    6749        }
    6850
    69         smb2_transport_send(req);
    70 
    71         return req;
     51        return tree;
    7252}
    73 
    74 
    75 /*
    76   recv a tree connect reply
    77 */
    78 NTSTATUS smb2_tree_connect_recv(struct smb2_request *req, struct smb2_tree_connect *io)
    79 {
    80         if (!smb2_request_receive(req) ||
    81             smb2_request_is_error(req)) {
    82                 return smb2_request_destroy(req);
    83         }
    84 
    85         SMB2_CHECK_PACKET_RECV(req, 0x10, false);
    86 
    87         io->out.tid      = IVAL(req->in.hdr,  SMB2_HDR_TID);
    88 
    89         io->out.share_type  = CVAL(req->in.body, 0x02);
    90         io->out.reserved    = CVAL(req->in.body, 0x03);
    91         io->out.flags       = IVAL(req->in.body, 0x04);
    92         io->out.capabilities= IVAL(req->in.body, 0x08);
    93         io->out.access_mask = IVAL(req->in.body, 0x0C);
    94 
    95         if (io->out.capabilities & ~SMB2_CAP_ALL) {
    96                 DEBUG(0,("Unknown capabilities mask 0x%x\n", io->out.capabilities));
    97         }
    98         if (io->out.flags & ~SMB2_SHAREFLAG_ALL) {
    99                 DEBUG(0,("Unknown tcon shareflag 0x%x\n", io->out.flags));
    100         }
    101        
    102         return smb2_request_destroy(req);
    103 }
    104 
    105 /*
    106   sync tree connect request
    107 */
    108 NTSTATUS smb2_tree_connect(struct smb2_tree *tree, struct smb2_tree_connect *io)
    109 {
    110         struct smb2_request *req = smb2_tree_connect_send(tree, io);
    111         return smb2_tree_connect_recv(req, io);
    112 }
  • vendor/current/source4/libcli/smb2/transport.c

    r740 r988  
    2121
    2222#include "includes.h"
     23#include "system/network.h"
    2324#include "libcli/raw/libcliraw.h"
    2425#include "libcli/raw/raw_proto.h"
     
    2728#include "lib/socket/socket.h"
    2829#include "lib/events/events.h"
    29 #include "lib/stream/packet.h"
    3030#include "../lib/util/dlinklist.h"
    31 
    32 
    33 /*
    34   an event has happened on the socket
    35 */
    36 static void smb2_transport_event_handler(struct tevent_context *ev,
    37                                          struct tevent_fd *fde,
    38                                          uint16_t flags, void *private_data)
    39 {
    40         struct smb2_transport *transport = talloc_get_type(private_data,
    41                                                            struct smb2_transport);
    42         if (flags & EVENT_FD_READ) {
    43                 packet_recv(transport->packet);
    44                 return;
    45         }
    46         if (flags & EVENT_FD_WRITE) {
    47                 packet_queue_run(transport->packet);
    48         }
    49 }
     31#include "../libcli/smb/smbXcli_base.h"
     32#include "librpc/ndr/libndr.h"
    5033
    5134/*
     
    5740        return 0;
    5841}
    59 
    60 
    61 /*
    62   handle receive errors
    63 */
    64 static void smb2_transport_error(void *private_data, NTSTATUS status)
    65 {
    66         struct smb2_transport *transport = talloc_get_type(private_data,
    67                                                            struct smb2_transport);
    68         smb2_transport_dead(transport, status);
    69 }
    70 
    71 static NTSTATUS smb2_transport_finish_recv(void *private_data, DATA_BLOB blob);
    7242
    7343/*
     
    8353        if (!transport) return NULL;
    8454
    85         transport->socket = talloc_steal(transport, sock);
     55        transport->ev = sock->event.ctx;
    8656        transport->options = *options;
    87         transport->credits.charge = 0;
    88         transport->credits.ask_num = 1;
    89 
    90         /* setup the stream -> packet parser */
    91         transport->packet = packet_init(transport);
    92         if (transport->packet == NULL) {
     57
     58        if (transport->options.max_protocol == PROTOCOL_DEFAULT) {
     59                transport->options.max_protocol = PROTOCOL_LATEST;
     60        }
     61
     62        if (transport->options.max_protocol < PROTOCOL_SMB2_02) {
     63                transport->options.max_protocol = PROTOCOL_LATEST;
     64        }
     65
     66        TALLOC_FREE(sock->event.fde);
     67        TALLOC_FREE(sock->event.te);
     68
     69        transport->conn = smbXcli_conn_create(transport,
     70                                              sock->sock->fd,
     71                                              sock->hostname,
     72                                              options->signing,
     73                                              0, /* smb1_capabilities */
     74                                              &options->client_guid,
     75                                              options->smb2_capabilities);
     76        if (transport->conn == NULL) {
    9377                talloc_free(transport);
    9478                return NULL;
    9579        }
    96         packet_set_private(transport->packet, transport);
    97         packet_set_socket(transport->packet, transport->socket->sock);
    98         packet_set_callback(transport->packet, smb2_transport_finish_recv);
    99         packet_set_full_request(transport->packet, packet_full_request_nbt);
    100         packet_set_error_handler(transport->packet, smb2_transport_error);
    101         packet_set_event_context(transport->packet, transport->socket->event.ctx);
    102         packet_set_nofree(transport->packet);
    103 
    104         /* take over event handling from the socket layer - it only
    105            handles events up until we are connected */
    106         talloc_free(transport->socket->event.fde);
    107         transport->socket->event.fde = event_add_fd(transport->socket->event.ctx,
    108                                                     transport->socket,
    109                                                     socket_get_fd(transport->socket->sock),
    110                                                     EVENT_FD_READ,
    111                                                     smb2_transport_event_handler,
    112                                                     transport);
    113 
    114         packet_set_fde(transport->packet, transport->socket->event.fde);
    115         packet_set_serialise(transport->packet);
     80        sock->sock->fd = -1;
     81        TALLOC_FREE(sock);
    11682
    11783        talloc_set_destructor(transport, transport_destructor);
     
    12591void smb2_transport_dead(struct smb2_transport *transport, NTSTATUS status)
    12692{
    127         smbcli_sock_dead(transport->socket);
    128 
    12993        if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
    13094                status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    13195        }
    132 
    133         /* kill all pending receives */
    134         while (transport->pending_recv) {
    135                 struct smb2_request *req = transport->pending_recv;
     96        if (NT_STATUS_IS_OK(status)) {
     97                status = NT_STATUS_LOCAL_DISCONNECT;
     98        }
     99
     100        smbXcli_conn_disconnect(transport->conn, status);
     101}
     102
     103static void smb2_request_done(struct tevent_req *subreq);
     104static void smb2_transport_break_handler(struct tevent_req *subreq);
     105
     106/*
     107  put a request into the send queue
     108*/
     109void smb2_transport_send(struct smb2_request *req)
     110{
     111        NTSTATUS status;
     112        struct smb2_transport *transport = req->transport;
     113        struct tevent_req **reqs = transport->compound.reqs;
     114        size_t num_reqs = talloc_array_length(reqs);
     115        size_t i;
     116        uint16_t cmd = SVAL(req->out.hdr, SMB2_HDR_OPCODE);
     117        uint32_t additional_flags = IVAL(req->out.hdr, SMB2_HDR_FLAGS);
     118        uint32_t clear_flags = 0;
     119        struct smbXcli_tcon *tcon = NULL;
     120        struct smbXcli_session *session = NULL;
     121        bool need_pending_break = false;
     122        size_t hdr_ofs;
     123        size_t pdu_len;
     124        DATA_BLOB body = data_blob_null;
     125        DATA_BLOB dyn = data_blob_null;
     126        uint32_t timeout_msec = transport->options.request_timeout * 1000;
     127
     128        if (transport->oplock.handler) {
     129                need_pending_break = true;
     130        }
     131
     132        if (transport->lease.handler) {
     133                need_pending_break = true;
     134        }
     135
     136        if (transport->break_subreq) {
     137                need_pending_break = false;
     138        }
     139
     140        if (need_pending_break) {
     141                struct tevent_req *subreq;
     142
     143                subreq = smb2cli_req_create(transport,
     144                                            transport->ev,
     145                                            transport->conn,
     146                                            SMB2_OP_BREAK,
     147                                            0, /* additional_flags */
     148                                            0, /*clear_flags */
     149                                            0, /* timeout_msec */
     150                                            NULL, /* tcon */
     151                                            NULL, /* session */
     152                                            NULL, /* body */
     153                                            0, /* body_fixed */
     154                                            NULL, /* dyn */
     155                                            0, /* dyn_len */
     156                                            0); /* max_dyn_len */
     157                if (subreq != NULL) {
     158                        smbXcli_req_set_pending(subreq);
     159                        tevent_req_set_callback(subreq,
     160                                                smb2_transport_break_handler,
     161                                                transport);
     162                        transport->break_subreq = subreq;
     163                }
     164        }
     165
     166        if (req->session) {
     167                session = req->session->smbXcli;
     168        }
     169
     170        if (req->tree) {
     171                tcon = req->tree->smbXcli;
     172        }
     173
     174        if (transport->compound.related) {
     175                additional_flags |= SMB2_HDR_FLAG_CHAINED;
     176        }
     177
     178        hdr_ofs = PTR_DIFF(req->out.hdr, req->out.buffer);
     179        pdu_len = req->out.size - hdr_ofs;
     180        body.data = req->out.body;
     181        body.length = req->out.body_fixed;
     182        dyn.data = req->out.body + req->out.body_fixed;
     183        dyn.length = pdu_len - (SMB2_HDR_BODY + req->out.body_fixed);
     184
     185        req->subreq = smb2cli_req_create(req,
     186                                         transport->ev,
     187                                         transport->conn,
     188                                         cmd,
     189                                         additional_flags,
     190                                         clear_flags,
     191                                         timeout_msec,
     192                                         tcon,
     193                                         session,
     194                                         body.data, body.length,
     195                                         dyn.data, dyn.length,
     196                                         0); /* max_dyn_len */
     197        if (req->subreq == NULL) {
    136198                req->state = SMB2_REQUEST_ERROR;
     199                req->status = NT_STATUS_NO_MEMORY;
     200                return;
     201        }
     202
     203        if (!tevent_req_is_in_progress(req->subreq)) {
     204                req->state = SMB2_REQUEST_ERROR;
     205                req->status = NT_STATUS_INTERNAL_ERROR;/* TODO */
     206                return;
     207        }
     208
     209        tevent_req_set_callback(req->subreq, smb2_request_done, req);
     210
     211        smb2cli_req_set_notify_async(req->subreq);
     212        if (req->credit_charge) {
     213                smb2cli_req_set_credit_charge(req->subreq, req->credit_charge);
     214        }
     215
     216        ZERO_STRUCT(req->out);
     217        req->state = SMB2_REQUEST_RECV;
     218
     219        if (num_reqs > 0) {
     220                for (i=0; i < num_reqs; i++) {
     221                        if (reqs[i] != NULL) {
     222                                continue;
     223                        }
     224
     225                        reqs[i] = req->subreq;
     226                        i++;
     227                        break;
     228                }
     229
     230                if (i < num_reqs) {
     231                        return;
     232                }
     233        } else {
     234                reqs = &req->subreq;
     235                num_reqs = 1;
     236        }
     237        status = smb2cli_req_compound_submit(reqs, num_reqs);
     238
     239        TALLOC_FREE(transport->compound.reqs);
     240        transport->compound.related = false;
     241
     242        if (!NT_STATUS_IS_OK(status)) {
    137243                req->status = status;
    138                 DLIST_REMOVE(transport->pending_recv, req);
    139                 if (req->async.fn) {
    140                         req->async.fn(req);
    141                 }
    142         }
    143 }
    144 
    145 static NTSTATUS smb2_handle_oplock_break(struct smb2_transport *transport,
    146                                          const DATA_BLOB *blob)
    147 {
    148         uint8_t *hdr;
     244                req->state = SMB2_REQUEST_ERROR;
     245                smbXcli_conn_disconnect(transport->conn, status);
     246        }
     247}
     248
     249static void smb2_request_done(struct tevent_req *subreq)
     250{
     251        struct smb2_request *req =
     252                tevent_req_callback_data(subreq,
     253                struct smb2_request);
     254        ssize_t len;
     255        size_t i;
     256
     257        req->recv_iov = NULL;
     258
     259        req->status = smb2cli_req_recv(req->subreq, req, &req->recv_iov, NULL, 0);
     260        if (NT_STATUS_EQUAL(req->status, STATUS_PENDING)) {
     261                req->cancel.can_cancel = true;
     262                return;
     263        }
     264        TALLOC_FREE(req->subreq);
     265        if (!NT_STATUS_IS_OK(req->status)) {
     266                if (req->recv_iov == NULL) {
     267                        req->state = SMB2_REQUEST_ERROR;
     268                        if (req->async.fn) {
     269                                req->async.fn(req);
     270                        }
     271                        return;
     272                }
     273        }
     274
     275        len = req->recv_iov[0].iov_len;
     276        for (i=1; i < 3; i++) {
     277                uint8_t *p = req->recv_iov[i-1].iov_base;
     278                uint8_t *c1 = req->recv_iov[i].iov_base;
     279                uint8_t *c2 = p + req->recv_iov[i-1].iov_len;
     280
     281                len += req->recv_iov[i].iov_len;
     282
     283                if (req->recv_iov[i].iov_len == 0) {
     284                        continue;
     285                }
     286
     287                if (c1 != c2) {
     288                        req->status = NT_STATUS_INTERNAL_ERROR;
     289                        req->state = SMB2_REQUEST_ERROR;
     290                        if (req->async.fn) {
     291                                req->async.fn(req);
     292                        }
     293                        return;
     294                }
     295        }
     296
     297        req->in.buffer = req->recv_iov[0].iov_base;
     298        req->in.size = len;
     299        req->in.allocated = req->in.size;
     300
     301        req->in.hdr        =  req->recv_iov[0].iov_base;
     302        req->in.body       =  req->recv_iov[1].iov_base;
     303        req->in.dynamic    =  req->recv_iov[2].iov_base;
     304        req->in.body_fixed =  req->recv_iov[1].iov_len;
     305        req->in.body_size  =  req->in.body_fixed;
     306        req->in.body_size  += req->recv_iov[2].iov_len;
     307
     308        smb2_setup_bufinfo(req);
     309
     310        req->state = SMB2_REQUEST_DONE;
     311        if (req->async.fn) {
     312                req->async.fn(req);
     313        }
     314}
     315
     316static void smb2_transport_break_handler(struct tevent_req *subreq)
     317{
     318        struct smb2_transport *transport =
     319                tevent_req_callback_data(subreq,
     320                struct smb2_transport);
     321        NTSTATUS status;
    149322        uint8_t *body;
    150         uint16_t len, bloblen;
     323        uint16_t len = 0;
    151324        bool lease;
    152 
    153         hdr = blob->data+NBT_HDR_SIZE;
    154         body = hdr+SMB2_HDR_BODY;
    155         bloblen = blob->length - SMB2_HDR_BODY;
    156 
    157         if (bloblen < 2) {
    158                 DEBUG(1,("Discarding smb2 oplock reply of size %u\n",
    159                         (unsigned)blob->length));
    160                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    161         }
    162 
    163         len = CVAL(body, 0x00);
    164         if (len > bloblen) {
    165                 DEBUG(1,("Discarding smb2 oplock reply,"
    166                         "packet claims %u byte body, only %u bytes seen\n",
    167                         len, bloblen));
    168                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     325        struct iovec *recv_iov = NULL;
     326
     327        transport->break_subreq = NULL;
     328
     329        status = smb2cli_req_recv(subreq, transport, &recv_iov, NULL, 0);
     330        TALLOC_FREE(subreq);
     331        if (!NT_STATUS_IS_OK(status)) {
     332                TALLOC_FREE(recv_iov);
     333                smb2_transport_dead(transport, status);
     334                return;
     335        }
     336
     337        /*
     338         * Setup the subreq to handle the
     339         * next incoming SMB2 Break.
     340         */
     341        subreq = smb2cli_req_create(transport,
     342                                    transport->ev,
     343                                    transport->conn,
     344                                    SMB2_OP_BREAK,
     345                                    0, /* additional_flags */
     346                                    0, /*clear_flags */
     347                                    0, /* timeout_msec */
     348                                    NULL, /* tcon */
     349                                    NULL, /* session */
     350                                    NULL, /* body */
     351                                    0, /* body_fixed */
     352                                    NULL, /* dyn */
     353                                    0, /* dyn_len */
     354                                    0); /* max_dyn_len */
     355        if (subreq != NULL) {
     356                smbXcli_req_set_pending(subreq);
     357                tevent_req_set_callback(subreq,
     358                                        smb2_transport_break_handler,
     359                                        transport);
     360                transport->break_subreq = subreq;
     361        }
     362
     363        body = recv_iov[1].iov_base;
     364
     365        len = recv_iov[1].iov_len;
     366        if (recv_iov[1].iov_len >= 2) {
     367                len = CVAL(body, 0x00);
     368                if (len != recv_iov[1].iov_len) {
     369                        len = recv_iov[1].iov_len;
     370                }
    169371        }
    170372
     
    175377        } else {
    176378                DEBUG(1,("Discarding smb2 oplock reply of invalid size %u\n",
    177                         (unsigned)blob->length));
    178                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     379                        (unsigned)len));
     380                TALLOC_FREE(recv_iov);
     381                status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     382                smb2_transport_dead(transport, status);
     383                return;
    179384        }
    180385
     
    185390                level = CVAL(body, 0x02);
    186391                smb2_pull_handle(body+0x08, &h);
     392
     393                TALLOC_FREE(recv_iov);
    187394
    188395                transport->oplock.handler(transport, &h, level,
     
    192399
    193400                ZERO_STRUCT(lb);
     401                lb.new_epoch =                  SVAL(body, 0x2);
    194402                lb.break_flags =                SVAL(body, 0x4);
    195403                memcpy(&lb.current_lease.lease_key, body+0x8,
     
    201409                lb.share_mask_hint =            SVAL(body, 0x28);
    202410
     411                TALLOC_FREE(recv_iov);
     412
    203413                transport->lease.handler(transport, &lb,
    204414                    transport->lease.private_data);
     
    207417                        lease ? "lease" : "oplock"));
    208418        }
    209 
    210         return NT_STATUS_OK;
    211 }
    212 
    213 struct smb2_transport_compount_response_state {
    214         struct smb2_transport *transport;
    215         DATA_BLOB blob;
    216 };
    217 
    218 static void smb2_transport_compound_response_handler(struct tevent_context *ctx,
    219                                                      struct tevent_immediate *im,
    220                                                      void *private_data)
    221 {
    222         struct smb2_transport_compount_response_state *state =
    223                 talloc_get_type_abort(private_data,
    224                 struct smb2_transport_compount_response_state);
    225         struct smb2_transport *transport = state->transport;
    226         NTSTATUS status;
    227 
    228         status = smb2_transport_finish_recv(transport, state->blob);
    229         TALLOC_FREE(state);
    230         if (!NT_STATUS_IS_OK(status)) {
    231                 smb2_transport_error(transport, status);
    232         }
    233 }
    234 
    235 /*
    236   we have a full request in our receive buffer - match it to a pending request
    237   and process
    238  */
    239 static NTSTATUS smb2_transport_finish_recv(void *private_data, DATA_BLOB blob)
    240 {
    241         struct smb2_transport *transport = talloc_get_type(private_data,
    242                                                              struct smb2_transport);
    243         uint8_t *buffer, *hdr;
    244         int len;
    245         struct smb2_request *req = NULL;
    246         uint64_t seqnum;
    247         uint32_t flags;
    248         uint16_t buffer_code;
    249         uint32_t dynamic_size;
    250         uint32_t i;
    251         uint16_t opcode;
    252         NTSTATUS status;
    253         uint32_t next_ofs;
    254 
    255         buffer = blob.data;
    256         len = blob.length;
    257 
    258         hdr = buffer+NBT_HDR_SIZE;
    259 
    260         if (len < SMB2_MIN_SIZE) {
    261                 DEBUG(1,("Discarding smb2 reply of size %d\n", len));
    262                 goto error;
    263         }
    264 
    265         flags   = IVAL(hdr, SMB2_HDR_FLAGS);
    266         seqnum  = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
    267         opcode  = SVAL(hdr, SMB2_HDR_OPCODE);
    268 
    269         /* see MS-SMB2 3.2.5.19 */
    270         if (seqnum == UINT64_MAX) {
    271                 if (opcode != SMB2_OP_BREAK) {
    272                         DEBUG(1,("Discarding packet with invalid seqnum, "
    273                                 "opcode %u\n", opcode));
    274                         return NT_STATUS_INVALID_NETWORK_RESPONSE;
    275                 }
    276 
    277                 return smb2_handle_oplock_break(transport, &blob);
    278         }
    279 
    280         /* match the incoming request against the list of pending requests */
    281         for (req=transport->pending_recv; req; req=req->next) {
    282                 if (req->seqnum == seqnum) break;
    283         }
    284 
    285         if (!req) {
    286                 DEBUG(1,("Discarding unmatched reply with seqnum 0x%llx op %d\n",
    287                          (long long)seqnum, SVAL(hdr, SMB2_HDR_OPCODE)));
    288                 goto error;
    289         }
    290 
    291         /* fill in the 'in' portion of the matching request */
    292         req->in.buffer = buffer;
    293         talloc_steal(req, buffer);
    294         req->in.size = len;
    295         req->in.allocated = req->in.size;
    296 
    297         req->in.hdr       = hdr;
    298         req->in.body      = hdr+SMB2_HDR_BODY;
    299         req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE);
    300         req->status       = NT_STATUS(IVAL(hdr, SMB2_HDR_STATUS));
    301 
    302         if ((flags & SMB2_HDR_FLAG_ASYNC) &&
    303             NT_STATUS_EQUAL(req->status, STATUS_PENDING)) {
    304                 req->cancel.can_cancel = true;
    305                 req->cancel.async_id = BVAL(hdr, SMB2_HDR_ASYNC_ID);
    306                 for (i=0; i< req->cancel.do_cancel; i++) {
    307                         smb2_cancel(req);
    308                 }
    309                 talloc_free(buffer);
    310                 return NT_STATUS_OK;
    311         }
    312 
    313         next_ofs = IVAL(req->in.hdr, SMB2_HDR_NEXT_COMMAND);
    314         if (next_ofs > 0) {
    315                 if (smb2_oob(&req->in, req->in.hdr + next_ofs, SMB2_HDR_BODY + 2)) {
    316                         DEBUG(1,("SMB2 request invalid next offset 0x%x\n",
    317                                  next_ofs));
    318                         goto error;
    319                 }
    320 
    321                 req->in.size = NBT_HDR_SIZE + next_ofs;
    322                 req->in.body_size = req->in.size - (SMB2_HDR_BODY+NBT_HDR_SIZE);
    323         }
    324 
    325         if (req->session && req->session->signing_active) {
    326                 status = smb2_check_signature(&req->in,
    327                                               req->session->session_key);
    328                 if (!NT_STATUS_IS_OK(status)) {
    329                         /* the spec says to ignore packets with a bad signature */
    330                         talloc_free(buffer);
    331                         return status;
    332                 }
    333         }
    334 
    335         buffer_code = SVAL(req->in.body, 0);
    336         req->in.body_fixed = (buffer_code & ~1);
    337         req->in.dynamic = NULL;
    338         dynamic_size = req->in.body_size - req->in.body_fixed;
    339         if (dynamic_size != 0 && (buffer_code & 1)) {
    340                 req->in.dynamic = req->in.body + req->in.body_fixed;
    341                 if (smb2_oob(&req->in, req->in.dynamic, dynamic_size)) {
    342                         DEBUG(1,("SMB2 request invalid dynamic size 0x%x\n",
    343                                  dynamic_size));
    344                         goto error;
    345                 }
    346         }
    347 
    348         smb2_setup_bufinfo(req);
    349 
    350         DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", (long long)req->seqnum));
    351         dump_data(5, req->in.body, req->in.body_size);
    352 
    353         if (next_ofs > 0) {
    354                 struct tevent_immediate *im;
    355                 struct smb2_transport_compount_response_state *state;
    356 
    357                 state = talloc(transport,
    358                                struct smb2_transport_compount_response_state);
    359                 if (!state) {
    360                         goto error;
    361                 }
    362                 state->transport = transport;
    363 
    364                 state->blob = data_blob_talloc(state, NULL,
    365                                                blob.length - next_ofs);
    366                 if (!state->blob.data) {
    367                         goto error;
    368                 }
    369                 im = tevent_create_immediate(state);
    370                 if (!im) {
    371                         TALLOC_FREE(state);
    372                         goto error;
    373                 }
    374                 _smb2_setlen(state->blob.data, state->blob.length - NBT_HDR_SIZE);
    375                 memcpy(state->blob.data + NBT_HDR_SIZE,
    376                        req->in.hdr + next_ofs,
    377                        req->in.allocated - req->in.size);
    378                 tevent_schedule_immediate(im, transport->socket->event.ctx,
    379                                           smb2_transport_compound_response_handler,
    380                                           state);
    381         }
    382 
    383         /* if this request has an async handler then call that to
    384            notify that the reply has been received. This might destroy
    385            the request so it must happen last */
    386         DLIST_REMOVE(transport->pending_recv, req);
    387         req->state = SMB2_REQUEST_DONE;
    388         if (req->async.fn) {
    389                 req->async.fn(req);
    390         }
    391         return NT_STATUS_OK;
    392 
    393 error:
    394         dump_data(5, buffer, len);
    395         if (req) {
    396                 DLIST_REMOVE(transport->pending_recv, req);
    397                 req->state = SMB2_REQUEST_ERROR;
    398                 if (req->async.fn) {
    399                         req->async.fn(req);
    400                 }
    401         } else {
    402                 talloc_free(buffer);
    403         }
    404         return NT_STATUS_UNSUCCESSFUL;
    405 }
    406 
    407 /*
    408   handle timeouts of individual smb requests
    409 */
    410 static void smb2_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
    411                                  struct timeval t, void *private_data)
    412 {
    413         struct smb2_request *req = talloc_get_type(private_data, struct smb2_request);
    414 
    415         if (req->state == SMB2_REQUEST_RECV) {
    416                 DLIST_REMOVE(req->transport->pending_recv, req);
    417         }
    418         req->status = NT_STATUS_IO_TIMEOUT;
    419         req->state = SMB2_REQUEST_ERROR;
    420         if (req->async.fn) {
    421                 req->async.fn(req);
    422         }
    423 }
    424 
    425 
    426 /*
    427   destroy a request
    428 */
    429 static int smb2_request_destructor(struct smb2_request *req)
    430 {
    431         if (req->state == SMB2_REQUEST_RECV) {
    432                 DLIST_REMOVE(req->transport->pending_recv, req);
    433         }
    434         return 0;
    435 }
    436 
    437 static NTSTATUS smb2_transport_raw_send(struct smb2_transport *transport,
    438                                         struct smb2_request_buffer *buffer)
    439 {
    440         DATA_BLOB blob;
    441         NTSTATUS status;
    442 
    443         /* check if the transport is dead */
    444         if (transport->socket->sock == NULL) {
    445                 return NT_STATUS_NET_WRITE_FAULT;
    446         }
    447 
    448         _smb2_setlen(buffer->buffer, buffer->size - NBT_HDR_SIZE);
    449         blob = data_blob_const(buffer->buffer, buffer->size);
    450         status = packet_send(transport->packet, blob);
    451         if (!NT_STATUS_IS_OK(status)) {
    452                 return status;
    453         }
    454 
    455         return NT_STATUS_OK;
    456 }
    457 
    458 /*
    459   put a request into the send queue
    460 */
    461 void smb2_transport_send(struct smb2_request *req)
    462 {
    463         NTSTATUS status;
    464 
    465         DEBUG(2, ("SMB2 send seqnum=0x%llx\n", (long long)req->seqnum));
    466         dump_data(5, req->out.body, req->out.body_size);
    467 
    468         if (req->transport->compound.missing > 0) {
    469                 off_t next_ofs;
    470                 size_t pad = 0;
    471                 uint8_t *end;
    472 
    473                 end = req->out.buffer + req->out.size;
    474 
    475                 /*
    476                  * we need to set dynamic otherwise
    477                  * smb2_grow_buffer segfaults
    478                  */
    479                 if (req->out.dynamic == NULL) {
    480                         req->out.dynamic = end;
    481                 }
    482 
    483                 next_ofs = end - req->out.hdr;
    484                 if ((next_ofs % 8) > 0) {
    485                         pad = 8 - (next_ofs % 8);
    486                 }
    487                 next_ofs += pad;
    488 
    489                 status = smb2_grow_buffer(&req->out, pad);
    490                 if (!NT_STATUS_IS_OK(status)) {
    491                         req->state = SMB2_REQUEST_ERROR;
    492                         req->status = status;
    493                         return;
    494                 }
    495                 req->out.size += pad;
    496 
    497                 SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND, next_ofs);
    498         }
    499 
    500         /* possibly sign the message */
    501         if (req->session && req->session->signing_active) {
    502                 status = smb2_sign_message(&req->out, req->session->session_key);
    503                 if (!NT_STATUS_IS_OK(status)) {
    504                         req->state = SMB2_REQUEST_ERROR;
    505                         req->status = status;
    506                         return;
    507                 }
    508         }
    509 
    510         if (req->transport->compound.missing > 0) {
    511                 req->transport->compound.buffer = req->out;
    512         } else {
    513                 status = smb2_transport_raw_send(req->transport,
    514                                                  &req->out);
    515                 if (!NT_STATUS_IS_OK(status)) {
    516                         req->state = SMB2_REQUEST_ERROR;
    517                         req->status = status;
    518                         return;
    519                 }
    520         }
    521         ZERO_STRUCT(req->out);
    522 
    523         req->state = SMB2_REQUEST_RECV;
    524         DLIST_ADD(req->transport->pending_recv, req);
    525 
    526         /* add a timeout */
    527         if (req->transport->options.request_timeout) {
    528                 event_add_timed(req->transport->socket->event.ctx, req,
    529                                 timeval_current_ofs(req->transport->options.request_timeout, 0),
    530                                 smb2_timeout_handler, req);
    531         }
    532 
    533         talloc_set_destructor(req, smb2_request_destructor);
     419        TALLOC_FREE(recv_iov);
    534420}
    535421
     
    537423                                       uint32_t num)
    538424{
     425        TALLOC_FREE(transport->compound.reqs);
    539426        ZERO_STRUCT(transport->compound);
    540         transport->compound.missing = num;
     427
     428        transport->compound.reqs = talloc_zero_array(transport,
     429                                                     struct tevent_req *,
     430                                                     num);
     431        if (transport->compound.reqs == NULL) {
     432                return NT_STATUS_NO_MEMORY;
     433        }
     434
    541435        return NT_STATUS_OK;
    542436}
     
    551445                                    uint16_t ask_num)
    552446{
    553         transport->credits.ask_num = ask_num;
    554 }
    555 
    556 void smb2_transport_credits_set_charge(struct smb2_transport *transport,
    557                                        uint16_t charge)
    558 {
    559         transport->credits.charge = charge;
     447        smb2cli_conn_set_max_credits(transport->conn, ask_num);
    560448}
    561449
     
    565453        struct smb2_transport *transport = talloc_get_type(private_data,
    566454                                                           struct smb2_transport);
    567         struct timeval next = timeval_add(&t, 0, transport->idle.period);
    568         transport->socket->event.te = event_add_timed(transport->socket->event.ctx,
    569                                                       transport,
    570                                                       next,
    571                                                       idle_handler, transport);
     455        struct timeval next;
     456
    572457        transport->idle.func(transport, transport->idle.private_data);
     458
     459        next = timeval_current_ofs_usec(transport->idle.period);
     460        transport->idle.te = tevent_add_timer(transport->ev,
     461                                              transport,
     462                                              next,
     463                                              idle_handler,
     464                                              transport);
    573465}
    574466
     
    582474                                 void *private_data)
    583475{
     476        TALLOC_FREE(transport->idle.te);
     477
    584478        transport->idle.func = idle_func;
    585479        transport->idle.private_data = private_data;
    586480        transport->idle.period = period;
    587481
    588         if (transport->socket->event.te != NULL) {
    589                 talloc_free(transport->socket->event.te);
    590         }
    591 
    592         transport->socket->event.te = event_add_timed(transport->socket->event.ctx,
    593                                                       transport,
    594                                                       timeval_current_ofs(0, period),
    595                                                       idle_handler, transport);
    596 }
     482        transport->idle.te = tevent_add_timer(transport->ev,
     483                                              transport,
     484                                              timeval_current_ofs_usec(period),
     485                                              idle_handler,
     486                                              transport);
     487}
  • vendor/current/source4/libcli/smb2/util.c

    r740 r988  
    231231        return (h1.data[0] == h2.data[0]) && (h1.data[1] == h2.data[1]);
    232232}
     233
     234bool smb2_util_handle_empty(const struct smb2_handle h)
     235{
     236        struct smb2_handle empty;
     237
     238        ZERO_STRUCT(empty);
     239
     240        return smb2_util_handle_equal(h, empty);
     241}
  • vendor/current/source4/libcli/smb2/write.c

    r414 r988  
    5959{
    6060        if (!smb2_request_receive(req) ||
    61             smb2_request_is_error(req)) {
     61            !smb2_request_is_ok(req)) {
    6262                return smb2_request_destroy(req);
    6363        }
  • vendor/current/source4/libcli/smb2/wscript_build

    r740 r988  
    22
    33bld.SAMBA_SUBSYSTEM('LIBCLI_SMB2',
    4         source='transport.c request.c negprot.c session.c tcon.c create.c close.c connect.c getinfo.c write.c read.c setinfo.c find.c ioctl.c logoff.c tdis.c flush.c lock.c notify.c cancel.c keepalive.c break.c util.c signing.c lease_break.c',
     4        source='transport.c request.c session.c tcon.c create.c close.c connect.c getinfo.c write.c read.c setinfo.c find.c ioctl.c logoff.c tdis.c flush.c lock.c notify.c cancel.c keepalive.c break.c util.c signing.c lease_break.c',
    55        autoproto='smb2_proto.h',
    6         public_deps='LIBCLI_RAW LIBPACKET gensec'
     6        deps='tevent-util cli_smb_common',
     7        public_deps='smbclient-raw gensec samba-credentials tevent',
     8        private_headers='smb2.h',
    79        )
    810
Note: See TracChangeset for help on using the changeset viewer.