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

Samba Server: update vendor to 3.6.0

Location:
vendor/current/source3/libsmb
Files:
10 added
3 deleted
53 edited

Legend:

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

    r594 r740  
    1919
    2020#include "includes.h"
     21#include "libsmb/libsmb.h"
     22#include "../lib/async_req/async_sock.h"
     23#include "../lib/util/tevent_ntstatus.h"
     24#include "../lib/util/tevent_unix.h"
     25#include "async_smb.h"
     26#include "smb_crypt.h"
     27#include "libsmb/nmblib.h"
    2128
    2229/*
     
    121128        }
    122129
    123         /* if the client uses dos errors, but there is no error,
    124            we should return no error here, otherwise it looks
    125            like an unknown bad NT_STATUS. jmcd */
    126         if (CVAL(buf, smb_rcls) == 0)
    127                 return NT_STATUS_OK;
    128 
    129         return NT_STATUS_DOS(CVAL(buf, smb_rcls), SVAL(buf,smb_err));
     130        return dos_to_ntstatus(CVAL(buf, smb_rcls), SVAL(buf,smb_err));
    130131}
    131132
     
    202203        uint32_t seqnum;
    203204        int chain_num;
     205        int chain_length;
    204206        struct tevent_req **chained_requests;
    205207};
     
    237239        int num_pending = talloc_array_length(cli->pending);
    238240        int i;
     241
     242        if (state->mid != 0) {
     243                /*
     244                 * This is a [nt]trans[2] request which waits
     245                 * for more than one reply.
     246                 */
     247                return;
     248        }
    239249
    240250        if (num_pending == 1) {
     
    280290static int cli_smb_req_destructor(struct tevent_req *req)
    281291{
     292        struct cli_smb_state *state = tevent_req_data(
     293                req, struct cli_smb_state);
     294        /*
     295         * Make sure we really remove it from
     296         * the pending array on destruction.
     297         */
     298        state->mid = 0;
    282299        cli_smb_req_unset_pending(req);
    283300        return 0;
     
    342359}
    343360
     361uint32_t cli_smb_req_seqnum(struct tevent_req *req)
     362{
     363        struct cli_smb_state *state = tevent_req_data(
     364                req, struct cli_smb_state);
     365        return state->seqnum;
     366}
     367
     368void cli_smb_req_set_seqnum(struct tevent_req *req, uint32_t seqnum)
     369{
     370        struct cli_smb_state *state = tevent_req_data(
     371                req, struct cli_smb_state);
     372        state->seqnum = seqnum;
     373}
     374
    344375static size_t iov_len(const struct iovec *iov, int count)
    345376{
     
    424455        state->iov_count = iov_count + 3;
    425456
    426         endtime = timeval_current_ofs(0, cli->timeout * 1000);
    427         if (!tevent_req_set_endtime(result, ev, endtime)) {
    428                 tevent_req_nomem(NULL, result);
     457        if (cli->timeout) {
     458                endtime = timeval_current_ofs(cli->timeout / 1000,
     459                                              (cli->timeout % 1000) * 1000);
     460                if (!tevent_req_set_endtime(result, ev, endtime)) {
     461                        tevent_req_nomem(NULL, result);
     462                }
    429463        }
    430464        return result;
     
    610644        struct tevent_req *req;
    611645        struct cli_smb_state *state;
    612         struct tevent_context *ev;
    613646        NTSTATUS status;
    614647        uint8_t *inbuf;
     
    699732        req = cli->pending[i];
    700733        state = tevent_req_data(req, struct cli_smb_state);
    701         ev = state->ev;
    702734
    703735        if (!oplock_break /* oplock breaks are not signed */
     
    714746                state->inbuf = talloc_move(state, &inbuf);
    715747                talloc_set_destructor(req, NULL);
    716                 cli_smb_req_destructor(req);
     748                cli_smb_req_unset_pending(req);
     749                state->chain_num = 0;
     750                state->chain_length = 1;
    717751                tevent_req_done(req);
    718752        } else {
     
    726760                        state->inbuf = inbuf;
    727761                        state->chain_num = i;
     762                        state->chain_length = num_chained;
    728763                        tevent_req_done(chain[i]);
    729764                }
     
    755790                req = cli->pending[0];
    756791                talloc_set_destructor(req, NULL);
    757                 cli_smb_req_destructor(req);
     792                cli_smb_req_unset_pending(req);
    758793                tevent_req_nterror(req, status);
    759794        }
    760795}
    761796
    762 NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct,
    763                       uint8_t *pwct, uint16_t **pvwv,
     797NTSTATUS cli_smb_recv(struct tevent_req *req,
     798                      TALLOC_CTX *mem_ctx, uint8_t **pinbuf,
     799                      uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv,
    764800                      uint32_t *pnum_bytes, uint8_t **pbytes)
    765801{
     
    777813
    778814        if (state->inbuf == NULL) {
     815                if (min_wct != 0) {
     816                        return NT_STATUS_INVALID_NETWORK_RESPONSE;
     817                }
     818                if (pinbuf) {
     819                        *pinbuf = NULL;
     820                }
     821                if (pwct) {
     822                        *pwct = 0;
     823                }
     824                if (pvwv) {
     825                        *pvwv = NULL;
     826                }
     827                if (pnum_bytes) {
     828                        *pnum_bytes = 0;
     829                }
     830                if (pbytes) {
     831                        *pbytes = NULL;
     832                }
    779833                /* This was a request without a reply */
    780834                return NT_STATUS_OK;
     
    819873        status = cli_pull_error((char *)state->inbuf);
    820874
    821         if (!have_andx_command((char *)state->inbuf, wct_ofs)
    822             && NT_STATUS_IS_ERR(status)) {
    823                 /*
    824                  * The last command takes the error code. All further commands
    825                  * down the requested chain will get a
    826                  * NT_STATUS_REQUEST_ABORTED.
    827                  */
    828                 return status;
    829         }
     875        if (!have_andx_command((char *)state->inbuf, wct_ofs)) {
     876
     877                if ((cmd == SMBsesssetupX)
     878                    && NT_STATUS_EQUAL(
     879                            status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     880                        /*
     881                         * NT_STATUS_MORE_PROCESSING_REQUIRED is a
     882                         * valid return code for session setup
     883                         */
     884                        goto no_err;
     885                }
     886
     887                if (NT_STATUS_IS_ERR(status)) {
     888                        /*
     889                         * The last command takes the error code. All
     890                         * further commands down the requested chain
     891                         * will get a NT_STATUS_REQUEST_ABORTED.
     892                         */
     893                        return status;
     894                }
     895        }
     896
     897no_err:
    830898
    831899        wct = CVAL(state->inbuf, wct_ofs);
     
    859927                *pbytes = (uint8_t *)state->inbuf + bytes_offset + 2;
    860928        }
    861 
    862         return NT_STATUS_OK;
     929        if ((mem_ctx != NULL) && (pinbuf != NULL)) {
     930                if (state->chain_num == state->chain_length-1) {
     931                        *pinbuf = talloc_move(mem_ctx, &state->inbuf);
     932                } else {
     933                        *pinbuf = state->inbuf;
     934                }
     935        }
     936
     937        return status;
    863938}
    864939
     
    10441119        uint32_t num_bytes;
    10451120        uint8_t *bytes;
     1121        uint8_t *inbuf;
    10461122        NTSTATUS status;
    10471123
    1048         status = cli_smb_recv(subreq, 8, &wct, &vwv, &num_bytes, &bytes);
     1124        status = cli_smb_recv(subreq, state, &inbuf, 8, &wct, &vwv,
     1125                              &num_bytes, &bytes);
     1126        TALLOC_FREE(subreq);
    10491127        if (!NT_STATUS_IS_OK(status)) {
    1050                 TALLOC_FREE(subreq);
    10511128                tevent_req_nterror(req, status);
    10521129                return;
  • vendor/current/source3/libsmb/cliconnect.c

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

    r597 r740  
    2121
    2222#include "includes.h"
     23#include "libsmb/libsmb.h"
     24#include "libsmb/clirap.h"
     25#include "msdfs.h"
     26#include "trans2.h"
     27#include "libsmb/nmblib.h"
    2328
    2429/********************************************************************
     
    128133
    129134        /* have to open a new connection */
    130         if (!(c=cli_initialise_ex(get_cmdline_auth_info_signing_state(auth_info)))) {
     135        c = cli_initialise_ex(get_cmdline_auth_info_signing_state(auth_info));
     136        if (c == NULL) {
    131137                d_printf("Connection to %s failed\n", server_n);
    132                 if (c) {
    133                         cli_shutdown(c);
    134                 }
    135138                return NULL;
    136139        }
     
    321324        }
    322325
    323         if (referring_cli && referring_cli->posix_capabilities) {
     326        if (referring_cli && referring_cli->requested_posix_capabilities) {
    324327                uint16 major, minor;
    325328                uint32 caplow, caphigh;
     
    352355
    353356        /* Search to the start of the list. */
    354         for (p = cli; p; p = p->prev) {
     357        for (p = cli; p; p = DLIST_PREV(p)) {
    355358                if (strequal(server, p->desthost) &&
    356359                                strequal(share,p->share)) {
     
    453456**********************************************************************/
    454457
    455 static void split_dfs_path(TALLOC_CTX *ctx,
     458static bool split_dfs_path(TALLOC_CTX *ctx,
    456459                                const char *nodepath,
    457460                                char **pp_server,
     
    468471        path = talloc_strdup(ctx, nodepath);
    469472        if (!path) {
    470                 return;
     473                goto fail;
    471474        }
    472475
    473476        if ( path[0] != '\\' ) {
    474                 return;
     477                goto fail;
    475478        }
    476479
    477480        p = strchr_m( path + 1, '\\' );
    478481        if ( !p ) {
    479                 return;
     482                goto fail;
    480483        }
    481484
     
    492495                *pp_extrapath = talloc_strdup(ctx, "");
    493496        }
     497        if (*pp_extrapath == NULL) {
     498                goto fail;
     499        }
    494500
    495501        *pp_share = talloc_strdup(ctx, p);
     502        if (*pp_share == NULL) {
     503                goto fail;
     504        }
     505
    496506        *pp_server = talloc_strdup(ctx, &path[1]);
     507        if (*pp_server == NULL) {
     508                goto fail;
     509        }
     510
     511        TALLOC_FREE(path);
     512        return true;
     513
     514fail:
     515        TALLOC_FREE(*pp_share);
     516        TALLOC_FREE(*pp_extrapath);
     517        TALLOC_FREE(path);
     518        return false;
    497519}
    498520
     
    565587        }
    566588
    567         if (cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
     589        if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
    568590                path_sep = '/';
    569591        }
     
    581603********************************************************************/
    582604
    583 static bool cli_dfs_check_error( struct cli_state *cli, NTSTATUS status )
    584 {
    585         uint32 flgs2 = SVAL(cli->inbuf,smb_flg2);
    586 
     605static bool cli_dfs_check_error(struct cli_state *cli, NTSTATUS expected,
     606                                NTSTATUS status)
     607{
    587608        /* only deal with DS when we negotiated NT_STATUS codes and UNICODE */
    588609
    589         if (!((flgs2&FLAGS2_32_BIT_ERROR_CODES) &&
    590                                 (flgs2&FLAGS2_UNICODE_STRINGS)))
    591                 return false;
    592 
    593         if (NT_STATUS_EQUAL(status, NT_STATUS(IVAL(cli->inbuf,smb_rcls))))
     610        if (!(cli->capabilities & CAP_UNICODE)) {
     611                return false;
     612        }
     613        if (!(cli->capabilities & CAP_STATUS32)) {
     614                return false;
     615        }
     616        if (NT_STATUS_EQUAL(status, expected)) {
    594617                return true;
    595 
     618        }
    596619        return false;
    597620}
     
    601624********************************************************************/
    602625
    603 bool cli_dfs_get_referral(TALLOC_CTX *ctx,
     626NTSTATUS cli_dfs_get_referral(TALLOC_CTX *ctx,
    604627                        struct cli_state *cli,
    605628                        const char *path,
    606                         CLIENT_DFS_REFERRAL**refs,
     629                        struct client_dfs_referral **refs,
    607630                        size_t *num_refs,
    608631                        size_t *consumed)
     
    610633        unsigned int data_len = 0;
    611634        unsigned int param_len = 0;
    612         uint16 setup = TRANSACT2_GET_DFS_REFERRAL;
    613         char *param = NULL;
    614         char *rparam=NULL, *rdata=NULL;
     635        uint16 setup[1];
     636        uint8_t *param = NULL;
     637        uint8_t *rdata = NULL;
    615638        char *p;
    616639        char *endp;
     
    620643        uint16_t consumed_ucs;
    621644        uint16 num_referrals;
    622         CLIENT_DFS_REFERRAL *referrals = NULL;
    623         bool ret = false;
     645        struct client_dfs_referral *referrals = NULL;
     646        NTSTATUS status;
    624647
    625648        *num_refs = 0;
    626649        *refs = NULL;
    627650
    628         param = SMB_MALLOC_ARRAY(char, 2+pathlen+2);
     651        SSVAL(setup, 0, TRANSACT2_GET_DFS_REFERRAL);
     652
     653        param = SMB_MALLOC_ARRAY(uint8_t, 2+pathlen+2);
    629654        if (!param) {
     655                status = NT_STATUS_NO_MEMORY;
    630656                goto out;
    631657        }
    632658        SSVAL(param, 0, 0x03);  /* max referral level */
    633         p = &param[2];
     659        p = (char *)(&param[2]);
    634660
    635661        path_ucs = (smb_ucs2_t *)p;
     
    637663        param_len = PTR_DIFF(p, param);
    638664
    639         if (!cli_send_trans(cli, SMBtrans2,
    640                         NULL,                        /* name */
    641                         -1, 0,                          /* fid, flags */
    642                         &setup, 1, 0,                   /* setup, length, max */
    643                         param, param_len, 2,            /* param, length, max */
    644                         NULL, 0, cli->max_xmit /* data, length, max */
    645                         )) {
     665        status = cli_trans(talloc_tos(), cli, SMBtrans2,
     666                           NULL, 0xffff, 0, 0,
     667                           setup, 1, 0,
     668                           param, param_len, 2,
     669                           NULL, 0, cli->max_xmit,
     670                           NULL,
     671                           NULL, 0, NULL, /* rsetup */
     672                           NULL, 0, NULL,
     673                           &rdata, 4, &data_len);
     674        if (!NT_STATUS_IS_OK(status)) {
    646675                goto out;
    647676        }
    648 
    649         if (!cli_receive_trans(cli, SMBtrans2,
    650                 &rparam, &param_len,
    651                 &rdata, &data_len)) {
    652                 goto out;
    653         }
    654 
    655677        if (data_len < 4) {
    656678                goto out;
    657679        }
    658680
    659         endp = rdata + data_len;
     681        endp = (char *)rdata + data_len;
    660682
    661683        consumed_ucs  = SVAL(rdata, 0);
     
    689711                uint16 node_offset;
    690712
    691                 referrals = TALLOC_ARRAY(ctx, CLIENT_DFS_REFERRAL,
    692                                 num_referrals);
     713                referrals = talloc_array(ctx, struct client_dfs_referral,
     714                                         num_referrals);
    693715
    694716                if (!referrals) {
     
    697719                /* start at the referrals array */
    698720
    699                 p = rdata+8;
     721                p = (char *)rdata+8;
    700722                for (i=0; i<num_referrals && p < endp; i++) {
    701723                        if (p + 18 > endp) {
     
    718740                        }
    719741                        clistr_pull_talloc(ctx, cli->inbuf,
     742                                           SVAL(cli->inbuf, smb_flg2),
    720743                                           &referrals[i].dfspath,
    721744                                           p+node_offset, -1,
     
    732755        }
    733756
    734         ret = true;
    735 
    736757        *num_refs = num_referrals;
    737758        *refs = referrals;
     
    741762        TALLOC_FREE(consumed_path);
    742763        SAFE_FREE(param);
    743         SAFE_FREE(rdata);
    744         SAFE_FREE(rparam);
    745         return ret;
     764        TALLOC_FREE(rdata);
     765        return status;
    746766}
    747767
     
    757777                        char **pp_targetpath)
    758778{
    759         CLIENT_DFS_REFERRAL *refs = NULL;
     779        struct client_dfs_referral *refs = NULL;
    760780        size_t num_refs = 0;
    761781        size_t consumed = 0;
     
    773793        SMB_STRUCT_STAT sbuf;
    774794        uint32 attributes;
     795        NTSTATUS status;
    775796
    776797        if ( !rootcli || !path || !targetcli ) {
     
    803824        }
    804825
    805         if (cli_qpathinfo_basic( rootcli, dfs_path, &sbuf, &attributes)) {
     826        status = cli_qpathinfo_basic( rootcli, dfs_path, &sbuf, &attributes);
     827        if (NT_STATUS_IS_OK(status)) {
    806828                /* This is an ordinary path, just return it. */
    807829                *targetcli = rootcli;
     
    815837        /* Special case where client asked for a path that does not exist */
    816838
    817         if (cli_dfs_check_error(rootcli, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     839        if (cli_dfs_check_error(rootcli, NT_STATUS_OBJECT_NAME_NOT_FOUND,
     840                                status)) {
    818841                *targetcli = rootcli;
    819842                *pp_targetpath = talloc_strdup(ctx, path);
     
    826849        /* We got an error, check for DFS referral. */
    827850
    828         if (!cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED)) {
     851        if (!cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED,
     852                                 status)) {
    829853                return false;
    830854        }
     
    845869        }
    846870
    847         if (!cli_dfs_get_referral(ctx, cli_ipc, dfs_path, &refs,
    848                         &num_refs, &consumed) || !num_refs) {
     871        status = cli_dfs_get_referral(ctx, cli_ipc, dfs_path, &refs,
     872                                      &num_refs, &consumed);
     873        if (!NT_STATUS_IS_OK(status) || !num_refs) {
    849874                return false;
    850875        }
     
    855880                return false;
    856881        }
    857         split_dfs_path(ctx, refs[0].dfspath, &server, &share, &extrapath );
    858 
    859         if (!server || !share) {
     882        if (!split_dfs_path(ctx, refs[0].dfspath, &server, &share,
     883                            &extrapath)) {
    860884                return false;
    861885        }
     
    9971021                                const char *domain)
    9981022{
    999         CLIENT_DFS_REFERRAL *refs = NULL;
     1023        struct client_dfs_referral *refs = NULL;
    10001024        size_t num_refs = 0;
    10011025        size_t consumed = 0;
     
    10041028        uint16 cnum;
    10051029        char *newextrapath = NULL;
     1030        NTSTATUS status;
    10061031
    10071032        if (!cli || !sharename) {
     
    10311056
    10321057        if (force_encrypt) {
    1033                 NTSTATUS status = cli_cm_force_encryption(cli,
     1058                status = cli_cm_force_encryption(cli,
    10341059                                        username,
    10351060                                        password,
     
    10411066        }
    10421067
    1043         res = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed);
    1044 
    1045         if (!cli_tdis(cli)) {
     1068        status = cli_dfs_get_referral(ctx, cli, fullpath, &refs,
     1069                                      &num_refs, &consumed);
     1070        res = NT_STATUS_IS_OK(status);
     1071
     1072        status = cli_tdis(cli);
     1073        if (!NT_STATUS_IS_OK(status)) {
    10461074                return false;
    10471075        }
     
    10571085        }
    10581086
    1059         split_dfs_path(ctx, refs[0].dfspath, pp_newserver,
    1060                         pp_newshare, &newextrapath );
    1061 
    1062         if ((*pp_newserver == NULL) || (*pp_newshare == NULL)) {
     1087        if (!split_dfs_path(ctx, refs[0].dfspath, pp_newserver,
     1088                            pp_newshare, &newextrapath)) {
    10631089                return false;
    10641090        }
  • vendor/current/source3/libsmb/clidgram.c

    r594 r740  
    1010   the Free Software Foundation; either version 3 of the License, or
    1111   (at your option) any later version.
    12    
     12
    1313   This program is distributed in the hope that it will be useful,
    1414   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1515   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1616   GNU General Public License for more details.
    17    
     17
    1818   You should have received a copy of the GNU General Public License
    1919   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2121
    2222#include "includes.h"
     23#include "libsmb/libsmb.h"
     24#include "../lib/util/tevent_ntstatus.h"
     25#include "libsmb/clidgram.h"
     26#include "libsmb/nmblib.h"
     27#include "messages.h"
    2328
    2429/*
     
    2631 */
    2732
    28 static bool cli_send_mailslot(struct messaging_context *msg_ctx,
    29                        bool unique, const char *mailslot,
     33static bool cli_prep_mailslot(bool unique, const char *mailslot,
    3034                       uint16 priority,
    3135                       char *buf, int len,
    3236                       const char *srcname, int src_type,
    3337                       const char *dstname, int dest_type,
    34                        const struct sockaddr_storage *dest_ss)
    35 {
    36         struct packet_struct p;
    37         struct dgram_packet *dgram = &p.packet.dgram;
     38                       const struct sockaddr_storage *dest_ss,
     39                       int dgm_id,
     40                       struct packet_struct *p)
     41{
     42        struct dgram_packet *dgram = &p->packet.dgram;
    3843        char *ptr, *p2;
    3944        char tmp[4];
    40         pid_t nmbd_pid;
    4145        char addr[INET6_ADDRSTRLEN];
    4246
    43         if ((nmbd_pid = pidfile_pid("nmbd")) == 0) {
    44                 DEBUG(3, ("No nmbd found\n"));
    45                 return False;
    46         }
    47 
    48         if (dest_ss->ss_family != AF_INET) {
    49                 DEBUG(3, ("cli_send_mailslot: can't send to IPv6 address.\n"));
    50                 return false;
    51         }
    52 
    53         memset((char *)&p, '\0', sizeof(p));
     47        ZERO_STRUCTP(p);
    5448
    5549        /*
     
    6256        dgram->header.flags.first = True;
    6357        dgram->header.flags.more = False;
    64         dgram->header.dgm_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) +
    65                 ((unsigned)sys_getpid()%(unsigned)100);
     58        dgram->header.dgm_id = dgm_id;
    6659        /* source ip is filled by nmbd */
    6760        dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
     
    10598        dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
    10699
    107         p.packet_type = DGRAM_PACKET;
    108         p.ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;
    109         p.timestamp = time(NULL);
     100        p->packet_type = DGRAM_PACKET;
     101        p->ip = ((const struct sockaddr_in *)dest_ss)->sin_addr;
     102        p->timestamp = time(NULL);
    110103
    111104        DEBUG(4,("send_mailslot: Sending to mailslot %s from %s ",
     
    115108        DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), addr));
    116109
    117         return NT_STATUS_IS_OK(messaging_send_buf(msg_ctx,
    118                                                   pid_to_procid(nmbd_pid),
    119                                                   MSG_SEND_PACKET,
    120                                                   (uint8 *)&p, sizeof(p)));
    121 }
    122 
    123 static const char *mailslot_name(TALLOC_CTX *mem_ctx, struct in_addr dc_ip)
     110        return true;
     111}
     112
     113static char *mailslot_name(TALLOC_CTX *mem_ctx, struct in_addr dc_ip)
    124114{
    125115        return talloc_asprintf(mem_ctx, "%s%X",
     
    127117}
    128118
    129 bool send_getdc_request(TALLOC_CTX *mem_ctx,
    130                         struct messaging_context *msg_ctx,
    131                         struct sockaddr_storage *dc_ss,
    132                         const char *domain_name,
    133                         const DOM_SID *sid,
    134                         uint32_t nt_version)
    135 {
    136         struct in_addr dc_ip;
    137         const char *my_acct_name = NULL;
    138         const char *my_mailslot = NULL;
     119static bool prep_getdc_request(const struct sockaddr_storage *dc_ss,
     120                               const char *domain_name,
     121                               const struct dom_sid *sid,
     122                               uint32_t nt_version,
     123                               const char *my_mailslot,
     124                               int dgm_id,
     125                               struct packet_struct *p)
     126{
     127        TALLOC_CTX *frame = talloc_stackframe();
     128        const char *my_acct_name;
    139129        struct nbt_netlogon_packet packet;
    140130        struct NETLOGON_SAM_LOGON_REQUEST *s;
    141131        enum ndr_err_code ndr_err;
    142         DATA_BLOB blob;
     132        DATA_BLOB blob = data_blob_null;
    143133        struct dom_sid my_sid;
     134        bool ret = false;
    144135
    145136        ZERO_STRUCT(packet);
    146137        ZERO_STRUCT(my_sid);
    147138
    148         if (dc_ss->ss_family != AF_INET) {
    149                 return false;
    150         }
    151 
    152         if (sid) {
     139        if (sid != NULL) {
    153140                my_sid = *sid;
    154141        }
    155142
    156         dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
    157         my_mailslot = mailslot_name(mem_ctx, dc_ip);
    158         if (!my_mailslot) {
    159                 return false;
    160         }
    161 
    162         my_acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname());
    163         if (!my_acct_name) {
    164                 return false;
     143        my_acct_name = talloc_asprintf(talloc_tos(), "%s$", global_myname());
     144        if (my_acct_name == NULL) {
     145                goto fail;
    165146        }
    166147
     
    182163        }
    183164
    184         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &packet,
     165        ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &packet,
    185166                       (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_packet);
    186167        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    187                 return false;
    188         }
    189 
    190         return cli_send_mailslot(msg_ctx,
    191                                  false, NBT_MAILSLOT_NTLOGON, 0,
    192                                  (char *)blob.data, blob.length,
    193                                  global_myname(), 0, domain_name, 0x1c,
    194                                  dc_ss);
    195 }
    196 
    197 bool receive_getdc_response(TALLOC_CTX *mem_ctx,
    198                             struct sockaddr_storage *dc_ss,
    199                             const char *domain_name,
    200                             uint32_t *nt_version,
    201                             const char **dc_name,
    202                             struct netlogon_samlogon_response **_r)
    203 {
    204         struct packet_struct *packet;
    205         const char *my_mailslot = NULL;
    206         struct in_addr dc_ip;
     168                goto fail;
     169        }
     170
     171        ret = cli_prep_mailslot(false, NBT_MAILSLOT_NTLOGON, 0,
     172                                (char *)blob.data, blob.length,
     173                                global_myname(), 0, domain_name, 0x1c,
     174                                dc_ss, dgm_id, p);
     175fail:
     176        TALLOC_FREE(frame);
     177        return ret;
     178}
     179
     180static bool parse_getdc_response(
     181        struct packet_struct *packet,
     182        TALLOC_CTX *mem_ctx,
     183        const char *domain_name,
     184        uint32_t *nt_version,
     185        const char **dc_name,
     186        struct netlogon_samlogon_response **samlogon_response)
     187{
    207188        DATA_BLOB blob;
    208         struct netlogon_samlogon_response r;
     189        struct netlogon_samlogon_response *r;
    209190        union dgram_message_body p;
    210191        enum ndr_err_code ndr_err;
     
    214195        const char *returned_domain = NULL;
    215196
    216         if (dc_ss->ss_family != AF_INET) {
    217                 return false;
    218         }
    219 
    220         dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;
    221 
    222         my_mailslot = mailslot_name(mem_ctx, dc_ip);
    223         if (!my_mailslot) {
    224                 return false;
    225         }
    226 
    227         packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);
    228 
    229         if (packet == NULL) {
    230                 DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
    231                 return False;
    232         }
    233 
    234         DEBUG(5, ("Received packet for %s\n", my_mailslot));
    235 
    236197        blob = data_blob_const(packet->packet.dgram.data,
    237198                               packet->packet.dgram.datasize);
    238 
    239199        if (blob.length < 4) {
    240                 DEBUG(0,("invalid length: %d\n", (int)blob.length));
    241                 free_packet(packet);
     200                DEBUG(1, ("invalid length: %d\n", (int)blob.length));
    242201                return false;
    243202        }
    244203
    245204        if (RIVAL(blob.data,0) != DGRAM_SMB) {
    246                 DEBUG(0,("invalid packet\n"));
    247                 free_packet(packet);
     205                DEBUG(1, ("invalid packet\n"));
    248206                return false;
    249207        }
     
    252210        blob.length -= 4;
    253211
    254         ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, NULL, &p, DGRAM_SMB,
     212        ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, &p, DGRAM_SMB,
    255213                       (ndr_pull_flags_fn_t)ndr_pull_dgram_smb_packet);
    256214        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    257                 DEBUG(0,("failed to parse packet\n"));
    258                 free_packet(packet);
     215                DEBUG(1, ("failed to parse packet\n"));
    259216                return false;
    260217        }
    261218
    262219        if (p.smb.smb_command != SMB_TRANSACTION) {
    263                 DEBUG(0,("invalid smb_command: %d\n", p.smb.smb_command));
    264                 free_packet(packet);
     220                DEBUG(1, ("invalid smb_command: %d\n", p.smb.smb_command));
    265221                return false;
    266222        }
     
    272228        blob = p.smb.body.trans.data;
    273229
    274         ZERO_STRUCT(r);
    275 
    276         status = pull_netlogon_samlogon_response(&blob, mem_ctx, NULL, &r);
     230        r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response);
     231        if (!r) {
     232                return false;
     233        }
     234
     235        status = pull_netlogon_samlogon_response(&blob, r, r);
    277236        if (!NT_STATUS_IS_OK(status)) {
    278                 free_packet(packet);
    279                 return false;
    280         }
    281 
    282         map_netlogon_samlogon_response(&r);
     237                TALLOC_FREE(r);
     238                return false;
     239        }
     240
     241        map_netlogon_samlogon_response(r);
    283242
    284243        /* do we still need this ? */
    285         *nt_version = r.ntver;
    286 
    287         returned_domain = r.data.nt5_ex.domain;
    288         returned_dc = r.data.nt5_ex.pdc_name;
     244        *nt_version = r->ntver;
     245
     246        returned_domain = r->data.nt5_ex.domain_name;
     247        returned_dc = r->data.nt5_ex.pdc_name;
    289248
    290249        if (!strequal(returned_domain, domain_name)) {
    291250                DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
    292251                          domain_name, returned_domain));
    293                 free_packet(packet);
    294                 return false;
    295         }
     252                TALLOC_FREE(r);
     253                return false;
     254        }
     255
     256        if (*returned_dc == '\\') returned_dc += 1;
     257        if (*returned_dc == '\\') returned_dc += 1;
    296258
    297259        *dc_name = talloc_strdup(mem_ctx, returned_dc);
    298260        if (!*dc_name) {
    299                 free_packet(packet);
    300                 return false;
    301         }
    302 
    303         if (**dc_name == '\\')  *dc_name += 1;
    304         if (**dc_name == '\\')  *dc_name += 1;
    305 
    306         if (_r) {
    307                 *_r = (struct netlogon_samlogon_response *)talloc_memdup(
    308                         mem_ctx, &r, sizeof(struct netlogon_samlogon_response));
    309                 if (!*_r) {
    310                 free_packet(packet);
    311                         return false;
    312                 }
     261                TALLOC_FREE(r);
     262                return false;
     263        }
     264
     265        if (samlogon_response) {
     266                *samlogon_response = r;
     267        } else {
     268                TALLOC_FREE(r);
    313269        }
    314270
     
    316272                   *dc_name, returned_domain));
    317273
    318         free_packet(packet);
    319274        return True;
    320275}
     276
     277struct nbt_getdc_state {
     278        struct tevent_context *ev;
     279        struct messaging_context *msg_ctx;
     280        struct nb_packet_reader *reader;
     281        const char *my_mailslot;
     282        pid_t nmbd_pid;
     283
     284        const struct sockaddr_storage *dc_addr;
     285        const char *domain_name;
     286        const struct dom_sid *sid;
     287        uint32_t nt_version;
     288        const char *dc_name;
     289        struct netlogon_samlogon_response *samlogon_response;
     290
     291        struct packet_struct p;
     292};
     293
     294static void nbt_getdc_got_reader(struct tevent_req *subreq);
     295static void nbt_getdc_got_response(struct tevent_req *subreq);
     296
     297struct tevent_req *nbt_getdc_send(TALLOC_CTX *mem_ctx,
     298                                  struct tevent_context *ev,
     299                                  struct messaging_context *msg_ctx,
     300                                  const struct sockaddr_storage *dc_addr,
     301                                  const char *domain_name,
     302                                  const struct dom_sid *sid,
     303                                  uint32_t nt_version)
     304{
     305        struct tevent_req *req, *subreq;
     306        struct nbt_getdc_state *state;
     307        uint16_t dgm_id;
     308
     309        req = tevent_req_create(mem_ctx, &state, struct nbt_getdc_state);
     310        if (req == NULL) {
     311                return NULL;
     312        }
     313        state->ev = ev;
     314        state->msg_ctx = msg_ctx;
     315        state->dc_addr = dc_addr;
     316        state->domain_name = domain_name;
     317        state->sid = sid;
     318        state->nt_version = nt_version;
     319
     320        if (dc_addr->ss_family != AF_INET) {
     321                tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     322                return tevent_req_post(req, ev);
     323        }
     324        state->my_mailslot = mailslot_name(
     325                state, ((struct sockaddr_in *)dc_addr)->sin_addr);
     326        if (tevent_req_nomem(state->my_mailslot, req)) {
     327                return tevent_req_post(req, ev);
     328        }
     329        state->nmbd_pid = pidfile_pid("nmbd");
     330        if (state->nmbd_pid == 0) {
     331                DEBUG(3, ("No nmbd found\n"));
     332                tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     333                return tevent_req_post(req, ev);
     334        }
     335
     336        generate_random_buffer((uint8_t *)(void *)&dgm_id, sizeof(dgm_id));
     337
     338        if (!prep_getdc_request(dc_addr, domain_name, sid, nt_version,
     339                                state->my_mailslot, dgm_id & 0x7fff,
     340                                &state->p)) {
     341                DEBUG(3, ("prep_getdc_request failed\n"));
     342                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     343                return tevent_req_post(req, ev);
     344        }
     345
     346        subreq = nb_packet_reader_send(state, ev, DGRAM_PACKET, -1,
     347                                       state->my_mailslot);
     348        if (tevent_req_nomem(subreq, req)) {
     349                return tevent_req_post(req, ev);
     350        }
     351        tevent_req_set_callback(subreq, nbt_getdc_got_reader, req);
     352        return req;
     353}
     354
     355static void nbt_getdc_got_reader(struct tevent_req *subreq)
     356{
     357        struct tevent_req *req = tevent_req_callback_data(
     358                subreq, struct tevent_req);
     359        struct nbt_getdc_state *state = tevent_req_data(
     360                req, struct nbt_getdc_state);
     361        NTSTATUS status;
     362
     363        status = nb_packet_reader_recv(subreq, state, &state->reader);
     364        TALLOC_FREE(subreq);
     365        if (tevent_req_nterror(req, status)) {
     366                DEBUG(10, ("nb_packet_reader_recv returned %s\n",
     367                           nt_errstr(status)));
     368                return;
     369        }
     370
     371        status = messaging_send_buf(
     372                state->msg_ctx, pid_to_procid(state->nmbd_pid),
     373                MSG_SEND_PACKET, (uint8_t *)&state->p, sizeof(state->p));
     374
     375        if (tevent_req_nterror(req, status)) {
     376                DEBUG(10, ("messaging_send_buf returned %s\n",
     377                           nt_errstr(status)));
     378                return;
     379        }
     380        subreq = nb_packet_read_send(state, state->ev, state->reader);
     381        if (tevent_req_nomem(subreq, req)) {
     382                return;
     383        }
     384        tevent_req_set_callback(subreq, nbt_getdc_got_response, req);
     385}
     386
     387static void nbt_getdc_got_response(struct tevent_req *subreq)
     388{
     389        struct tevent_req *req = tevent_req_callback_data(
     390                subreq, struct tevent_req);
     391        struct nbt_getdc_state *state = tevent_req_data(
     392                req, struct nbt_getdc_state);
     393        struct packet_struct *p;
     394        NTSTATUS status;
     395        bool ret;
     396
     397        status = nb_packet_read_recv(subreq, &p);
     398        TALLOC_FREE(subreq);
     399        if (tevent_req_nterror(req, status)) {
     400                return;
     401        }
     402
     403        ret = parse_getdc_response(p, state, state->domain_name,
     404                                   &state->nt_version, &state->dc_name,
     405                                   &state->samlogon_response);
     406        free_packet(p);
     407        if (!ret) {
     408                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     409                return;
     410        }
     411        tevent_req_done(req);
     412}
     413
     414NTSTATUS nbt_getdc_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     415                        uint32_t *nt_version, const char **dc_name,
     416                        struct netlogon_samlogon_response **samlogon_response)
     417{
     418        struct nbt_getdc_state *state = tevent_req_data(
     419                req, struct nbt_getdc_state);
     420        NTSTATUS status;
     421
     422        if (tevent_req_is_nterror(req, &status)) {
     423                return status;
     424        }
     425        if (nt_version != NULL) {
     426                *nt_version = state->nt_version;
     427        }
     428        if (dc_name != NULL) {
     429                *dc_name = talloc_move(mem_ctx, &state->dc_name);
     430        }
     431        if (samlogon_response != NULL) {
     432                *samlogon_response = talloc_move(
     433                        mem_ctx, &state->samlogon_response);
     434        }
     435        return NT_STATUS_OK;
     436}
     437
     438NTSTATUS nbt_getdc(struct messaging_context *msg_ctx,
     439                   const struct sockaddr_storage *dc_addr,
     440                   const char *domain_name,
     441                   const struct dom_sid *sid,
     442                   uint32_t nt_version,
     443                   TALLOC_CTX *mem_ctx,
     444                   uint32_t *pnt_version,
     445                   const char **dc_name,
     446                   struct netlogon_samlogon_response **samlogon_response)
     447{
     448        TALLOC_CTX *frame = talloc_stackframe();
     449        struct tevent_context *ev;
     450        struct tevent_req *req;
     451        NTSTATUS status = NT_STATUS_NO_MEMORY;
     452
     453        ev = tevent_context_init(frame);
     454        if (ev == NULL) {
     455                goto fail;
     456        }
     457        req = nbt_getdc_send(ev, ev, msg_ctx, dc_addr, domain_name,
     458                             sid, nt_version);
     459        if (req == NULL) {
     460                goto fail;
     461        }
     462        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     463                goto fail;
     464        }
     465        status = nbt_getdc_recv(req, mem_ctx, pnt_version, dc_name,
     466                                samlogon_response);
     467 fail:
     468        TALLOC_FREE(frame);
     469        return status;
     470}
  • vendor/current/source3/libsmb/clientgen.c

    r427 r740  
    2020
    2121#include "includes.h"
     22#include "libsmb/libsmb.h"
     23#include "../lib/util/tevent_ntstatus.h"
     24#include "smb_signing.h"
     25#include "async_smb.h"
    2226
    2327/*******************************************************************
     
    247251        /* If the server is not responding, note that now */
    248252        if (len < 0) {
    249                 DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
    250                 close(cli->fd);
    251                 cli->fd = -1;
     253                /*
     254                 * only log if the connection should still be open and not when
     255                 * the connection was closed due to a dropped ip message
     256                 */
     257                if (cli->fd != -1) {
     258                        char addr[INET6_ADDRSTRLEN];
     259                        print_sockaddr(addr, sizeof(addr), &cli->dest_ss);
     260                        DEBUG(0, ("Receiving SMB: Server %s stopped responding\n",
     261                                addr));
     262                        close(cli->fd);
     263                        cli->fd = -1;
     264                }
    252265                return false;
    253266        }
     
    286299}
    287300
    288 /****************************************************************************
    289  Read the data portion of a readX smb.
    290  The timeout is in milliseconds
    291 ****************************************************************************/
    292 
    293 ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len)
    294 {
    295         NTSTATUS status;
    296 
    297         set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
    298 
    299         status = read_fd_with_timeout(
    300                 cli->fd, buffer, len, len, cli->timeout, NULL);
    301         if (NT_STATUS_IS_OK(status)) {
    302                 return len;
    303         }
    304 
    305         if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
    306                 set_smb_read_error(&cli->smb_rw_error, SMB_READ_EOF);
    307                 return -1;
    308         }
    309 
    310         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
    311                 set_smb_read_error(&cli->smb_rw_error, SMB_READ_TIMEOUT);
    312                 return -1;
    313         }
    314 
    315         set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
    316         return -1;
    317 }
    318 
    319301static ssize_t write_socket(int fd, const char *buf, size_t len)
    320302{
     
    391373        if (enc_on) {
    392374                cli_free_enc_buffer(cli, buf_out);
    393         }
    394 
    395         /* Increment the mid so we can tell between responses. */
    396         cli->mid++;
    397         if (!cli->mid)
    398                 cli->mid++;
    399         return true;
    400 }
    401 
    402 /****************************************************************************
    403  Send a "direct" writeX smb to a fd.
    404 ****************************************************************************/
    405 
    406 bool cli_send_smb_direct_writeX(struct cli_state *cli,
    407                                 const char *p,
    408                                 size_t extradata)
    409 {
    410         /* First length to send is the offset to the data. */
    411         size_t len = SVAL(cli->outbuf,smb_vwv11) + 4;
    412         size_t nwritten=0;
    413         struct iovec iov[2];
    414 
    415         /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
    416         if (cli->fd == -1) {
    417                 return false;
    418         }
    419 
    420         if (client_is_signing_on(cli)) {
    421                 DEBUG(0,("cli_send_smb_large: cannot send signed packet.\n"));
    422                 return false;
    423         }
    424 
    425         iov[0].iov_base = (void *)cli->outbuf;
    426         iov[0].iov_len = len;
    427         iov[1].iov_base = CONST_DISCARD(void *, p);
    428         iov[1].iov_len = extradata;
    429 
    430         nwritten = write_data_iov(cli->fd, iov, 2);
    431         if (nwritten < (len + extradata)) {
    432                 close(cli->fd);
    433                 cli->fd = -1;
    434                 cli->smb_rw_error = SMB_WRITE_ERROR;
    435                 DEBUG(0,("Error writing %d bytes to client. (%s)\n",
    436                          (int)(len+extradata), strerror(errno)));
    437                 return false;
    438375        }
    439376
     
    639576#if defined(DEVELOPER)
    640577        /* just because we over-allocate, doesn't mean it's right to use it */
    641         clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
    642         clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
     578        clobber_region(__FUNCTION__, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN);
     579        clobber_region(__FUNCTION__, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN);
    643580#endif
    644581
     
    694631****************************************************************************/
    695632
    696 void cli_shutdown(struct cli_state *cli)
    697 {
    698         if (cli == NULL) {
    699                 return;
    700         }
    701 
    702         if (cli->prev == NULL) {
    703                 /*
    704                  * Possible head of a DFS list,
    705                  * shutdown all subsidiary DFS
    706                  * connections.
    707                  */
    708                 struct cli_state *p, *next;
    709 
    710                 for (p = cli->next; p; p = next) {
    711                         next = p->next;
    712                         cli_shutdown(p);
    713                 }
    714         } else {
    715                 /*
    716                  * We're a subsidiary connection.
    717                  * Just remove ourselves from the
    718                  * DFS list.
    719                  */
    720                 DLIST_REMOVE(cli->prev, cli);
    721         }
    722 
     633static void _cli_shutdown(struct cli_state *cli)
     634{
    723635        cli_nt_pipes_close(cli);
    724636
     
    760672}
    761673
     674void cli_shutdown(struct cli_state *cli)
     675{
     676        struct cli_state *cli_head;
     677        if (cli == NULL) {
     678                return;
     679        }
     680        DLIST_HEAD(cli, cli_head);
     681        if (cli_head == cli) {
     682                /*
     683                 * head of a DFS list, shutdown all subsidiary DFS
     684                 * connections.
     685                 */
     686                struct cli_state *p, *next;
     687
     688                for (p = cli_head->next; p; p = next) {
     689                        next = p->next;
     690                        DLIST_REMOVE(cli_head, p);
     691                        _cli_shutdown(p);
     692                }
     693        } else {
     694                DLIST_REMOVE(cli_head, cli);
     695        }
     696
     697        _cli_shutdown(cli);
     698}
     699
    762700/****************************************************************************
    763701 Set socket options on a open connection.
     
    789727        cli->case_sensitive = case_sensitive;
    790728        return ret;
    791 }
    792 
    793 /****************************************************************************
    794 Send a keepalive packet to the server
    795 ****************************************************************************/
    796 
    797 bool cli_send_keepalive(struct cli_state *cli)
    798 {
    799         if (cli->fd == -1) {
    800                 DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
    801                 return false;
    802         }
    803         if (!send_keepalive(cli->fd)) {
    804                 close(cli->fd);
    805                 cli->fd = -1;
    806                 DEBUG(0,("Error sending keepalive packet to client.\n"));
    807                 return false;
    808         }
    809         return true;
    810729}
    811730
     
    854773        uint32_t num_bytes;
    855774        uint8_t *bytes;
    856 
    857         status = cli_smb_recv(subreq, 0, NULL, NULL, &num_bytes, &bytes);
     775        uint8_t *inbuf;
     776
     777        status = cli_smb_recv(subreq, state, &inbuf, 0, NULL, NULL,
     778                              &num_bytes, &bytes);
    858779        if (!NT_STATUS_IS_OK(status)) {
    859780                tevent_req_nterror(req, status);
     
    964885        return false;
    965886}
     887
     888NTSTATUS cli_smb(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     889                 uint8_t smb_command, uint8_t additional_flags,
     890                 uint8_t wct, uint16_t *vwv,
     891                 uint32_t num_bytes, const uint8_t *bytes,
     892                 struct tevent_req **result_parent,
     893                 uint8_t min_wct, uint8_t *pwct, uint16_t **pvwv,
     894                 uint32_t *pnum_bytes, uint8_t **pbytes)
     895{
     896        struct tevent_context *ev;
     897        struct tevent_req *req = NULL;
     898        NTSTATUS status = NT_STATUS_NO_MEMORY;
     899
     900        if (cli_has_async_calls(cli)) {
     901                return NT_STATUS_INVALID_PARAMETER;
     902        }
     903        ev = tevent_context_init(mem_ctx);
     904        if (ev == NULL) {
     905                goto fail;
     906        }
     907        req = cli_smb_send(mem_ctx, ev, cli, smb_command, additional_flags,
     908                           wct, vwv, num_bytes, bytes);
     909        if (req == NULL) {
     910                goto fail;
     911        }
     912        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     913                goto fail;
     914        }
     915        status = cli_smb_recv(req, NULL, NULL, min_wct, pwct, pvwv,
     916                              pnum_bytes, pbytes);
     917fail:
     918        TALLOC_FREE(ev);
     919        if (NT_STATUS_IS_OK(status) && (result_parent != NULL)) {
     920                *result_parent = req;
     921        }
     922        return status;
     923}
  • vendor/current/source3/libsmb/clierror.c

    r427 r740  
    2121
    2222#include "includes.h"
     23#include "libsmb/libsmb.h"
    2324
    2425/*****************************************************
  • vendor/current/source3/libsmb/clifile.c

    r414 r740  
    44   Copyright (C) Andrew Tridgell 1994-1998
    55   Copyright (C) Jeremy Allison 2001-2009
    6    
     6
    77   This program is free software; you can redistribute it and/or modify
    88   it under the terms of the GNU General Public License as published by
    99   the Free Software Foundation; either version 3 of the License, or
    1010   (at your option) any later version.
    11    
     11
    1212   This program is distributed in the hope that it will be useful,
    1313   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1414   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1515   GNU General Public License for more details.
    16    
     16
    1717   You should have received a copy of the GNU General Public License
    1818   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2020
    2121#include "includes.h"
     22#include "system/filesys.h"
     23#include "libsmb/libsmb.h"
     24#include "../lib/util/tevent_ntstatus.h"
     25#include "async_smb.h"
     26#include "libsmb/clirap.h"
     27#include "trans2.h"
     28#include "ntioctl.h"
    2229
    2330/***********************************************************
     
    9299}
    93100
     101uint8_t *smb_bytes_push_bytes(uint8_t *buf, uint8_t prefix,
     102                              const uint8_t *bytes, size_t num_bytes)
     103{
     104        size_t buflen;
     105
     106        if (buf == NULL) {
     107                return NULL;
     108        }
     109        buflen = talloc_get_size(buf);
     110
     111        buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
     112                                   buflen + 1 + num_bytes);
     113        if (buf == NULL) {
     114                return NULL;
     115        }
     116        buf[buflen] = prefix;
     117        memcpy(&buf[buflen+1], bytes, num_bytes);
     118        return buf;
     119}
     120
    94121/***********************************************************
    95122 Same as smb_bytes_push_str(), but without the odd byte
     
    107134}
    108135
     136struct cli_setpathinfo_state {
     137        uint16_t setup;
     138        uint8_t *param;
     139};
     140
     141static void cli_setpathinfo_done(struct tevent_req *subreq);
     142
     143struct tevent_req *cli_setpathinfo_send(TALLOC_CTX *mem_ctx,
     144                                        struct tevent_context *ev,
     145                                        struct cli_state *cli,
     146                                        uint16_t level,
     147                                        const char *path,
     148                                        uint8_t *data,
     149                                        size_t data_len)
     150{
     151        struct tevent_req *req, *subreq;
     152        struct cli_setpathinfo_state *state;
     153
     154        req = tevent_req_create(mem_ctx, &state,
     155                                struct cli_setpathinfo_state);
     156        if (req == NULL) {
     157                return NULL;
     158        }
     159
     160        /* Setup setup word. */
     161        SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
     162
     163        /* Setup param array. */
     164        state->param = TALLOC_ZERO_ARRAY(state, uint8_t, 6);
     165        if (tevent_req_nomem(state->param, req)) {
     166                return tevent_req_post(req, ev);
     167        }
     168        SSVAL(state->param, 0, level);
     169
     170        state->param = trans2_bytes_push_str(
     171                state->param, cli_ucs2(cli), path, strlen(path)+1, NULL);
     172        if (tevent_req_nomem(state->param, req)) {
     173                return tevent_req_post(req, ev);
     174        }
     175
     176        subreq = cli_trans_send(
     177                state,                  /* mem ctx. */
     178                ev,                     /* event ctx. */
     179                cli,                    /* cli_state. */
     180                SMBtrans2,              /* cmd. */
     181                NULL,                   /* pipe name. */
     182                -1,                     /* fid. */
     183                0,                      /* function. */
     184                0,                      /* flags. */
     185                &state->setup,          /* setup. */
     186                1,                      /* num setup uint16_t words. */
     187                0,                      /* max returned setup. */
     188                state->param,           /* param. */
     189                talloc_get_size(state->param),  /* num param. */
     190                2,                      /* max returned param. */
     191                data,                   /* data. */
     192                data_len,               /* num data. */
     193                0);                     /* max returned data. */
     194
     195        if (tevent_req_nomem(subreq, req)) {
     196                return tevent_req_post(req, ev);
     197        }
     198        tevent_req_set_callback(subreq, cli_setpathinfo_done, req);
     199        return req;
     200}
     201
     202static void cli_setpathinfo_done(struct tevent_req *subreq)
     203{
     204        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     205                                         NULL, 0, NULL, NULL, 0, NULL);
     206        tevent_req_simple_finish_ntstatus(subreq, status);
     207}
     208
     209NTSTATUS cli_setpathinfo_recv(struct tevent_req *req)
     210{
     211        return tevent_req_simple_recv_ntstatus(req);
     212}
     213
     214NTSTATUS cli_setpathinfo(struct cli_state *cli,
     215                         uint16_t level,
     216                         const char *path,
     217                         uint8_t *data,
     218                         size_t data_len)
     219{
     220        TALLOC_CTX *frame = talloc_stackframe();
     221        struct tevent_context *ev;
     222        struct tevent_req *req;
     223        NTSTATUS status = NT_STATUS_NO_MEMORY;
     224
     225        if (cli_has_async_calls(cli)) {
     226                /*
     227                 * Can't use sync call while an async call is in flight
     228                 */
     229                status = NT_STATUS_INVALID_PARAMETER;
     230                goto fail;
     231        }
     232        ev = tevent_context_init(frame);
     233        if (ev == NULL) {
     234                goto fail;
     235        }
     236        req = cli_setpathinfo_send(ev, ev, cli, level, path, data, data_len);
     237        if (req == NULL) {
     238                goto fail;
     239        }
     240        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     241                goto fail;
     242        }
     243        status = cli_setpathinfo_recv(req);
     244 fail:
     245        TALLOC_FREE(frame);
     246        return status;
     247}
     248
    109249/****************************************************************************
    110250 Hard/Symlink a file (UNIX extensions).
     
    112252****************************************************************************/
    113253
    114 struct link_state {
    115         uint16_t setup;
    116         uint8_t *param;
     254struct cli_posix_link_internal_state {
    117255        uint8_t *data;
    118256};
    119257
    120 static void cli_posix_link_internal_done(struct tevent_req *subreq)
    121 {
    122         struct tevent_req *req = tevent_req_callback_data(
    123                                 subreq, struct tevent_req);
    124         struct link_state *state = tevent_req_data(req, struct link_state);
    125         NTSTATUS status;
    126 
    127         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    128         TALLOC_FREE(subreq);
    129         if (!NT_STATUS_IS_OK(status)) {
    130                 tevent_req_nterror(req, status);
    131                 return;
    132         }
    133         tevent_req_done(req);
    134 }
     258static void cli_posix_link_internal_done(struct tevent_req *subreq);
    135259
    136260static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
    137261                                        struct event_context *ev,
    138262                                        struct cli_state *cli,
     263                                        uint16_t level,
    139264                                        const char *oldname,
    140                                         const char *newname,
    141                                         bool hardlink)
     265                                        const char *newname)
    142266{
    143267        struct tevent_req *req = NULL, *subreq = NULL;
    144         struct link_state *state = NULL;
    145 
    146         req = tevent_req_create(mem_ctx, &state, struct link_state);
     268        struct cli_posix_link_internal_state *state = NULL;
     269
     270        req = tevent_req_create(mem_ctx, &state,
     271                                struct cli_posix_link_internal_state);
    147272        if (req == NULL) {
    148273                return NULL;
    149         }
    150 
    151         /* Setup setup word. */
    152         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
    153 
    154         /* Setup param array. */
    155         state->param = talloc_array(state, uint8_t, 6);
    156         if (tevent_req_nomem(state->param, req)) {
    157                 return tevent_req_post(req, ev);
    158         }
    159         memset(state->param, '\0', 6);
    160         SSVAL(state->param,0,hardlink ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
    161 
    162         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), newname,
    163                                    strlen(newname)+1, NULL);
    164 
    165         if (tevent_req_nomem(state->param, req)) {
    166                 return tevent_req_post(req, ev);
    167274        }
    168275
     
    172279                return tevent_req_post(req, ev);
    173280        }
    174         state->data = trans2_bytes_push_str(state->data, cli_ucs2(cli), oldname,
    175                                    strlen(oldname)+1, NULL);
    176 
    177         subreq = cli_trans_send(state,                  /* mem ctx. */
    178                                 ev,                     /* event ctx. */
    179                                 cli,                    /* cli_state. */
    180                                 SMBtrans2,              /* cmd. */
    181                                 NULL,                   /* pipe name. */
    182                                 -1,                     /* fid. */
    183                                 0,                      /* function. */
    184                                 0,                      /* flags. */
    185                                 &state->setup,          /* setup. */
    186                                 1,                      /* num setup uint16_t words. */
    187                                 0,                      /* max returned setup. */
    188                                 state->param,           /* param. */
    189                                 talloc_get_size(state->param),  /* num param. */
    190                                 2,                      /* max returned param. */
    191                                 state->data,            /* data. */
    192                                 talloc_get_size(state->data),   /* num data. */
    193                                 0);                     /* max returned data. */
    194 
     281        state->data = trans2_bytes_push_str(
     282                state->data, cli_ucs2(cli), oldname, strlen(oldname)+1, NULL);
     283
     284        subreq = cli_setpathinfo_send(
     285                state, ev, cli, level, newname,
     286                state->data, talloc_get_size(state->data));
    195287        if (tevent_req_nomem(subreq, req)) {
    196288                return tevent_req_post(req, ev);
     
    198290        tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
    199291        return req;
     292}
     293
     294static void cli_posix_link_internal_done(struct tevent_req *subreq)
     295{
     296        NTSTATUS status = cli_setpathinfo_recv(subreq);
     297        tevent_req_simple_finish_ntstatus(subreq, status);
    200298}
    201299
     
    210308                                        const char *newname)
    211309{
    212         return cli_posix_link_internal_send(mem_ctx, ev, cli,
    213                         oldname, newname, false);
     310        return cli_posix_link_internal_send(
     311                mem_ctx, ev, cli, SMB_SET_FILE_UNIX_LINK, oldname, newname);
    214312}
    215313
    216314NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
    217315{
    218         NTSTATUS status;
    219 
    220         if (tevent_req_is_nterror(req, &status)) {
    221                 return status;
    222         }
    223         return NT_STATUS_OK;
     316        return tevent_req_simple_recv_ntstatus(req);
    224317}
    225318
     
    277370
    278371struct readlink_state {
    279         uint16_t setup;
    280         uint8_t *param;
    281372        uint8_t *data;
    282373        uint32_t num_data;
    283374};
    284375
    285 static void cli_posix_readlink_done(struct tevent_req *subreq)
    286 {
    287         struct tevent_req *req = tevent_req_callback_data(
    288                                 subreq, struct tevent_req);
    289         struct readlink_state *state = tevent_req_data(req, struct readlink_state);
    290         NTSTATUS status;
    291 
    292         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
    293                         &state->data, &state->num_data);
    294         TALLOC_FREE(subreq);
    295         if (!NT_STATUS_IS_OK(status)) {
    296                 tevent_req_nterror(req, status);
    297                 return;
    298         }
    299         if (state->num_data == 0) {
    300                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
    301                 return;
    302         }
    303         if (state->data[state->num_data-1] != '\0') {
    304                 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
    305                 return;
    306         }
    307         tevent_req_done(req);
    308 }
     376static void cli_posix_readlink_done(struct tevent_req *subreq);
    309377
    310378struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
     
    318386        uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len);
    319387
    320         if (maxbytelen < len) {
     388        req = tevent_req_create(mem_ctx, &state, struct readlink_state);
     389        if (req == NULL) {
    321390                return NULL;
    322391        }
    323392
    324         req = tevent_req_create(mem_ctx, &state, struct readlink_state);
    325         if (req == NULL) {
    326                 return NULL;
    327         }
    328 
    329         /* Setup setup word. */
    330         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
    331 
    332         /* Setup param array. */
    333         state->param = talloc_array(state, uint8_t, 6);
    334         if (tevent_req_nomem(state->param, req)) {
    335                 return tevent_req_post(req, ev);
    336         }
    337         memset(state->param, '\0', 6);
    338         SSVAL(state->param,0,SMB_QUERY_FILE_UNIX_LINK);
    339 
    340         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    341                                    strlen(fname)+1, NULL);
    342 
    343         if (tevent_req_nomem(state->param, req)) {
    344                 return tevent_req_post(req, ev);
    345         }
    346 
    347         subreq = cli_trans_send(state,                  /* mem ctx. */
    348                                 ev,                     /* event ctx. */
    349                                 cli,                    /* cli_state. */
    350                                 SMBtrans2,              /* cmd. */
    351                                 NULL,                   /* pipe name. */
    352                                 -1,                     /* fid. */
    353                                 0,                      /* function. */
    354                                 0,                      /* flags. */
    355                                 &state->setup,          /* setup. */
    356                                 1,                      /* num setup uint16_t words. */
    357                                 0,                      /* max returned setup. */
    358                                 state->param,           /* param. */
    359                                 talloc_get_size(state->param),  /* num param. */
    360                                 2,                      /* max returned param. */
    361                                 NULL,                   /* data. */
    362                                 0,                      /* num data. */
    363                                 maxbytelen);            /* max returned data. */
    364 
     393        /*
     394         * Len is in bytes, we need it in UCS2 units.
     395         */
     396        if ((2*len < len) || (maxbytelen < len)) {
     397                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     398                return tevent_req_post(req, ev);
     399        }
     400
     401        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     402                                    SMB_QUERY_FILE_UNIX_LINK, 1, maxbytelen);
    365403        if (tevent_req_nomem(subreq, req)) {
    366404                return tevent_req_post(req, ev);
     
    368406        tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
    369407        return req;
     408}
     409
     410static void cli_posix_readlink_done(struct tevent_req *subreq)
     411{
     412        struct tevent_req *req = tevent_req_callback_data(
     413                subreq, struct tevent_req);
     414        struct readlink_state *state = tevent_req_data(
     415                req, struct readlink_state);
     416        NTSTATUS status;
     417
     418        status = cli_qpathinfo_recv(subreq, state, &state->data,
     419                                    &state->num_data);
     420        TALLOC_FREE(subreq);
     421        if (tevent_req_nterror(req, status)) {
     422                return;
     423        }
     424        /*
     425         * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
     426         */
     427        if (state->data[state->num_data-1] != '\0') {
     428                tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
     429                return;
     430        }
     431        tevent_req_done(req);
    370432}
    371433
     
    423485        }
    424486
    425         /* Len is in bytes, we need it in UCS2 units. */
    426         if (2*len < len) {
    427                 status = NT_STATUS_INVALID_PARAMETER;
    428                 goto fail;
    429         }
    430 
    431487        req = cli_posix_readlink_send(frame,
    432488                                ev,
     
    464520                                        const char *newname)
    465521{
    466         return cli_posix_link_internal_send(mem_ctx, ev, cli,
    467                         oldname, newname, true);
     522        return cli_posix_link_internal_send(
     523                mem_ctx, ev, cli, SMB_SET_FILE_UNIX_HLINK, oldname, newname);
    468524}
    469525
    470526NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
    471527{
    472         NTSTATUS status;
    473 
    474         if (tevent_req_is_nterror(req, &status)) {
    475                 return status;
    476         }
    477         return NT_STATUS_OK;
     528        return tevent_req_simple_recv_ntstatus(req);
    478529}
    479530
     
    625676
    626677struct getfacl_state {
    627         uint16_t setup;
    628         uint8_t *param;
    629678        uint32_t num_data;
    630679        uint8_t *data;
    631680};
    632681
    633 static void cli_posix_getfacl_done(struct tevent_req *subreq)
    634 {
    635         struct tevent_req *req = tevent_req_callback_data(
    636                                 subreq, struct tevent_req);
    637         struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
    638         NTSTATUS status;
    639 
    640         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
    641                         &state->data, &state->num_data);
    642         TALLOC_FREE(subreq);
    643         if (!NT_STATUS_IS_OK(status)) {
    644                 tevent_req_nterror(req, status);
    645                 return;
    646         }
    647         tevent_req_done(req);
    648 }
     682static void cli_posix_getfacl_done(struct tevent_req *subreq);
    649683
    650684struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
     
    654688{
    655689        struct tevent_req *req = NULL, *subreq = NULL;
    656         struct link_state *state = NULL;
     690        struct getfacl_state *state = NULL;
    657691
    658692        req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
     
    660694                return NULL;
    661695        }
    662 
    663         /* Setup setup word. */
    664         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
    665 
    666         /* Setup param array. */
    667         state->param = talloc_array(state, uint8_t, 6);
    668         if (tevent_req_nomem(state->param, req)) {
    669                 return tevent_req_post(req, ev);
    670         }
    671         memset(state->param, '\0', 6);
    672         SSVAL(state->param, 0, SMB_QUERY_POSIX_ACL);
    673 
    674         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    675                                    strlen(fname)+1, NULL);
    676 
    677         if (tevent_req_nomem(state->param, req)) {
    678                 return tevent_req_post(req, ev);
    679         }
    680 
    681         subreq = cli_trans_send(state,                  /* mem ctx. */
    682                                 ev,                     /* event ctx. */
    683                                 cli,                    /* cli_state. */
    684                                 SMBtrans2,              /* cmd. */
    685                                 NULL,                   /* pipe name. */
    686                                 -1,                     /* fid. */
    687                                 0,                      /* function. */
    688                                 0,                      /* flags. */
    689                                 &state->setup,          /* setup. */
    690                                 1,                      /* num setup uint16_t words. */
    691                                 0,                      /* max returned setup. */
    692                                 state->param,           /* param. */
    693                                 talloc_get_size(state->param),  /* num param. */
    694                                 2,                      /* max returned param. */
    695                                 NULL,                   /* data. */
    696                                 0,                      /* num data. */
    697                                 cli->max_xmit);         /* max returned data. */
    698 
     696        subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_POSIX_ACL,
     697                                    0, cli->max_xmit);
    699698        if (tevent_req_nomem(subreq, req)) {
    700699                return tevent_req_post(req, ev);
     
    702701        tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
    703702        return req;
     703}
     704
     705static void cli_posix_getfacl_done(struct tevent_req *subreq)
     706{
     707        struct tevent_req *req = tevent_req_callback_data(
     708                subreq, struct tevent_req);
     709        struct getfacl_state *state = tevent_req_data(
     710                req, struct getfacl_state);
     711        NTSTATUS status;
     712
     713        status = cli_qpathinfo_recv(subreq, state, &state->data,
     714                                    &state->num_data);
     715        TALLOC_FREE(subreq);
     716        if (tevent_req_nterror(req, status)) {
     717                return;
     718        }
     719        tevent_req_done(req);
    704720}
    705721
     
    774790
    775791struct stat_state {
    776         uint16_t setup;
    777         uint8_t *param;
    778792        uint32_t num_data;
    779793        uint8_t *data;
    780794};
     795
     796static void cli_posix_stat_done(struct tevent_req *subreq);
     797
     798struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
     799                                        struct event_context *ev,
     800                                        struct cli_state *cli,
     801                                        const char *fname)
     802{
     803        struct tevent_req *req = NULL, *subreq = NULL;
     804        struct stat_state *state = NULL;
     805
     806        req = tevent_req_create(mem_ctx, &state, struct stat_state);
     807        if (req == NULL) {
     808                return NULL;
     809        }
     810        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     811                                    SMB_QUERY_FILE_UNIX_BASIC, 100, 100);
     812        if (tevent_req_nomem(subreq, req)) {
     813                return tevent_req_post(req, ev);
     814        }
     815        tevent_req_set_callback(subreq, cli_posix_stat_done, req);
     816        return req;
     817}
    781818
    782819static void cli_posix_stat_done(struct tevent_req *subreq)
     
    787824        NTSTATUS status;
    788825
    789         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
    790                         &state->data, &state->num_data);
     826        status = cli_qpathinfo_recv(subreq, state, &state->data,
     827                                    &state->num_data);
    791828        TALLOC_FREE(subreq);
    792         if (!NT_STATUS_IS_OK(status)) {
    793                 tevent_req_nterror(req, status);
     829        if (tevent_req_nterror(req, status)) {
    794830                return;
    795831        }
    796832        tevent_req_done(req);
    797 }
    798 
    799 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
    800                                         struct event_context *ev,
    801                                         struct cli_state *cli,
    802                                         const char *fname)
    803 {
    804         struct tevent_req *req = NULL, *subreq = NULL;
    805         struct stat_state *state = NULL;
    806 
    807         req = tevent_req_create(mem_ctx, &state, struct stat_state);
    808         if (req == NULL) {
    809                 return NULL;
    810         }
    811 
    812         /* Setup setup word. */
    813         SSVAL(&state->setup, 0, TRANSACT2_QPATHINFO);
    814 
    815         /* Setup param array. */
    816         state->param = talloc_array(state, uint8_t, 6);
    817         if (tevent_req_nomem(state->param, req)) {
    818                 return tevent_req_post(req, ev);
    819         }
    820         memset(state->param, '\0', 6);
    821         SSVAL(state->param, 0, SMB_QUERY_FILE_UNIX_BASIC);
    822 
    823         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    824                                    strlen(fname)+1, NULL);
    825 
    826         if (tevent_req_nomem(state->param, req)) {
    827                 return tevent_req_post(req, ev);
    828         }
    829 
    830         subreq = cli_trans_send(state,                  /* mem ctx. */
    831                                 ev,                     /* event ctx. */
    832                                 cli,                    /* cli_state. */
    833                                 SMBtrans2,              /* cmd. */
    834                                 NULL,                   /* pipe name. */
    835                                 -1,                     /* fid. */
    836                                 0,                      /* function. */
    837                                 0,                      /* flags. */
    838                                 &state->setup,          /* setup. */
    839                                 1,                      /* num setup uint16_t words. */
    840                                 0,                      /* max returned setup. */
    841                                 state->param,           /* param. */
    842                                 talloc_get_size(state->param),  /* num param. */
    843                                 2,                      /* max returned param. */
    844                                 NULL,                   /* data. */
    845                                 0,                      /* num data. */
    846                                 96);                    /* max returned data. */
    847 
    848         if (tevent_req_nomem(subreq, req)) {
    849                 return tevent_req_post(req, ev);
    850         }
    851         tevent_req_set_callback(subreq, cli_posix_stat_done, req);
    852         return req;
    853833}
    854834
     
    861841        if (tevent_req_is_nterror(req, &status)) {
    862842                return status;
    863         }
    864 
    865         if (state->num_data != 96) {
    866                 return NT_STATUS_DATA_ERROR;
    867843        }
    868844
     
    891867        sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76);      /* inode */
    892868        sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84));     /* protection */
    893         sbuf->st_ex_nlink = IVAL(state->data,92);    /* number of hard links */
     869        sbuf->st_ex_nlink = BIG_UINT(state->data,92); /* number of hard links */
    894870
    895871        return NT_STATUS_OK;
     
    947923****************************************************************************/
    948924
    949 struct ch_state {
    950         uint16_t setup;
    951         uint8_t *param;
    952         uint8_t *data;
     925struct cli_posix_chown_chmod_internal_state {
     926        uint8_t data[100];
    953927};
    954928
    955 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
    956 {
    957         struct tevent_req *req = tevent_req_callback_data(
    958                                 subreq, struct tevent_req);
    959         struct ch_state *state = tevent_req_data(req, struct ch_state);
    960         NTSTATUS status;
    961 
    962         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    963         TALLOC_FREE(subreq);
    964         if (!NT_STATUS_IS_OK(status)) {
    965                 tevent_req_nterror(req, status);
    966                 return;
    967         }
    968         tevent_req_done(req);
    969 }
     929static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq);
    970930
    971931static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
     
    978938{
    979939        struct tevent_req *req = NULL, *subreq = NULL;
    980         struct ch_state *state = NULL;
    981 
    982         req = tevent_req_create(mem_ctx, &state, struct ch_state);
     940        struct cli_posix_chown_chmod_internal_state *state = NULL;
     941
     942        req = tevent_req_create(mem_ctx, &state,
     943                                struct cli_posix_chown_chmod_internal_state);
    983944        if (req == NULL) {
    984945                return NULL;
    985946        }
    986947
    987         /* Setup setup word. */
    988         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
    989 
    990         /* Setup param array. */
    991         state->param = talloc_array(state, uint8_t, 6);
    992         if (tevent_req_nomem(state->param, req)) {
    993                 return tevent_req_post(req, ev);
    994         }
    995         memset(state->param, '\0', 6);
    996         SSVAL(state->param,0,SMB_SET_FILE_UNIX_BASIC);
    997 
    998         state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
    999                                    strlen(fname)+1, NULL);
    1000 
    1001         if (tevent_req_nomem(state->param, req)) {
    1002                 return tevent_req_post(req, ev);
    1003         }
    1004 
    1005         /* Setup data array. */
    1006         state->data = talloc_array(state, uint8_t, 100);
    1007         if (tevent_req_nomem(state->data, req)) {
    1008                 return tevent_req_post(req, ev);
    1009         }
    1010948        memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
    1011949        memset(&state->data[40], '\0', 60);
     
    1014952        SIVAL(state->data,84,mode);
    1015953
    1016         subreq = cli_trans_send(state,                  /* mem ctx. */
    1017                                 ev,                     /* event ctx. */
    1018                                 cli,                    /* cli_state. */
    1019                                 SMBtrans2,              /* cmd. */
    1020                                 NULL,                   /* pipe name. */
    1021                                 -1,                     /* fid. */
    1022                                 0,                      /* function. */
    1023                                 0,                      /* flags. */
    1024                                 &state->setup,          /* setup. */
    1025                                 1,                      /* num setup uint16_t words. */
    1026                                 0,                      /* max returned setup. */
    1027                                 state->param,           /* param. */
    1028                                 talloc_get_size(state->param),  /* num param. */
    1029                                 2,                      /* max returned param. */
    1030                                 state->data,            /* data. */
    1031                                 talloc_get_size(state->data),   /* num data. */
    1032                                 0);                     /* max returned data. */
    1033 
     954        subreq = cli_setpathinfo_send(state, ev, cli, SMB_SET_FILE_UNIX_BASIC,
     955                                      fname, state->data, sizeof(state->data));
    1034956        if (tevent_req_nomem(subreq, req)) {
    1035957                return tevent_req_post(req, ev);
    1036958        }
    1037         tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done, req);
     959        tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done,
     960                                req);
    1038961        return req;
     962}
     963
     964static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
     965{
     966        NTSTATUS status = cli_setpathinfo_recv(subreq);
     967        tevent_req_simple_finish_ntstatus(subreq, status);
    1039968}
    1040969
     
    1058987NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
    1059988{
    1060         NTSTATUS status;
    1061 
    1062         if (tevent_req_is_nterror(req, &status)) {
    1063                 return status;
    1064         }
    1065         return NT_STATUS_OK;
     989        return tevent_req_simple_recv_ntstatus(req);
    1066990}
    1067991
     
    11321056NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
    11331057{
    1134         NTSTATUS status;
    1135 
    1136         if (tevent_req_is_nterror(req, &status)) {
    1137                 return status;
    1138         }
    1139         return NT_STATUS_OK;
     1058        return tevent_req_simple_recv_ntstatus(req);
    11401059}
    11411060
     
    12161135        }
    12171136
    1218         SSVAL(state->vwv+0, 0, aSYSTEM | aHIDDEN | aDIR);
     1137        SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
    12191138
    12201139        bytes = talloc_array(state, uint8_t, 1);
     
    12571176        NTSTATUS status;
    12581177
    1259         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1178        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    12601179        TALLOC_FREE(subreq);
    1261         if (!NT_STATUS_IS_OK(status)) {
    1262                 tevent_req_nterror(req, status);
     1180        if (tevent_req_nterror(req, status)) {
    12631181                return;
    12641182        }
     
    13411259        }
    13421260
    1343         SSVAL(state->vwv+0, 0 ,aSYSTEM | aHIDDEN | aDIR);
     1261        SSVAL(state->vwv+0, 0 ,FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
    13441262        SSVAL(state->vwv+1, 0, rename_flag);
    13451263
     
    13831301        NTSTATUS status;
    13841302
    1385         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1303        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    13861304        TALLOC_FREE(subreq);
    1387         if (!NT_STATUS_IS_OK(status)) {
    1388                 tevent_req_nterror(req, status);
     1305        if (tevent_req_nterror(req, status)) {
    13891306                return;
    13901307        }
     
    15781495        NTSTATUS status;
    15791496
    1580         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1497        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    15811498        TALLOC_FREE(subreq);
    1582         if (!NT_STATUS_IS_OK(status)) {
    1583                 tevent_req_nterror(req, status);
     1499        if (tevent_req_nterror(req, status)) {
    15841500                return;
    15851501        }
     
    16861602        NTSTATUS status;
    16871603
    1688         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1604        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    16891605        TALLOC_FREE(subreq);
    1690         if (!NT_STATUS_IS_OK(status)) {
    1691                 tevent_req_nterror(req, status);
     1606        if (tevent_req_nterror(req, status)) {
    16921607                return;
    16931608        }
     
    17941709        NTSTATUS status;
    17951710
    1796         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     1711        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    17971712        TALLOC_FREE(subreq);
    1798         if (!NT_STATUS_IS_OK(status)) {
    1799                 tevent_req_nterror(req, status);
     1713        if (tevent_req_nterror(req, status)) {
    18001714                return;
    18011715        }
     
    18621776static void cli_nt_delete_on_close_done(struct tevent_req *subreq)
    18631777{
    1864         struct tevent_req *req = tevent_req_callback_data(
    1865                                 subreq, struct tevent_req);
    1866         struct doc_state *state = tevent_req_data(req, struct doc_state);
    1867         NTSTATUS status;
    1868 
    1869         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    1870         TALLOC_FREE(subreq);
    1871         if (!NT_STATUS_IS_OK(status)) {
    1872                 tevent_req_nterror(req, status);
    1873                 return;
    1874         }
    1875         tevent_req_done(req);
     1778        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     1779                                         NULL, 0, NULL, NULL, 0, NULL);
     1780        tevent_req_simple_finish_ntstatus(subreq, status);
    18761781}
    18771782
     
    19271832NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
    19281833{
    1929         NTSTATUS status;
    1930 
    1931         if (tevent_req_is_nterror(req, &status)) {
    1932                 return status;
    1933         }
    1934         return NT_STATUS_OK;
     1834        return tevent_req_simple_recv_ntstatus(req);
    19351835}
    19361836
     
    20661966        uint32_t num_bytes;
    20671967        uint8_t *bytes;
     1968        uint8_t *inbuf;
    20681969        NTSTATUS status;
    20691970
    2070         status = cli_smb_recv(subreq, 3, &wct, &vwv, &num_bytes, &bytes);
    2071         if (!NT_STATUS_IS_OK(status)) {
    2072                 TALLOC_FREE(subreq);
    2073                 tevent_req_nterror(req, status);
     1971        status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv,
     1972                              &num_bytes, &bytes);
     1973        TALLOC_FREE(subreq);
     1974        if (tevent_req_nterror(req, status)) {
    20741975                return;
    20751976        }
     
    22092110        SSVAL(state->vwv + 2, 0, 0);  /* no additional info */
    22102111        SSVAL(state->vwv + 3, 0, accessmode);
    2211         SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN);
     2112        SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
    22122113        SSVAL(state->vwv + 5, 0, 0);
    22132114        SIVAL(state->vwv + 6, 0, 0);
     
    22632164
    22642165        status = cli_smb_req_send(subreq);
    2265         if (!NT_STATUS_IS_OK(status)) {
    2266                 tevent_req_nterror(req, status);
     2166        if (tevent_req_nterror(req, status)) {
    22672167                return tevent_req_post(req, ev);
    22682168        }
     
    22782178        uint8_t wct;
    22792179        uint16_t *vwv;
     2180        uint8_t *inbuf;
    22802181        NTSTATUS status;
    22812182
    2282         status = cli_smb_recv(subreq, 3, &wct, &vwv, NULL, NULL);
    2283         if (!NT_STATUS_IS_OK(status)) {
    2284                 TALLOC_FREE(subreq);
    2285                 tevent_req_nterror(req, status);
     2183        status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv, NULL,
     2184                              NULL);
     2185        TALLOC_FREE(subreq);
     2186        if (tevent_req_nterror(req, status)) {
    22862187                return;
    22872188        }
     
    23972298
    23982299        status = cli_smb_req_send(subreq);
    2399         if (!NT_STATUS_IS_OK(status)) {
    2400                 tevent_req_nterror(req, status);
     2300        if (tevent_req_nterror(req, status)) {
    24012301                return tevent_req_post(req, ev);
    24022302        }
     
    24102310        NTSTATUS status;
    24112311
    2412         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     2312        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    24132313        TALLOC_FREE(subreq);
    2414         if (!NT_STATUS_IS_OK(status)) {
    2415                 tevent_req_nterror(req, status);
     2314        if (tevent_req_nterror(req, status)) {
    24162315                return;
    24172316        }
     
    24772376static void cli_ftruncate_done(struct tevent_req *subreq)
    24782377{
    2479         struct tevent_req *req = tevent_req_callback_data(
    2480                                 subreq, struct tevent_req);
    2481         struct ftrunc_state *state = tevent_req_data(req, struct ftrunc_state);
    2482         NTSTATUS status;
    2483 
    2484         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    2485         TALLOC_FREE(subreq);
    2486         if (!NT_STATUS_IS_OK(status)) {
    2487                 tevent_req_nterror(req, status);
    2488                 return;
    2489         }
    2490         tevent_req_done(req);
     2378        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     2379                                         NULL, 0, NULL, NULL, 0, NULL);
     2380        tevent_req_simple_finish_ntstatus(subreq, status);
    24912381}
    24922382
     
    25432433NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
    25442434{
    2545         NTSTATUS status;
    2546 
    2547         if (tevent_req_is_nterror(req, &status)) {
    2548                 return status;
    2549         }
    2550         return NT_STATUS_OK;
     2435        return tevent_req_simple_recv_ntstatus(req);
    25512436}
    25522437
     
    26062491                      int timeout, unsigned char locktype)
    26072492{
    2608         char *p;
    2609         int saved_timeout = cli->timeout;
    2610 
    2611         memset(cli->outbuf,'\0',smb_size);
    2612         memset(cli->inbuf,'\0', smb_size);
    2613 
    2614         cli_set_message(cli->outbuf,8,0,True);
    2615 
    2616         SCVAL(cli->outbuf,smb_com,SMBlockingX);
    2617         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    2618         cli_setup_packet(cli);
    2619 
    2620         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    2621         SSVAL(cli->outbuf,smb_vwv2,fnum);
    2622         SCVAL(cli->outbuf,smb_vwv3,locktype);
    2623         SIVALS(cli->outbuf, smb_vwv4, timeout);
    2624         SSVAL(cli->outbuf,smb_vwv6,0);
    2625         SSVAL(cli->outbuf,smb_vwv7,1);
    2626 
    2627         p = smb_buf(cli->outbuf);
    2628         SSVAL(p, 0, cli->pid);
    2629         SIVAL(p, 2, offset);
    2630         SIVAL(p, 6, len);
    2631 
    2632         p += 10;
    2633 
    2634         cli_setup_bcc(cli, p);
    2635 
    2636         cli_send_smb(cli);
     2493        uint16_t vwv[8];
     2494        uint8_t bytes[10];
     2495        NTSTATUS status;
     2496        int saved_timeout;
     2497
     2498        SCVAL(vwv + 0, 0, 0xff);
     2499        SCVAL(vwv + 0, 1, 0);
     2500        SSVAL(vwv + 1, 0, 0);
     2501        SSVAL(vwv + 2, 0, fnum);
     2502        SCVAL(vwv + 3, 0, locktype);
     2503        SCVAL(vwv + 3, 1, 0);
     2504        SIVALS(vwv + 4, 0, timeout);
     2505        SSVAL(vwv + 6, 0, 0);
     2506        SSVAL(vwv + 7, 0, 1);
     2507
     2508        SSVAL(bytes, 0, cli->pid);
     2509        SIVAL(bytes, 2, offset);
     2510        SIVAL(bytes, 6, len);
     2511
     2512        saved_timeout = cli->timeout;
    26372513
    26382514        if (timeout != 0) {
    2639                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
    2640         }
    2641 
    2642         if (!cli_receive_smb(cli)) {
    2643                 cli->timeout = saved_timeout;
    2644                 return NT_STATUS_UNSUCCESSFUL;
    2645         }
     2515                cli->timeout = (timeout == -1)
     2516                        ? 0x7FFFFFFF : (timeout + 2*1000);
     2517        }
     2518
     2519        status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
     2520                         10, bytes, NULL, 0, NULL, NULL, NULL, NULL);
    26462521
    26472522        cli->timeout = saved_timeout;
    26482523
    2649         return cli_nt_error(cli);
     2524        return status;
    26502525}
    26512526
     
    26562531
    26572532bool cli_lock(struct cli_state *cli, uint16_t fnum,
    2658               uint32_t offset, uint32_t len, int timeout, enum brl_type lock_type)
    2659 {
    2660         char *p;
    2661         int saved_timeout = cli->timeout;
    2662 
    2663         memset(cli->outbuf,'\0',smb_size);
    2664         memset(cli->inbuf,'\0', smb_size);
    2665 
    2666         cli_set_message(cli->outbuf,8,0,True);
    2667 
    2668         SCVAL(cli->outbuf,smb_com,SMBlockingX);
    2669         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    2670         cli_setup_packet(cli);
    2671 
    2672         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    2673         SSVAL(cli->outbuf,smb_vwv2,fnum);
    2674         SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
    2675         SIVALS(cli->outbuf, smb_vwv4, timeout);
    2676         SSVAL(cli->outbuf,smb_vwv6,0);
    2677         SSVAL(cli->outbuf,smb_vwv7,1);
    2678 
    2679         p = smb_buf(cli->outbuf);
    2680         SSVAL(p, 0, cli->pid);
    2681         SIVAL(p, 2, offset);
    2682         SIVAL(p, 6, len);
    2683 
    2684         p += 10;
    2685 
    2686         cli_setup_bcc(cli, p);
    2687 
    2688         cli_send_smb(cli);
    2689 
    2690         if (timeout != 0) {
    2691                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
    2692         }
    2693 
    2694         if (!cli_receive_smb(cli)) {
    2695                 cli->timeout = saved_timeout;
    2696                 return False;
    2697         }
    2698 
    2699         cli->timeout = saved_timeout;
    2700 
    2701         if (cli_is_error(cli)) {
    2702                 return False;
    2703         }
    2704 
    2705         return True;
     2533                  uint32_t offset, uint32_t len, int timeout,
     2534                  enum brl_type lock_type)
     2535{
     2536        NTSTATUS status;
     2537
     2538        status = cli_locktype(cli, fnum, offset, len, timeout,
     2539                              (lock_type == READ_LOCK? 1 : 0));
     2540        cli_set_error(cli, status);
     2541        return NT_STATUS_IS_OK(status);
    27062542}
    27072543
     
    27602596        NTSTATUS status;
    27612597
    2762         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     2598        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    27632599        TALLOC_FREE(subreq);
    2764         if (!NT_STATUS_IS_OK(status)) {
    2765                 tevent_req_nterror(req, status);
     2600        if (tevent_req_nterror(req, status)) {
    27662601                return;
    27672602        }
     
    28252660
    28262661bool cli_lock64(struct cli_state *cli, uint16_t fnum,
    2827                 uint64_t offset, uint64_t len, int timeout, enum brl_type lock_type)
    2828 {
    2829         char *p;
     2662                uint64_t offset, uint64_t len, int timeout,
     2663                enum brl_type lock_type)
     2664{
     2665        uint16_t vwv[8];
     2666        uint8_t bytes[20];
    28302667        int saved_timeout = cli->timeout;
    28312668        int ltype;
     2669        NTSTATUS status;
    28322670
    28332671        if (! (cli->capabilities & CAP_LARGE_FILES)) {
     
    28382676        ltype |= LOCKING_ANDX_LARGE_FILES;
    28392677
    2840         memset(cli->outbuf,'\0',smb_size);
    2841         memset(cli->inbuf,'\0', smb_size);
    2842 
    2843         cli_set_message(cli->outbuf,8,0,True);
    2844 
    2845         SCVAL(cli->outbuf,smb_com,SMBlockingX);
    2846         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    2847         cli_setup_packet(cli);
    2848 
    2849         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    2850         SSVAL(cli->outbuf,smb_vwv2,fnum);
    2851         SCVAL(cli->outbuf,smb_vwv3,ltype);
    2852         SIVALS(cli->outbuf, smb_vwv4, timeout);
    2853         SSVAL(cli->outbuf,smb_vwv6,0);
    2854         SSVAL(cli->outbuf,smb_vwv7,1);
    2855 
    2856         p = smb_buf(cli->outbuf);
    2857         SIVAL(p, 0, cli->pid);
    2858         SOFF_T_R(p, 4, offset);
    2859         SOFF_T_R(p, 12, len);
    2860         p += 20;
    2861 
    2862         cli_setup_bcc(cli, p);
    2863         cli_send_smb(cli);
     2678        SCVAL(vwv + 0, 0, 0xff);
     2679        SCVAL(vwv + 0, 1, 0);
     2680        SSVAL(vwv + 1, 0, 0);
     2681        SSVAL(vwv + 2, 0, fnum);
     2682        SCVAL(vwv + 3, 0, ltype);
     2683        SCVAL(vwv + 3, 1, 0);
     2684        SIVALS(vwv + 4, 0, timeout);
     2685        SSVAL(vwv + 6, 0, 0);
     2686        SSVAL(vwv + 7, 0, 1);
     2687
     2688        SIVAL(bytes, 0, cli->pid);
     2689        SOFF_T_R(bytes, 4, offset);
     2690        SOFF_T_R(bytes, 12, len);
     2691
     2692        saved_timeout = cli->timeout;
    28642693
    28652694        if (timeout != 0) {
    2866                 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
    2867         }
    2868 
    2869         if (!cli_receive_smb(cli)) {
    2870                 cli->timeout = saved_timeout;
    2871                 return False;
    2872         }
     2695                cli->timeout = (timeout == -1)
     2696                        ? 0x7FFFFFFF : (timeout + 2*1000);
     2697        }
     2698
     2699        status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
     2700                         20, bytes, NULL, 0, NULL, NULL, NULL, NULL);
    28732701
    28742702        cli->timeout = saved_timeout;
    28752703
    2876         if (cli_is_error(cli)) {
    2877                 return False;
    2878         }
    2879 
    2880         return True;
     2704        cli_set_error(cli, status);
     2705        return NT_STATUS_IS_OK(status);
    28812706}
    28822707
     
    29352760        NTSTATUS status;
    29362761
    2937         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     2762        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    29382763        TALLOC_FREE(subreq);
    2939         if (!NT_STATUS_IS_OK(status)) {
    2940                 tevent_req_nterror(req, status);
     2764        if (tevent_req_nterror(req, status)) {
    29412765                return;
    29422766        }
     
    30112835static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
    30122836{
    3013         struct tevent_req *req = tevent_req_callback_data(
    3014                                         subreq, struct tevent_req);
    3015         struct posix_lock_state *state = tevent_req_data(req, struct posix_lock_state);
    3016         NTSTATUS status;
    3017 
    3018         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    3019         TALLOC_FREE(subreq);
    3020         if (!NT_STATUS_IS_OK(status)) {
    3021                 tevent_req_nterror(req, status);
    3022                 return;
    3023         }
    3024         tevent_req_done(req);
     2837        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     2838                                         NULL, 0, NULL, NULL, 0, NULL);
     2839        tevent_req_simple_finish_ntstatus(subreq, status);
    30252840}
    30262841
     
    31232938NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
    31242939{
    3125         NTSTATUS status;
    3126 
    3127         if (tevent_req_is_nterror(req, &status)) {
    3128                 return status;
    3129         }
    3130         return NT_STATUS_OK;
     2940        return tevent_req_simple_recv_ntstatus(req);
    31312941}
    31322942
     
    32043014NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
    32053015{
    3206         NTSTATUS status;
    3207 
    3208         if (tevent_req_is_nterror(req, &status)) {
    3209                 return status;
    3210         }
    3211         return NT_STATUS_OK;
     3016        return tevent_req_simple_recv_ntstatus(req);
    32123017}
    32133018
     
    33093114        uint8_t wct;
    33103115        uint16_t *vwv = NULL;
     3116        uint8_t *inbuf;
    33113117        NTSTATUS status;
    33123118
    3313         status = cli_smb_recv(subreq, 11, &wct, &vwv, NULL, NULL);
    3314         if (!NT_STATUS_IS_OK(status)) {
    3315                 tevent_req_nterror(req, status);
     3119        status = cli_smb_recv(subreq, state, &inbuf, 11, &wct, &vwv,
     3120                              NULL, NULL);
     3121        TALLOC_FREE(subreq);
     3122        if (tevent_req_nterror(req, status)) {
    33163123                return;
    33173124        }
     
    33233130        state->write_time = make_unix_date2(vwv+4, state->zone_offset);
    33243131
    3325         TALLOC_FREE(subreq);
    33263132        tevent_req_done(req);
    33273133}
     
    34713277        uint8_t wct;
    34723278        uint16_t *vwv = NULL;
     3279        uint8_t *inbuf;
    34733280        NTSTATUS status;
    34743281
    3475         status = cli_smb_recv(subreq, 4, &wct, &vwv, NULL, NULL);
    3476         if (!NT_STATUS_IS_OK(status)) {
    3477                 tevent_req_nterror(req, status);
     3282        status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
     3283                              NULL);
     3284        TALLOC_FREE(subreq);
     3285        if (tevent_req_nterror(req, status)) {
    34783286                return;
    34793287        }
     
    34833291        state->write_time = make_unix_date3(vwv+1, state->zone_offset);
    34843292
    3485         TALLOC_FREE(subreq);
    34863293        tevent_req_done(req);
    34873294}
     
    35883395
    35893396        SSVAL(state->vwv+0, 0, fnum);
    3590         cli_put_dos_date2(cli, (char *)&state->vwv[1], 0, change_time);
    3591         cli_put_dos_date2(cli, (char *)&state->vwv[3], 0, access_time);
    3592         cli_put_dos_date2(cli, (char *)&state->vwv[5], 0, write_time);
     3397        push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
     3398                       cli->serverzone);
     3399        push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
     3400                       cli->serverzone);
     3401        push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
     3402                       cli->serverzone);
    35933403
    35943404        subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags,
     
    36073417        NTSTATUS status;
    36083418
    3609         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     3419        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    36103420        TALLOC_FREE(subreq);
    3611         if (!NT_STATUS_IS_OK(status)) {
    3612                 tevent_req_nterror(req, status);
     3421        if (tevent_req_nterror(req, status)) {
    36133422                return;
    36143423        }
     
    37013510
    37023511        SSVAL(state->vwv+0, 0, attr);
    3703         cli_put_dos_date3(cli, (char *)&state->vwv[1], 0, mtime);
     3512        push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, cli->serverzone);
    37043513
    37053514        bytes = talloc_array(state, uint8_t, 1);
     
    37413550        NTSTATUS status;
    37423551
    3743         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     3552        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    37443553        TALLOC_FREE(subreq);
    3745         if (!NT_STATUS_IS_OK(status)) {
    3746                 tevent_req_nterror(req, status);
     3554        if (tevent_req_nterror(req, status)) {
    37473555                return;
    37483556        }
     
    38523660        NTSTATUS status;
    38533661
    3854         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     3662        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    38553663        TALLOC_FREE(subreq);
    3856         if (!NT_STATUS_IS_OK(status)) {
    3857                 tevent_req_nterror(req, status);
     3664        if (tevent_req_nterror(req, status)) {
    38583665                return;
    38593666        }
     
    39653772        uint8_t wct;
    39663773        uint16_t *vwv = NULL;
     3774        uint8_t *inbuf;
    39673775        NTSTATUS status;
    39683776
    3969         status = cli_smb_recv(subreq, 4, &wct, &vwv, NULL, NULL);
    3970         if (!NT_STATUS_IS_OK(status)) {
    3971                 tevent_req_nterror(req, status);
     3777        status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
     3778                              NULL);
     3779        TALLOC_FREE(subreq);
     3780        if (tevent_req_nterror(req, status)) {
    39723781                return;
    39733782        }
     
    39753784        state->total = SVAL(vwv+0, 0);
    39763785        state->avail = SVAL(vwv+3, 0);
    3977         TALLOC_FREE(subreq);
    39783786        tevent_req_done(req);
    39793787}
     
    40973905        uint32_t num_bytes = 0;
    40983906        uint8_t *bytes = NULL;
    4099 
    4100         status = cli_smb_recv(subreq, 1, &wcnt, &vwv, &num_bytes, &bytes);
    4101         if (!NT_STATUS_IS_OK(status)) {
    4102                 TALLOC_FREE(subreq);
    4103                 tevent_req_nterror(req, status);
     3907        uint8_t *inbuf;
     3908
     3909        status = cli_smb_recv(subreq, state, &inbuf, 1, &wcnt, &vwv,
     3910                              &num_bytes, &bytes);
     3911        TALLOC_FREE(subreq);
     3912        if (tevent_req_nterror(req, status)) {
    41043913                return;
    41053914        }
    41063915
    41073916        state->fnum = SVAL(vwv+0, 0);
    4108 
    4109         TALLOC_FREE(subreq);
    41103917
    41113918        /* From W2K3, the result is just the ASCII name */
     
    41994006NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
    42004007{
    4201         memset(cli->outbuf,'\0',smb_size);
    4202         memset(cli->inbuf,'\0',smb_size);
    4203 
    4204         cli_set_message(cli->outbuf, 3, 0, True);
    4205         SCVAL(cli->outbuf,smb_com,SMBioctl);
    4206         cli_setup_packet(cli);
    4207 
    4208         SSVAL(cli->outbuf, smb_vwv0, fnum);
    4209         SSVAL(cli->outbuf, smb_vwv1, code>>16);
    4210         SSVAL(cli->outbuf, smb_vwv2, (code&0xFFFF));
    4211 
    4212         cli_send_smb(cli);
    4213         if (!cli_receive_smb(cli)) {
    4214                 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    4215         }
    4216 
    4217         if (cli_is_error(cli)) {
    4218                 return cli_nt_error(cli);
    4219         }
    4220 
     4008        uint16_t vwv[3];
     4009        NTSTATUS status;
     4010
     4011        SSVAL(vwv+0, 0, fnum);
     4012        SSVAL(vwv+1, 0, code>>16);
     4013        SSVAL(vwv+2, 0, (code&0xFFFF));
     4014
     4015        status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
     4016                         NULL, 0, NULL, NULL, NULL, NULL);
     4017        if (!NT_STATUS_IS_OK(status)) {
     4018                return status;
     4019        }
    42214020        *blob = data_blob_null;
    4222 
    42234021        return NT_STATUS_OK;
    42244022}
     
    42284026*********************************************************/
    42294027
    4230 static bool cli_set_ea(struct cli_state *cli, uint16_t setup, char *param, unsigned int param_len,
    4231                         const char *ea_name, const char *ea_val, size_t ea_len)
    4232 {
     4028static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
     4029                           uint8_t *param, unsigned int param_len,
     4030                           const char *ea_name,
     4031                           const char *ea_val, size_t ea_len)
     4032{
     4033        uint16_t setup[1];
    42334034        unsigned int data_len = 0;
    4234         char *data = NULL;
    4235         char *rparam=NULL, *rdata=NULL;
     4035        uint8_t *data = NULL;
    42364036        char *p;
    42374037        size_t ea_namelen = strlen(ea_name);
     4038        NTSTATUS status;
     4039
     4040        SSVAL(setup, 0, setup_val);
    42384041
    42394042        if (ea_namelen == 0 && ea_len == 0) {
    42404043                data_len = 4;
    4241                 data = (char *)SMB_MALLOC(data_len);
     4044                data = (uint8_t *)SMB_MALLOC(data_len);
    42424045                if (!data) {
    4243                         return False;
     4046                        return NT_STATUS_NO_MEMORY;
    42444047                }
    4245                 p = data;
     4048                p = (char *)data;
    42464049                SIVAL(p,0,data_len);
    42474050        } else {
    42484051                data_len = 4 + 4 + ea_namelen + 1 + ea_len;
    4249                 data = (char *)SMB_MALLOC(data_len);
     4052                data = (uint8_t *)SMB_MALLOC(data_len);
    42504053                if (!data) {
    4251                         return False;
     4054                        return NT_STATUS_NO_MEMORY;
    42524055                }
    4253                 p = data;
     4056                p = (char *)data;
    42544057                SIVAL(p,0,data_len);
    42554058                p += 4;
     
    42614064        }
    42624065
    4263         if (!cli_send_trans(cli, SMBtrans2,
    4264                         NULL,                        /* name */
    4265                         -1, 0,                          /* fid, flags */
    4266                         &setup, 1, 0,                   /* setup, length, max */
    4267                         param, param_len, 2,            /* param, length, max */
    4268                         data,  data_len, cli->max_xmit /* data, length, max */
    4269                         )) {
    4270                 SAFE_FREE(data);
    4271                 return False;
    4272         }
    4273 
    4274         if (!cli_receive_trans(cli, SMBtrans2,
    4275                         &rparam, &param_len,
    4276                         &rdata, &data_len)) {
    4277                         SAFE_FREE(data);
    4278                 return false;
    4279         }
    4280 
     4066        status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
     4067                           setup, 1, 0,
     4068                           param, param_len, 2,
     4069                           data,  data_len, cli->max_xmit,
     4070                           NULL,
     4071                           NULL, 0, NULL, /* rsetup */
     4072                           NULL, 0, NULL, /* rparam */
     4073                           NULL, 0, NULL); /* rdata */
    42814074        SAFE_FREE(data);
    4282         SAFE_FREE(rdata);
    4283         SAFE_FREE(rparam);
    4284 
    4285         return True;
     4075        return status;
    42864076}
    42874077
     
    42904080*********************************************************/
    42914081
    4292 bool cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
    4293 {
    4294         uint16_t setup = TRANSACT2_SETPATHINFO;
     4082NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
     4083                         const char *ea_name, const char *ea_val,
     4084                         size_t ea_len)
     4085{
    42954086        unsigned int param_len = 0;
    4296         char *param;
     4087        uint8_t *param;
    42974088        size_t srclen = 2*(strlen(path)+1);
    42984089        char *p;
    4299         bool ret;
    4300 
    4301         param = SMB_MALLOC_ARRAY(char, 6+srclen+2);
     4090        NTSTATUS status;
     4091
     4092        param = SMB_MALLOC_ARRAY(uint8_t, 6+srclen+2);
    43024093        if (!param) {
    4303                 return false;
     4094                return NT_STATUS_NO_MEMORY;
    43044095        }
    43054096        memset(param, '\0', 6);
    43064097        SSVAL(param,0,SMB_INFO_SET_EA);
    4307         p = &param[6];
     4098        p = (char *)(&param[6]);
    43084099
    43094100        p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
    43104101        param_len = PTR_DIFF(p, param);
    43114102
    4312         ret = cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
     4103        status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
     4104                            ea_name, ea_val, ea_len);
    43134105        SAFE_FREE(param);
    4314         return ret;
     4106        return status;
    43154107}
    43164108
     
    43194111*********************************************************/
    43204112
    4321 bool cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum, const char *ea_name, const char *ea_val, size_t ea_len)
    4322 {
    4323         char param[6];
    4324         uint16_t setup = TRANSACT2_SETFILEINFO;
     4113NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
     4114                         const char *ea_name, const char *ea_val,
     4115                         size_t ea_len)
     4116{
     4117        uint8_t param[6];
    43254118
    43264119        memset(param, 0, 6);
     
    43284121        SSVAL(param,2,SMB_INFO_SET_EA);
    43294122
    4330         return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
     4123        return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
     4124                          ea_name, ea_val, ea_len);
    43314125}
    43324126
     
    43354129*********************************************************/
    43364130
    4337 static bool cli_get_ea_list(struct cli_state *cli,
    4338                 uint16_t setup, char *param, unsigned int param_len,
    4339                 TALLOC_CTX *ctx,
    4340                 size_t *pnum_eas,
    4341                 struct ea_struct **pea_list)
    4342 {
    4343         unsigned int data_len = 0;
    4344         unsigned int rparam_len, rdata_len;
    4345         char *rparam=NULL, *rdata=NULL;
    4346         char *p;
     4131static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
     4132                          size_t rdata_len,
     4133                          size_t *pnum_eas, struct ea_struct **pea_list)
     4134{
     4135        struct ea_struct *ea_list = NULL;
     4136        size_t num_eas;
    43474137        size_t ea_size;
    4348         size_t num_eas;
    4349         bool ret = False;
    4350         struct ea_struct *ea_list;
    4351 
    4352         *pnum_eas = 0;
    4353         if (pea_list) {
    4354                 *pea_list = NULL;
    4355         }
    4356 
    4357         if (!cli_send_trans(cli, SMBtrans2,
    4358                         NULL,           /* Name */
    4359                         -1, 0,          /* fid, flags */
    4360                         &setup, 1, 0,   /* setup, length, max */
    4361                         param, param_len, 10, /* param, length, max */
    4362                         NULL, data_len, cli->max_xmit /* data, length, max */
    4363                                 )) {
    4364                 return False;
    4365         }
    4366 
    4367         if (!cli_receive_trans(cli, SMBtrans2,
    4368                         &rparam, &rparam_len,
    4369                         &rdata, &rdata_len)) {
    4370                 return False;
    4371         }
    4372 
    4373         if (!rdata || rdata_len < 4) {
    4374                 goto out;
     4138        const uint8_t *p;
     4139
     4140        if (rdata_len < 4) {
     4141                return false;
    43754142        }
    43764143
    43774144        ea_size = (size_t)IVAL(rdata,0);
    43784145        if (ea_size > rdata_len) {
    4379                 goto out;
     4146                return false;
    43804147        }
    43814148
    43824149        if (ea_size == 0) {
    43834150                /* No EA's present. */
    4384                 ret = True;
    4385                 goto out;
     4151                *pnum_eas = 0;
     4152                *pea_list = NULL;
     4153                return true;
    43864154        }
    43874155
     
    43944162                unsigned int ea_valuelen = SVAL(p,2);
    43954163                if (ea_namelen == 0) {
    4396                         goto out;
     4164                        return false;
    43974165                }
    43984166                if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
    4399                         goto out;
     4167                        return false;
    44004168                }
    44014169                ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
     
    44044172
    44054173        if (num_eas == 0) {
    4406                 ret = True;
    4407                 goto out;
     4174                *pnum_eas = 0;
     4175                *pea_list = NULL;
     4176                return true;
    44084177        }
    44094178
     
    44114180        if (!pea_list) {
    44124181                /* Caller only wants number of EA's. */
    4413                 ret = True;
    4414                 goto out;
     4182                return true;
    44154183        }
    44164184
    44174185        ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
    44184186        if (!ea_list) {
    4419                 goto out;
     4187                return false;
    44204188        }
    44214189
     
    44324200                unix_ea_name[0] = '\0';
    44334201                pull_ascii_fstring(unix_ea_name, p + 4);
    4434                 ea->name = talloc_strdup(ctx, unix_ea_name);
     4202                ea->name = talloc_strdup(ea_list, unix_ea_name);
     4203                if (!ea->name) {
     4204                        goto fail;
     4205                }
    44354206                /* Ensure the value is null terminated (in case it's a string). */
    4436                 ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
     4207                ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
    44374208                if (!ea->value.data) {
    4438                         goto out;
     4209                        goto fail;
    44394210                }
    44404211                if (ea_valuelen) {
     
    44474218
    44484219        *pea_list = ea_list;
    4449         ret = True;
    4450 
    4451  out :
    4452 
    4453         SAFE_FREE(rdata);
    4454         SAFE_FREE(rparam);
    4455         return ret;
     4220        return true;
     4221
     4222fail:
     4223        TALLOC_FREE(ea_list);
     4224        return false;
    44564225}
    44574226
     
    44604229*********************************************************/
    44614230
    4462 bool cli_get_ea_list_path(struct cli_state *cli, const char *path,
     4231struct cli_get_ea_list_path_state {
     4232        uint32_t num_data;
     4233        uint8_t *data;
     4234};
     4235
     4236static void cli_get_ea_list_path_done(struct tevent_req *subreq);
     4237
     4238struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
     4239                                             struct tevent_context *ev,
     4240                                             struct cli_state *cli,
     4241                                             const char *fname)
     4242{
     4243        struct tevent_req *req, *subreq;
     4244        struct cli_get_ea_list_path_state *state;
     4245
     4246        req = tevent_req_create(mem_ctx, &state,
     4247                                struct cli_get_ea_list_path_state);
     4248        if (req == NULL) {
     4249                return NULL;
     4250        }
     4251        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     4252                                    SMB_INFO_QUERY_ALL_EAS, 4,
     4253                                    cli->max_xmit);
     4254        if (tevent_req_nomem(subreq, req)) {
     4255                return tevent_req_post(req, ev);
     4256        }
     4257        tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
     4258        return req;
     4259}
     4260
     4261static void cli_get_ea_list_path_done(struct tevent_req *subreq)
     4262{
     4263        struct tevent_req *req = tevent_req_callback_data(
     4264                                subreq, struct tevent_req);
     4265        struct cli_get_ea_list_path_state *state = tevent_req_data(
     4266                req, struct cli_get_ea_list_path_state);
     4267        NTSTATUS status;
     4268
     4269        status = cli_qpathinfo_recv(subreq, state, &state->data,
     4270                                    &state->num_data);
     4271        TALLOC_FREE(subreq);
     4272        if (tevent_req_nterror(req, status)) {
     4273                return;
     4274        }
     4275        tevent_req_done(req);
     4276}
     4277
     4278NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     4279                                   size_t *pnum_eas, struct ea_struct **peas)
     4280{
     4281        struct cli_get_ea_list_path_state *state = tevent_req_data(
     4282                req, struct cli_get_ea_list_path_state);
     4283        NTSTATUS status;
     4284
     4285        if (tevent_req_is_nterror(req, &status)) {
     4286                return status;
     4287        }
     4288        if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
     4289                           pnum_eas, peas)) {
     4290                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     4291        }
     4292        return NT_STATUS_OK;
     4293}
     4294
     4295NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
    44634296                TALLOC_CTX *ctx,
    44644297                size_t *pnum_eas,
    44654298                struct ea_struct **pea_list)
    44664299{
    4467         uint16_t setup = TRANSACT2_QPATHINFO;
    4468         unsigned int param_len = 0;
    4469         char *param;
    4470         char *p;
    4471         size_t srclen = 2*(strlen(path)+1);
    4472         bool ret;
    4473 
    4474         param = SMB_MALLOC_ARRAY(char, 6+srclen+2);
    4475         if (!param) {
    4476                 return false;
    4477         }
    4478         p = param;
    4479         memset(p, 0, 6);
    4480         SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
    4481         p += 6;
    4482         p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
    4483         param_len = PTR_DIFF(p, param);
    4484 
    4485         ret = cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
    4486         SAFE_FREE(param);
    4487         return ret;
    4488 }
    4489 
    4490 /*********************************************************
    4491  Get an extended attribute list from an fnum.
    4492 *********************************************************/
    4493 
    4494 bool cli_get_ea_list_fnum(struct cli_state *cli, uint16_t fnum,
    4495                 TALLOC_CTX *ctx,
    4496                 size_t *pnum_eas,
    4497                 struct ea_struct **pea_list)
    4498 {
    4499         uint16_t setup = TRANSACT2_QFILEINFO;
    4500         char param[6];
    4501 
    4502         memset(param, 0, 6);
    4503         SSVAL(param,0,fnum);
    4504         SSVAL(param,2,SMB_INFO_SET_EA);
    4505 
    4506         return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
     4300        TALLOC_CTX *frame = talloc_stackframe();
     4301        struct event_context *ev = NULL;
     4302        struct tevent_req *req = NULL;
     4303        NTSTATUS status = NT_STATUS_NO_MEMORY;
     4304
     4305        if (cli_has_async_calls(cli)) {
     4306                /*
     4307                 * Can't use sync call while an async call is in flight
     4308                 */
     4309                status = NT_STATUS_INVALID_PARAMETER;
     4310                goto fail;
     4311        }
     4312        ev = event_context_init(frame);
     4313        if (ev == NULL) {
     4314                goto fail;
     4315        }
     4316        req = cli_get_ea_list_path_send(frame, ev, cli, path);
     4317        if (req == NULL) {
     4318                goto fail;
     4319        }
     4320        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     4321                goto fail;
     4322        }
     4323        status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
     4324 fail:
     4325        TALLOC_FREE(frame);
     4326        if (!NT_STATUS_IS_OK(status)) {
     4327                cli_set_error(cli, status);
     4328        }
     4329        return status;
    45074330}
    45084331
     
    45534376#if defined(O_DIRECTORY)
    45544377        if (flags & O_DIRECTORY) {
    4555                 ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
    45564378                ret |= SMB_O_DIRECTORY;
    45574379        }
     
    45804402        uint32_t num_data;
    45814403
    4582         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, &data, &num_data);
     4404        status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
     4405                                NULL, 0, NULL, &data, 12, &num_data);
    45834406        TALLOC_FREE(subreq);
    4584         if (!NT_STATUS_IS_OK(status)) {
    4585                 tevent_req_nterror(req, status);
    4586                 return;
    4587         }
    4588         if (num_data < 12) {
    4589                 tevent_req_nterror(req, status);
     4407        if (tevent_req_nterror(req, status)) {
    45904408                return;
    45914409        }
     
    46314449        /* Setup data words. */
    46324450        if (is_dir) {
    4633                 wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
    46344451                wire_flags |= SMB_O_DIRECTORY;
    46354452        }
     
    47544571NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
    47554572{
    4756         NTSTATUS status;
    4757 
    4758         if (tevent_req_is_nterror(req, &status)) {
    4759                 return status;
    4760         }
    4761         return NT_STATUS_OK;
     4573        return tevent_req_simple_recv_ntstatus(req);
    47624574}
    47634575
     
    48124624****************************************************************************/
    48134625
    4814 struct unlink_state {
    4815         uint16_t setup;
     4626struct cli_posix_unlink_internal_state {
    48164627        uint8_t data[2];
    48174628};
    48184629
    4819 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
    4820 {
    4821         struct tevent_req *req = tevent_req_callback_data(
    4822                                 subreq, struct tevent_req);
    4823         struct unlink_state *state = tevent_req_data(req, struct unlink_state);
    4824         NTSTATUS status;
    4825 
    4826         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL);
    4827         TALLOC_FREE(subreq);
    4828         if (!NT_STATUS_IS_OK(status)) {
    4829                 tevent_req_nterror(req, status);
    4830                 return;
    4831         }
    4832         tevent_req_done(req);
    4833 }
     4630static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
    48344631
    48354632static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
     
    48374634                                        struct cli_state *cli,
    48384635                                        const char *fname,
    4839                                         bool is_dir)
     4636                                        uint16_t level)
    48404637{
    48414638        struct tevent_req *req = NULL, *subreq = NULL;
    4842         struct unlink_state *state = NULL;
    4843         uint8_t *param = NULL;
    4844 
    4845         req = tevent_req_create(mem_ctx, &state, struct unlink_state);
     4639        struct cli_posix_unlink_internal_state *state = NULL;
     4640
     4641        req = tevent_req_create(mem_ctx, &state,
     4642                                struct cli_posix_unlink_internal_state);
    48464643        if (req == NULL) {
    48474644                return NULL;
    48484645        }
    48494646
    4850         /* Setup setup word. */
    4851         SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
    4852 
    4853         /* Setup param array. */
    4854         param = talloc_array(state, uint8_t, 6);
    4855         if (tevent_req_nomem(param, req)) {
    4856                 return tevent_req_post(req, ev);
    4857         }
    4858         memset(param, '\0', 6);
    4859         SSVAL(param, 0, SMB_POSIX_PATH_UNLINK);
    4860 
    4861         param = trans2_bytes_push_str(param, cli_ucs2(cli), fname,
    4862                                    strlen(fname)+1, NULL);
    4863 
    4864         if (tevent_req_nomem(param, req)) {
    4865                 return tevent_req_post(req, ev);
    4866         }
    4867 
    48684647        /* Setup data word. */
    4869         SSVAL(state->data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
    4870                         SMB_POSIX_UNLINK_FILE_TARGET);
    4871 
    4872         subreq = cli_trans_send(state,                  /* mem ctx. */
    4873                                 ev,                     /* event ctx. */
    4874                                 cli,                    /* cli_state. */
    4875                                 SMBtrans2,              /* cmd. */
    4876                                 NULL,                   /* pipe name. */
    4877                                 -1,                     /* fid. */
    4878                                 0,                      /* function. */
    4879                                 0,                      /* flags. */
    4880                                 &state->setup,          /* setup. */
    4881                                 1,                      /* num setup uint16_t words. */
    4882                                 0,                      /* max returned setup. */
    4883                                 param,                  /* param. */
    4884                                 talloc_get_size(param), /* num param. */
    4885                                 2,                      /* max returned param. */
    4886                                 state->data,            /* data. */
    4887                                 2,                      /* num data. */
    4888                                 0);                     /* max returned data. */
    4889 
     4648        SSVAL(state->data, 0, level);
     4649
     4650        subreq = cli_setpathinfo_send(state, ev, cli,
     4651                                      SMB_POSIX_PATH_UNLINK,
     4652                                      fname,
     4653                                      state->data, sizeof(state->data));
    48904654        if (tevent_req_nomem(subreq, req)) {
    48914655                return tevent_req_post(req, ev);
     
    48934657        tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
    48944658        return req;
     4659}
     4660
     4661static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
     4662{
     4663        NTSTATUS status = cli_setpathinfo_recv(subreq);
     4664        tevent_req_simple_finish_ntstatus(subreq, status);
    48954665}
    48964666
     
    49004670                                        const char *fname)
    49014671{
    4902         return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, false);
     4672        return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname,
     4673                                              SMB_POSIX_UNLINK_FILE_TARGET);
    49034674}
    49044675
    49054676NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
    49064677{
    4907         NTSTATUS status;
    4908 
    4909         if (tevent_req_is_nterror(req, &status)) {
    4910                 return status;
    4911         }
    4912         return NT_STATUS_OK;
     4678        return tevent_req_simple_recv_ntstatus(req);
    49134679}
    49144680
     
    49714737                                        const char *fname)
    49724738{
    4973         return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, true);
     4739        return cli_posix_unlink_internal_send(
     4740                mem_ctx, ev, cli, fname,
     4741                SMB_POSIX_UNLINK_DIRECTORY_TARGET);
    49744742}
    49754743
    49764744NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
    49774745{
    4978         NTSTATUS status;
    4979 
    4980         if (tevent_req_is_nterror(req, &status)) {
    4981                 return status;
    4982         }
    4983         return NT_STATUS_OK;
     4746        return tevent_req_simple_recv_ntstatus(req);
    49844747}
    49854748
     
    50944857        uint8_t *params;
    50954858        uint32_t i, ofs, num_params;
    5096 
    5097         status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL,
    5098                                 &params, &num_params, NULL, NULL);
     4859        uint16_t flags2;
     4860
     4861        status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
     4862                                &params, 0, &num_params, NULL, 0, NULL);
    50994863        TALLOC_FREE(subreq);
    5100         if (!NT_STATUS_IS_OK(status)) {
     4864        if (tevent_req_nterror(req, status)) {
    51014865                DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
    5102                 tevent_req_nterror(req, status);
    51034866                return;
    51044867        }
     
    51404903
    51414904                state->changes[i].action = IVAL(params, ofs+4);
    5142                 ret = clistr_pull_talloc(params, (char *)params, &name,
    5143                                          params+ofs+12, len,
     4905                ret = clistr_pull_talloc(params, (char *)params, flags2,
     4906                                         &name, params+ofs+12, len,
    51444907                                         STR_TERMINATE|STR_UNICODE);
    51454908                if (ret == -1) {
     
    51724935        return NT_STATUS_OK;
    51734936}
     4937
     4938struct cli_qpathinfo_state {
     4939        uint8_t *param;
     4940        uint8_t *data;
     4941        uint16_t setup[1];
     4942        uint32_t min_rdata;
     4943        uint8_t *rdata;
     4944        uint32_t num_rdata;
     4945};
     4946
     4947static void cli_qpathinfo_done(struct tevent_req *subreq);
     4948
     4949struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
     4950                                      struct tevent_context *ev,
     4951                                      struct cli_state *cli, const char *fname,
     4952                                      uint16_t level, uint32_t min_rdata,
     4953                                      uint32_t max_rdata)
     4954{
     4955        struct tevent_req *req, *subreq;
     4956        struct cli_qpathinfo_state *state;
     4957
     4958        req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
     4959        if (req == NULL) {
     4960                return NULL;
     4961        }
     4962        state->min_rdata = min_rdata;
     4963        SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
     4964
     4965        state->param = talloc_zero_array(state, uint8_t, 6);
     4966        if (tevent_req_nomem(state->param, req)) {
     4967                return tevent_req_post(req, ev);
     4968        }
     4969        SSVAL(state->param, 0, level);
     4970        state->param = trans2_bytes_push_str(
     4971                state->param, cli_ucs2(cli), fname, strlen(fname)+1, NULL);
     4972        if (tevent_req_nomem(state->param, req)) {
     4973                return tevent_req_post(req, ev);
     4974        }
     4975
     4976        subreq = cli_trans_send(
     4977                state,                  /* mem ctx. */
     4978                ev,                     /* event ctx. */
     4979                cli,                    /* cli_state. */
     4980                SMBtrans2,              /* cmd. */
     4981                NULL,                   /* pipe name. */
     4982                -1,                     /* fid. */
     4983                0,                      /* function. */
     4984                0,                      /* flags. */
     4985                state->setup,           /* setup. */
     4986                1,                      /* num setup uint16_t words. */
     4987                0,                      /* max returned setup. */
     4988                state->param,           /* param. */
     4989                talloc_get_size(state->param),  /* num param. */
     4990                2,                      /* max returned param. */
     4991                NULL,                   /* data. */
     4992                0,                      /* num data. */
     4993                max_rdata);             /* max returned data. */
     4994
     4995        if (tevent_req_nomem(subreq, req)) {
     4996                return tevent_req_post(req, ev);
     4997        }
     4998        tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
     4999        return req;
     5000}
     5001
     5002static void cli_qpathinfo_done(struct tevent_req *subreq)
     5003{
     5004        struct tevent_req *req = tevent_req_callback_data(
     5005                subreq, struct tevent_req);
     5006        struct cli_qpathinfo_state *state = tevent_req_data(
     5007                req, struct cli_qpathinfo_state);
     5008        NTSTATUS status;
     5009
     5010        status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
     5011                                NULL, 0, NULL,
     5012                                &state->rdata, state->min_rdata,
     5013                                &state->num_rdata);
     5014        if (tevent_req_nterror(req, status)) {
     5015                return;
     5016        }
     5017        tevent_req_done(req);
     5018}
     5019
     5020NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     5021                            uint8_t **rdata, uint32_t *num_rdata)
     5022{
     5023        struct cli_qpathinfo_state *state = tevent_req_data(
     5024                req, struct cli_qpathinfo_state);
     5025        NTSTATUS status;
     5026
     5027        if (tevent_req_is_nterror(req, &status)) {
     5028                return status;
     5029        }
     5030        if (rdata != NULL) {
     5031                *rdata = talloc_move(mem_ctx, &state->rdata);
     5032        } else {
     5033                TALLOC_FREE(state->rdata);
     5034        }
     5035        if (num_rdata != NULL) {
     5036                *num_rdata = state->num_rdata;
     5037        }
     5038        return NT_STATUS_OK;
     5039}
     5040
     5041NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     5042                       const char *fname, uint16_t level, uint32_t min_rdata,
     5043                       uint32_t max_rdata,
     5044                       uint8_t **rdata, uint32_t *num_rdata)
     5045{
     5046        TALLOC_CTX *frame = talloc_stackframe();
     5047        struct event_context *ev;
     5048        struct tevent_req *req;
     5049        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5050
     5051        if (cli_has_async_calls(cli)) {
     5052                /*
     5053                 * Can't use sync call while an async call is in flight
     5054                 */
     5055                status = NT_STATUS_INVALID_PARAMETER;
     5056                goto fail;
     5057        }
     5058        ev = event_context_init(frame);
     5059        if (ev == NULL) {
     5060                goto fail;
     5061        }
     5062        req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
     5063                                 max_rdata);
     5064        if (req == NULL) {
     5065                goto fail;
     5066        }
     5067        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5068                goto fail;
     5069        }
     5070        status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
     5071 fail:
     5072        TALLOC_FREE(frame);
     5073        if (!NT_STATUS_IS_OK(status)) {
     5074                cli_set_error(cli, status);
     5075        }
     5076        return status;
     5077}
     5078
     5079struct cli_qfileinfo_state {
     5080        uint16_t setup[1];
     5081        uint8_t param[4];
     5082        uint8_t *data;
     5083        uint32_t min_rdata;
     5084        uint8_t *rdata;
     5085        uint32_t num_rdata;
     5086};
     5087
     5088static void cli_qfileinfo_done(struct tevent_req *subreq);
     5089
     5090struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
     5091                                      struct tevent_context *ev,
     5092                                      struct cli_state *cli, uint16_t fnum,
     5093                                      uint16_t level, uint32_t min_rdata,
     5094                                      uint32_t max_rdata)
     5095{
     5096        struct tevent_req *req, *subreq;
     5097        struct cli_qfileinfo_state *state;
     5098
     5099        req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
     5100        if (req == NULL) {
     5101                return NULL;
     5102        }
     5103        state->min_rdata = min_rdata;
     5104        SSVAL(state->param, 0, fnum);
     5105        SSVAL(state->param, 2, level);
     5106        SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
     5107
     5108        subreq = cli_trans_send(
     5109                state,                  /* mem ctx. */
     5110                ev,                     /* event ctx. */
     5111                cli,                    /* cli_state. */
     5112                SMBtrans2,              /* cmd. */
     5113                NULL,                   /* pipe name. */
     5114                -1,                     /* fid. */
     5115                0,                      /* function. */
     5116                0,                      /* flags. */
     5117                state->setup,           /* setup. */
     5118                1,                      /* num setup uint16_t words. */
     5119                0,                      /* max returned setup. */
     5120                state->param,           /* param. */
     5121                sizeof(state->param),   /* num param. */
     5122                2,                      /* max returned param. */
     5123                NULL,                   /* data. */
     5124                0,                      /* num data. */
     5125                max_rdata);             /* max returned data. */
     5126
     5127        if (tevent_req_nomem(subreq, req)) {
     5128                return tevent_req_post(req, ev);
     5129        }
     5130        tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
     5131        return req;
     5132}
     5133
     5134static void cli_qfileinfo_done(struct tevent_req *subreq)
     5135{
     5136        struct tevent_req *req = tevent_req_callback_data(
     5137                subreq, struct tevent_req);
     5138        struct cli_qfileinfo_state *state = tevent_req_data(
     5139                req, struct cli_qfileinfo_state);
     5140        NTSTATUS status;
     5141
     5142        status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
     5143                                NULL, 0, NULL,
     5144                                &state->rdata, state->min_rdata,
     5145                                &state->num_rdata);
     5146        if (tevent_req_nterror(req, status)) {
     5147                return;
     5148        }
     5149        tevent_req_done(req);
     5150}
     5151
     5152NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     5153                            uint8_t **rdata, uint32_t *num_rdata)
     5154{
     5155        struct cli_qfileinfo_state *state = tevent_req_data(
     5156                req, struct cli_qfileinfo_state);
     5157        NTSTATUS status;
     5158
     5159        if (tevent_req_is_nterror(req, &status)) {
     5160                return status;
     5161        }
     5162        if (rdata != NULL) {
     5163                *rdata = talloc_move(mem_ctx, &state->rdata);
     5164        } else {
     5165                TALLOC_FREE(state->rdata);
     5166        }
     5167        if (num_rdata != NULL) {
     5168                *num_rdata = state->num_rdata;
     5169        }
     5170        return NT_STATUS_OK;
     5171}
     5172
     5173NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     5174                       uint16_t fnum, uint16_t level, uint32_t min_rdata,
     5175                       uint32_t max_rdata,
     5176                       uint8_t **rdata, uint32_t *num_rdata)
     5177{
     5178        TALLOC_CTX *frame = talloc_stackframe();
     5179        struct event_context *ev;
     5180        struct tevent_req *req;
     5181        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5182
     5183        if (cli_has_async_calls(cli)) {
     5184                /*
     5185                 * Can't use sync call while an async call is in flight
     5186                 */
     5187                status = NT_STATUS_INVALID_PARAMETER;
     5188                goto fail;
     5189        }
     5190        ev = event_context_init(frame);
     5191        if (ev == NULL) {
     5192                goto fail;
     5193        }
     5194        req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
     5195                                 max_rdata);
     5196        if (req == NULL) {
     5197                goto fail;
     5198        }
     5199        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5200                goto fail;
     5201        }
     5202        status = cli_qfileinfo_recv(req, mem_ctx, rdata, num_rdata);
     5203 fail:
     5204        TALLOC_FREE(frame);
     5205        if (!NT_STATUS_IS_OK(status)) {
     5206                cli_set_error(cli, status);
     5207        }
     5208        return status;
     5209}
     5210
     5211struct cli_flush_state {
     5212        uint16_t vwv[1];
     5213};
     5214
     5215static void cli_flush_done(struct tevent_req *subreq);
     5216
     5217struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
     5218                                  struct event_context *ev,
     5219                                  struct cli_state *cli,
     5220                                  uint16_t fnum)
     5221{
     5222        struct tevent_req *req, *subreq;
     5223        struct cli_flush_state *state;
     5224
     5225        req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
     5226        if (req == NULL) {
     5227                return NULL;
     5228        }
     5229        SSVAL(state->vwv + 0, 0, fnum);
     5230
     5231        subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 1, state->vwv,
     5232                              0, NULL);
     5233        if (tevent_req_nomem(subreq, req)) {
     5234                return tevent_req_post(req, ev);
     5235        }
     5236        tevent_req_set_callback(subreq, cli_flush_done, req);
     5237        return req;
     5238}
     5239
     5240static void cli_flush_done(struct tevent_req *subreq)
     5241{
     5242        struct tevent_req *req = tevent_req_callback_data(
     5243                subreq, struct tevent_req);
     5244        NTSTATUS status;
     5245
     5246        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
     5247        TALLOC_FREE(subreq);
     5248        if (tevent_req_nterror(req, status)) {
     5249                return;
     5250        }
     5251        tevent_req_done(req);
     5252}
     5253
     5254NTSTATUS cli_flush_recv(struct tevent_req *req)
     5255{
     5256        return tevent_req_simple_recv_ntstatus(req);
     5257}
     5258
     5259NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
     5260{
     5261        TALLOC_CTX *frame = talloc_stackframe();
     5262        struct event_context *ev;
     5263        struct tevent_req *req;
     5264        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5265
     5266        if (cli_has_async_calls(cli)) {
     5267                /*
     5268                 * Can't use sync call while an async call is in flight
     5269                 */
     5270                status = NT_STATUS_INVALID_PARAMETER;
     5271                goto fail;
     5272        }
     5273        ev = event_context_init(frame);
     5274        if (ev == NULL) {
     5275                goto fail;
     5276        }
     5277        req = cli_flush_send(frame, ev, cli, fnum);
     5278        if (req == NULL) {
     5279                goto fail;
     5280        }
     5281        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5282                goto fail;
     5283        }
     5284        status = cli_flush_recv(req);
     5285 fail:
     5286        TALLOC_FREE(frame);
     5287        if (!NT_STATUS_IS_OK(status)) {
     5288                cli_set_error(cli, status);
     5289        }
     5290        return status;
     5291}
     5292
     5293struct cli_shadow_copy_data_state {
     5294        uint16_t setup[4];
     5295        uint8_t *data;
     5296        uint32_t num_data;
     5297        bool get_names;
     5298};
     5299
     5300static void cli_shadow_copy_data_done(struct tevent_req *subreq);
     5301
     5302struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
     5303                                             struct tevent_context *ev,
     5304                                             struct cli_state *cli,
     5305                                             uint16_t fnum,
     5306                                             bool get_names)
     5307{
     5308        struct tevent_req *req, *subreq;
     5309        struct cli_shadow_copy_data_state *state;
     5310        uint32_t ret_size;
     5311
     5312        req = tevent_req_create(mem_ctx, &state,
     5313                                struct cli_shadow_copy_data_state);
     5314        if (req == NULL) {
     5315                return NULL;
     5316        }
     5317        state->get_names = get_names;
     5318        ret_size = get_names ? cli->max_xmit : 16;
     5319
     5320        SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
     5321        SSVAL(state->setup + 2, 0, fnum);
     5322        SCVAL(state->setup + 3, 0, 0); /* isFsctl */
     5323        SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
     5324
     5325        subreq = cli_trans_send(
     5326                state, ev, cli, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
     5327                state->setup, ARRAY_SIZE(state->setup), 0,
     5328                NULL, 0, 0,
     5329                NULL, 0, ret_size);
     5330        if (tevent_req_nomem(subreq, req)) {
     5331                return tevent_req_post(req, ev);
     5332        }
     5333        tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
     5334        return req;
     5335}
     5336
     5337static void cli_shadow_copy_data_done(struct tevent_req *subreq)
     5338{
     5339        struct tevent_req *req = tevent_req_callback_data(
     5340                subreq, struct tevent_req);
     5341        struct cli_shadow_copy_data_state *state = tevent_req_data(
     5342                req, struct cli_shadow_copy_data_state);
     5343        NTSTATUS status;
     5344
     5345        status = cli_trans_recv(subreq, state, NULL,
     5346                                NULL, 0, NULL, /* setup */
     5347                                NULL, 0, NULL, /* param */
     5348                                &state->data, 12, &state->num_data);
     5349        TALLOC_FREE(subreq);
     5350        if (tevent_req_nterror(req, status)) {
     5351                return;
     5352        }
     5353        tevent_req_done(req);
     5354}
     5355
     5356NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     5357                                   char ***pnames, int *pnum_names)
     5358{
     5359        struct cli_shadow_copy_data_state *state = tevent_req_data(
     5360                req, struct cli_shadow_copy_data_state);
     5361        char **names;
     5362        int i, num_names;
     5363        uint32_t dlength;
     5364        NTSTATUS status;
     5365
     5366        if (tevent_req_is_nterror(req, &status)) {
     5367                return status;
     5368        }
     5369        num_names = IVAL(state->data, 4);
     5370        dlength = IVAL(state->data, 8);
     5371
     5372        if (!state->get_names) {
     5373                *pnum_names = num_names;
     5374                return NT_STATUS_OK;
     5375        }
     5376
     5377        if (dlength+12 > state->num_data) {
     5378                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     5379        }
     5380        names = talloc_array(mem_ctx, char *, num_names);
     5381        if (names == NULL) {
     5382                return NT_STATUS_NO_MEMORY;
     5383        }
     5384
     5385        for (i=0; i<num_names; i++) {
     5386                bool ret;
     5387                uint8_t *src;
     5388                size_t converted_size;
     5389
     5390                src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
     5391                ret = convert_string_talloc(
     5392                        names, CH_UTF16LE, CH_UNIX,
     5393                        src, 2 * sizeof(SHADOW_COPY_LABEL),
     5394                        &names[i], &converted_size, True);
     5395                if (!ret) {
     5396                        TALLOC_FREE(names);
     5397                        return NT_STATUS_INVALID_NETWORK_RESPONSE;
     5398                }
     5399        }
     5400        *pnum_names = num_names;
     5401        *pnames = names;
     5402        return NT_STATUS_OK;
     5403}
     5404
     5405NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     5406                              uint16_t fnum, bool get_names,
     5407                              char ***pnames, int *pnum_names)
     5408{
     5409        TALLOC_CTX *frame = talloc_stackframe();
     5410        struct event_context *ev;
     5411        struct tevent_req *req;
     5412        NTSTATUS status = NT_STATUS_NO_MEMORY;
     5413
     5414        if (cli_has_async_calls(cli)) {
     5415                /*
     5416                 * Can't use sync call while an async call is in flight
     5417                 */
     5418                status = NT_STATUS_INVALID_PARAMETER;
     5419                goto fail;
     5420        }
     5421        ev = event_context_init(frame);
     5422        if (ev == NULL) {
     5423                goto fail;
     5424        }
     5425        req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
     5426        if (req == NULL) {
     5427                goto fail;
     5428        }
     5429        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     5430                goto fail;
     5431        }
     5432        status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);
     5433 fail:
     5434        TALLOC_FREE(frame);
     5435        if (!NT_STATUS_IS_OK(status)) {
     5436                cli_set_error(cli, status);
     5437        }
     5438        return status;
     5439}
  • vendor/current/source3/libsmb/clifsinfo.c

    r414 r740  
    44   Copyright (C) Stefan (metze) Metzmacher      2003
    55   Copyright (C) Jeremy Allison 2007
    6    
     6
    77   This program is free software; you can redistribute it and/or modify
    88   it under the terms of the GNU General Public License as published by
    99   the Free Software Foundation; either version 3 of the License, or
    1010   (at your option) any later version.
    11    
     11
    1212   This program is distributed in the hope that it will be useful,
    1313   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1414   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1515   GNU General Public License for more details.
    16    
     16
    1717   You should have received a copy of the GNU General Public License
    1818   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2020
    2121#include "includes.h"
     22#include "libsmb/libsmb.h"
    2223#include "../libcli/auth/spnego.h"
     24#include "../libcli/auth/ntlmssp.h"
     25#include "../lib/util/tevent_ntstatus.h"
     26#include "async_smb.h"
     27#include "smb_crypt.h"
     28#include "trans2.h"
    2329
    2430/****************************************************************************
     
    2733
    2834struct cli_unix_extensions_version_state {
     35        struct cli_state *cli;
    2936        uint16_t setup[1];
    3037        uint8_t param[2];
     
    4754                return NULL;
    4855        }
     56        state->cli = cli;
    4957        SSVAL(state->setup, 0, TRANSACT2_QFSINFO);
    5058        SSVAL(state->param, 0, SMB_QUERY_CIFS_UNIX_INFO);
     
    7280        NTSTATUS status;
    7381
    74         status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL,
    75                                 &data, &num_data);
     82        status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
     83                                NULL, 0, NULL, &data, 12, &num_data);
    7684        TALLOC_FREE(subreq);
    7785        if (!NT_STATUS_IS_OK(status)) {
    7886                tevent_req_nterror(req, status);
    79                 return;
    80         }
    81         if (num_data < 12) {
    82                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    8387                return;
    8488        }
     
    108112        *pcaplow = state->caplow;
    109113        *pcaphigh = state->caphigh;
     114        state->cli->server_posix_capabilities = *pcaplow;
    110115        return NT_STATUS_OK;
    111116}
     
    147152        status = cli_unix_extensions_version_recv(req, pmajor, pminor, pcaplow,
    148153                                                  pcaphigh);
    149         if (NT_STATUS_IS_OK(status)) {
    150                 cli->posix_capabilities = *pcaplow;
    151         }
    152154 fail:
    153155        TALLOC_FREE(frame);
     
    162164****************************************************************************/
    163165
    164 bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, uint16 minor,
    165                                         uint32 caplow, uint32 caphigh)
    166 {
    167         bool ret = False;
    168         uint16 setup;
    169         char param[4];
    170         char data[12];
    171         char *rparam=NULL, *rdata=NULL;
    172         unsigned int rparam_count=0, rdata_count=0;
    173 
    174         setup = TRANSACT2_SETFSINFO;
    175 
    176         SSVAL(param,0,0);
    177         SSVAL(param,2,SMB_SET_CIFS_UNIX_INFO);
    178 
    179         SSVAL(data,0,major);
    180         SSVAL(data,2,minor);
    181         SIVAL(data,4,caplow);
    182         SIVAL(data,8,caphigh);
    183 
    184         if (!cli_send_trans(cli, SMBtrans2,
    185                     NULL,
    186                     0, 0,
    187                     &setup, 1, 0,
    188                     param, 4, 0,
    189                     data, 12, 560)) {
    190                 goto cleanup;
    191         }
    192 
    193         if (!cli_receive_trans(cli, SMBtrans2,
    194                               &rparam, &rparam_count,
    195                               &rdata, &rdata_count)) {
    196                 goto cleanup;
    197         }
    198 
    199         if (cli_is_error(cli)) {
    200                 ret = False;
    201                 goto cleanup;
    202         } else {
    203                 ret = True;
    204         }
    205 
    206 cleanup:
    207         SAFE_FREE(rparam);
    208         SAFE_FREE(rdata);
    209 
    210         return ret;
    211 }
    212 
    213 bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr)
    214 {
    215         bool ret = False;
    216         uint16 setup;
    217         char param[2];
    218         char *rparam=NULL, *rdata=NULL;
    219         unsigned int rparam_count=0, rdata_count=0;
    220 
    221         if (!cli||!fs_attr)
    222                 smb_panic("cli_get_fs_attr_info() called with NULL Pionter!");
    223 
    224         setup = TRANSACT2_QFSINFO;
    225 
    226         SSVAL(param,0,SMB_QUERY_FS_ATTRIBUTE_INFO);
    227 
    228         if (!cli_send_trans(cli, SMBtrans2,
    229                     NULL,
    230                     0, 0,
    231                     &setup, 1, 0,
    232                     param, 2, 0,
    233                     NULL, 0, 560)) {
    234                 goto cleanup;
    235         }
    236 
    237         if (!cli_receive_trans(cli, SMBtrans2,
    238                               &rparam, &rparam_count,
    239                               &rdata, &rdata_count)) {
    240                 goto cleanup;
    241         }
    242 
    243         if (cli_is_error(cli)) {
    244                 ret = False;
    245                 goto cleanup;
    246         } else {
    247                 ret = True;
    248         }
    249 
    250         if (rdata_count < 12) {
    251                 goto cleanup;
    252         }
    253 
    254         *fs_attr = IVAL(rdata,0);
     166struct cli_set_unix_extensions_capabilities_state {
     167        struct cli_state *cli;
     168        uint16_t setup[1];
     169        uint8_t param[4];
     170        uint8_t data[12];
     171};
     172
     173static void cli_set_unix_extensions_capabilities_done(
     174        struct tevent_req *subreq);
     175
     176struct tevent_req *cli_set_unix_extensions_capabilities_send(
     177        TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
     178        uint16_t major, uint16_t minor, uint32_t caplow, uint32_t caphigh)
     179{
     180        struct tevent_req *req, *subreq;
     181        struct cli_set_unix_extensions_capabilities_state *state;
     182
     183        req = tevent_req_create(
     184                mem_ctx, &state,
     185                struct cli_set_unix_extensions_capabilities_state);
     186        if (req == NULL) {
     187                return NULL;
     188        }
     189
     190        state->cli = cli;
     191        SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
     192
     193        SSVAL(state->param, 0, 0);
     194        SSVAL(state->param, 2, SMB_SET_CIFS_UNIX_INFO);
     195
     196        SSVAL(state->data, 0, major);
     197        SSVAL(state->data, 2, minor);
     198        SIVAL(state->data, 4, caplow);
     199        SIVAL(state->data, 8, caphigh);
     200
     201        subreq = cli_trans_send(state, ev, cli, SMBtrans2,
     202                                NULL, 0, 0, 0,
     203                                state->setup, 1, 0,
     204                                state->param, 4, 0,
     205                                state->data, 12, 560);
     206        if (tevent_req_nomem(subreq, req)) {
     207                return tevent_req_post(req, ev);
     208        }
     209        tevent_req_set_callback(
     210                subreq, cli_set_unix_extensions_capabilities_done, req);
     211        return req;
     212}
     213
     214static void cli_set_unix_extensions_capabilities_done(
     215        struct tevent_req *subreq)
     216{
     217        struct tevent_req *req = tevent_req_callback_data(
     218                subreq, struct tevent_req);
     219        struct cli_set_unix_extensions_capabilities_state *state = tevent_req_data(
     220                req, struct cli_set_unix_extensions_capabilities_state);
     221
     222        NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
     223                                         NULL, 0, NULL, NULL, 0, NULL);
     224        if (NT_STATUS_IS_OK(status)) {
     225                state->cli->requested_posix_capabilities = IVAL(state->data, 4);
     226        }
     227        tevent_req_simple_finish_ntstatus(subreq, status);
     228}
     229
     230NTSTATUS cli_set_unix_extensions_capabilities_recv(struct tevent_req *req)
     231{
     232        return tevent_req_simple_recv_ntstatus(req);
     233}
     234
     235NTSTATUS cli_set_unix_extensions_capabilities(struct cli_state *cli,
     236                                              uint16 major, uint16 minor,
     237                                              uint32 caplow, uint32 caphigh)
     238{
     239        struct tevent_context *ev;
     240        struct tevent_req *req;
     241        NTSTATUS status = NT_STATUS_NO_MEMORY;
     242
     243        if (cli_has_async_calls(cli)) {
     244                return NT_STATUS_INVALID_PARAMETER;
     245        }
     246        ev = tevent_context_init(talloc_tos());
     247        if (ev == NULL) {
     248                goto fail;
     249        }
     250        req = cli_set_unix_extensions_capabilities_send(
     251                ev, ev, cli, major, minor, caplow, caphigh);
     252        if (req == NULL) {
     253                goto fail;
     254        }
     255        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     256                goto fail;
     257        }
     258        status = cli_set_unix_extensions_capabilities_recv(req);
     259fail:
     260        TALLOC_FREE(ev);
     261        if (!NT_STATUS_IS_OK(status)) {
     262                cli_set_error(cli, status);
     263        }
     264        return status;
     265}
     266
     267struct cli_get_fs_attr_info_state {
     268        uint16_t setup[1];
     269        uint8_t param[2];
     270        uint32_t fs_attr;
     271};
     272
     273static void cli_get_fs_attr_info_done(struct tevent_req *subreq);
     274
     275struct tevent_req *cli_get_fs_attr_info_send(TALLOC_CTX *mem_ctx,
     276                                             struct tevent_context *ev,
     277                                             struct cli_state *cli)
     278{
     279        struct tevent_req *subreq, *req;
     280        struct cli_get_fs_attr_info_state *state;
     281
     282        req = tevent_req_create(mem_ctx, &state,
     283                                struct cli_get_fs_attr_info_state);
     284        if (req == NULL) {
     285                return NULL;
     286        }
     287        SSVAL(state->setup+0, 0, TRANSACT2_QFSINFO);
     288        SSVAL(state->param+0, 0, SMB_QUERY_FS_ATTRIBUTE_INFO);
     289
     290        subreq = cli_trans_send(state, ev, cli, SMBtrans2,
     291                                NULL, 0, 0, 0,
     292                                state->setup, 1, 0,
     293                                state->param, 2, 0,
     294                                NULL, 0, 560);
     295        if (tevent_req_nomem(subreq, req)) {
     296                return tevent_req_post(req, ev);
     297        }
     298        tevent_req_set_callback(subreq, cli_get_fs_attr_info_done, req);
     299        return req;
     300}
     301
     302static void cli_get_fs_attr_info_done(struct tevent_req *subreq)
     303{
     304        struct tevent_req *req = tevent_req_callback_data(
     305                subreq, struct tevent_req);
     306        struct cli_get_fs_attr_info_state *state = tevent_req_data(
     307                req, struct cli_get_fs_attr_info_state);
     308        uint8_t *data;
     309        uint32_t num_data;
     310        NTSTATUS status;
     311
     312        status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL, 0, NULL,
     313                                NULL, 0, NULL, &data, 12, &num_data);
     314        TALLOC_FREE(subreq);
     315        if (!NT_STATUS_IS_OK(status)) {
     316                tevent_req_nterror(req, status);
     317                return;
     318        }
     319        state->fs_attr = IVAL(data, 0);
     320        TALLOC_FREE(data);
     321        tevent_req_done(req);
     322}
     323
     324NTSTATUS cli_get_fs_attr_info_recv(struct tevent_req *req, uint32_t *fs_attr)
     325{
     326        struct cli_get_fs_attr_info_state *state = tevent_req_data(
     327                req, struct cli_get_fs_attr_info_state);
     328        NTSTATUS status;
     329
     330        if (tevent_req_is_nterror(req, &status)) {
     331                return status;
     332        }
     333        *fs_attr = state->fs_attr;
     334        return NT_STATUS_OK;
     335}
     336
     337NTSTATUS cli_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr)
     338{
     339        struct tevent_context *ev;
     340        struct tevent_req *req;
     341        NTSTATUS status = NT_STATUS_NO_MEMORY;
     342
     343        if (cli_has_async_calls(cli)) {
     344                return NT_STATUS_INVALID_PARAMETER;
     345        }
     346        ev = tevent_context_init(talloc_tos());
     347        if (ev == NULL) {
     348                goto fail;
     349        }
     350        req = cli_get_fs_attr_info_send(ev, ev, cli);
     351        if (req == NULL) {
     352                goto fail;
     353        }
     354        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     355                goto fail;
     356        }
     357        status = cli_get_fs_attr_info_recv(req, fs_attr);
     358fail:
     359        TALLOC_FREE(ev);
     360        if (!NT_STATUS_IS_OK(status)) {
     361                cli_set_error(cli, status);
     362        }
     363        return status;
     364}
     365
     366NTSTATUS cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name,
     367                                uint32 *pserial_number, time_t *pdate)
     368{
     369        NTSTATUS status;
     370        uint16 setup[1];
     371        uint8_t param[2];
     372        uint8_t *rdata;
     373        uint32_t rdata_count;
     374        unsigned int nlen;
     375
     376        SSVAL(setup, 0, TRANSACT2_QFSINFO);
     377        SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO);
     378
     379        status = cli_trans(talloc_tos(), cli, SMBtrans2,
     380                           NULL, 0, 0, 0,
     381                           setup, 1, 0,
     382                           param, 2, 0,
     383                           NULL, 0, 560,
     384                           NULL,
     385                           NULL, 0, NULL,
     386                           NULL, 0, NULL,
     387                           &rdata, 10, &rdata_count);
     388        if (!NT_STATUS_IS_OK(status)) {
     389                return status;
     390        }
     391
     392        if (pdate) {
     393                struct timespec ts;
     394                ts = interpret_long_date((char *)rdata);
     395                *pdate = ts.tv_sec;
     396        }
     397        if (pserial_number) {
     398                *pserial_number = IVAL(rdata,8);
     399        }
     400        nlen = IVAL(rdata,12);
     401        clistr_pull(cli->inbuf, volume_name, rdata + 18, sizeof(fstring),
     402                    nlen, STR_UNICODE);
    255403
    256404        /* todo: but not yet needed
     
    258406         */
    259407
    260 cleanup:
    261         SAFE_FREE(rparam);
    262         SAFE_FREE(rdata);
    263 
    264         return ret;
    265 }
    266 
    267 bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number)
    268 {
    269         bool ret = False;
    270         uint16 setup;
    271         char param[2];
    272         char *rparam=NULL, *rdata=NULL;
    273         unsigned int rparam_count=0, rdata_count=0;
    274         unsigned char nlen;
    275 
    276         setup = TRANSACT2_QFSINFO;
    277 
    278         SSVAL(param,0,SMB_INFO_VOLUME);
    279 
    280         if (!cli_send_trans(cli, SMBtrans2,
    281                     NULL,
    282                     0, 0,
    283                     &setup, 1, 0,
    284                     param, 2, 0,
    285                     NULL, 0, 560)) {
    286                 goto cleanup;
    287         }
    288 
    289         if (!cli_receive_trans(cli, SMBtrans2,
    290                               &rparam, &rparam_count,
    291                               &rdata, &rdata_count)) {
    292                 goto cleanup;
    293         }
    294 
    295         if (cli_is_error(cli)) {
    296                 ret = False;
    297                 goto cleanup;
    298         } else {
    299                 ret = True;
    300         }
    301 
    302         if (rdata_count < 5) {
    303                 goto cleanup;
    304         }
    305 
    306         if (pserial_number) {
    307                 *pserial_number = IVAL(rdata,0);
    308         }
    309         nlen = CVAL(rdata,l2_vol_cch);
    310         clistr_pull(cli->inbuf, volume_name, rdata + l2_vol_szVolLabel,
    311                     sizeof(fstring), nlen, STR_NOALIGN);
    312 
    313         /* todo: but not yet needed
    314          *       return the other stuff
    315          */
    316 
    317 cleanup:
    318         SAFE_FREE(rparam);
    319         SAFE_FREE(rdata);
    320 
    321         return ret;
    322 }
    323 
    324 bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate)
    325 {
    326         bool ret = False;
    327         uint16 setup;
    328         char param[2];
    329         char *rparam=NULL, *rdata=NULL;
    330         unsigned int rparam_count=0, rdata_count=0;
    331         unsigned int nlen;
    332 
    333         setup = TRANSACT2_QFSINFO;
    334 
    335         SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO);
    336 
    337         if (!cli_send_trans(cli, SMBtrans2,
    338                     NULL,
    339                     0, 0,
    340                     &setup, 1, 0,
    341                     param, 2, 0,
    342                     NULL, 0, 560)) {
    343                 goto cleanup;
    344         }
    345 
    346         if (!cli_receive_trans(cli, SMBtrans2,
    347                               &rparam, &rparam_count,
    348                               &rdata, &rdata_count)) {
    349                 goto cleanup;
    350         }
    351 
    352         if (cli_is_error(cli)) {
    353                 ret = False;
    354                 goto cleanup;
    355         } else {
    356                 ret = True;
    357         }
    358 
    359         if (rdata_count < 19) {
    360                 goto cleanup;
    361         }
    362 
    363         if (pdate) {
    364                 struct timespec ts;
    365                 ts = interpret_long_date(rdata);
    366                 *pdate = ts.tv_sec;
    367         }
    368         if (pserial_number) {
    369                 *pserial_number = IVAL(rdata,8);
    370         }
    371         nlen = IVAL(rdata,12);
    372         clistr_pull(cli->inbuf, volume_name, rdata + 18, sizeof(fstring),
    373                     nlen, STR_UNICODE);
    374 
    375         /* todo: but not yet needed
    376          *       return the other stuff
    377          */
    378 
    379 cleanup:
    380         SAFE_FREE(rparam);
    381         SAFE_FREE(rdata);
    382 
    383         return ret;
    384 }
    385 
    386 bool cli_get_fs_full_size_info(struct cli_state *cli,
    387                                uint64_t *total_allocation_units,
    388                                uint64_t *caller_allocation_units,
    389                                uint64_t *actual_allocation_units,
    390                                uint64_t *sectors_per_allocation_unit,
    391                                uint64_t *bytes_per_sector)
    392 {
    393         bool ret = False;
    394         uint16 setup;
    395         char param[2];
    396         char *rparam=NULL, *rdata=NULL;
    397         unsigned int rparam_count=0, rdata_count=0;
    398 
    399         setup = TRANSACT2_QFSINFO;
    400 
    401         SSVAL(param,0,SMB_FS_FULL_SIZE_INFORMATION);
    402 
    403         if (!cli_send_trans(cli, SMBtrans2,
    404                     NULL,
    405                     0, 0,
    406                     &setup, 1, 0,
    407                     param, 2, 0,
    408                     NULL, 0, 560)) {
    409                 goto cleanup;
    410         }
    411 
    412         if (!cli_receive_trans(cli, SMBtrans2,
    413                               &rparam, &rparam_count,
    414                               &rdata, &rdata_count)) {
    415                 goto cleanup;
    416         }
    417 
    418         if (cli_is_error(cli)) {
    419                 ret = False;
    420                 goto cleanup;
    421         } else {
    422                 ret = True;
    423         }
    424 
    425         if (rdata_count != 32) {
    426                 goto cleanup;
     408        TALLOC_FREE(rdata);
     409        return NT_STATUS_OK;
     410}
     411
     412NTSTATUS cli_get_fs_full_size_info(struct cli_state *cli,
     413                                   uint64_t *total_allocation_units,
     414                                   uint64_t *caller_allocation_units,
     415                                   uint64_t *actual_allocation_units,
     416                                   uint64_t *sectors_per_allocation_unit,
     417                                   uint64_t *bytes_per_sector)
     418{
     419        uint16 setup[1];
     420        uint8_t param[2];
     421        uint8_t *rdata = NULL;
     422        uint32_t rdata_count;
     423        NTSTATUS status;
     424
     425        SSVAL(setup, 0, TRANSACT2_QFSINFO);
     426        SSVAL(param, 0, SMB_FS_FULL_SIZE_INFORMATION);
     427
     428        status = cli_trans(talloc_tos(), cli, SMBtrans2,
     429                           NULL, 0, 0, 0,
     430                           setup, 1, 0, /* setup */
     431                           param, 2, 0,  /* param */
     432                           NULL, 0, 560, /* data */
     433                           NULL,
     434                           NULL, 0, NULL, /* rsetup */
     435                           NULL, 0, NULL, /* rparam */
     436                           &rdata, 32, &rdata_count);  /* rdata */
     437        if (!NT_STATUS_IS_OK(status)) {
     438                goto fail;
    427439        }
    428440
     
    443455        }
    444456
    445 cleanup:
    446         SAFE_FREE(rparam);
    447         SAFE_FREE(rdata);
    448 
    449         return ret;
    450 }
    451 
    452 bool cli_get_posix_fs_info(struct cli_state *cli,
    453                            uint32 *optimal_transfer_size,
    454                            uint32 *block_size,
    455                            uint64_t *total_blocks,
    456                            uint64_t *blocks_available,
    457                            uint64_t *user_blocks_available,
    458                            uint64_t *total_file_nodes,
    459                            uint64_t *free_file_nodes,
    460                            uint64_t *fs_identifier)
    461 {
    462         bool ret = False;
    463         uint16 setup;
    464         char param[2];
    465         char *rparam=NULL, *rdata=NULL;
    466         unsigned int rparam_count=0, rdata_count=0;
    467 
    468         setup = TRANSACT2_QFSINFO;
    469 
     457fail:
     458        TALLOC_FREE(rdata);
     459        return status;
     460}
     461
     462NTSTATUS cli_get_posix_fs_info(struct cli_state *cli,
     463                               uint32 *optimal_transfer_size,
     464                               uint32 *block_size,
     465                               uint64_t *total_blocks,
     466                               uint64_t *blocks_available,
     467                               uint64_t *user_blocks_available,
     468                               uint64_t *total_file_nodes,
     469                               uint64_t *free_file_nodes,
     470                               uint64_t *fs_identifier)
     471{
     472        uint16 setup[1];
     473        uint8_t param[2];
     474        uint8_t *rdata = NULL;
     475        uint32_t rdata_count;
     476        NTSTATUS status;
     477
     478        SSVAL(setup, 0, TRANSACT2_QFSINFO);
    470479        SSVAL(param,0,SMB_QUERY_POSIX_FS_INFO);
    471480
    472         if (!cli_send_trans(cli, SMBtrans2,
    473                     NULL,
    474                     0, 0,
    475                     &setup, 1, 0,
    476                     param, 2, 0,
    477                     NULL, 0, 560)) {
    478                 goto cleanup;
    479         }
    480 
    481         if (!cli_receive_trans(cli, SMBtrans2,
    482                               &rparam, &rparam_count,
    483                               &rdata, &rdata_count)) {
    484                 goto cleanup;
    485         }
    486 
    487         if (cli_is_error(cli)) {
    488                 ret = False;
    489                 goto cleanup;
    490         } else {
    491                 ret = True;
    492         }
    493 
    494         if (rdata_count != 56) {
    495                 goto cleanup;
     481        status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0, 0, 0,
     482                           setup, 1, 0,
     483                           param, 2, 0,
     484                           NULL, 0, 560,
     485                           NULL,
     486                           NULL, 0, NULL, /* rsetup */
     487                           NULL, 0, NULL, /* rparam */
     488                           &rdata, 56, &rdata_count);
     489        if (!NT_STATUS_IS_OK(status)) {
     490                return status;
    496491        }
    497492
     
    520515                *fs_identifier = BIG_UINT(rdata,48);
    521516        }
    522 
    523 cleanup:
    524         SAFE_FREE(rparam);
    525         SAFE_FREE(rdata);
    526 
    527         return ret;
     517        return NT_STATUS_OK;
    528518}
    529519
     
    535525static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out, DATA_BLOB *param_out)
    536526{
    537         uint16 setup;
    538         char param[4];
    539         char *rparam=NULL, *rdata=NULL;
    540         unsigned int rparam_count=0, rdata_count=0;
    541         NTSTATUS status = NT_STATUS_OK;
    542 
    543         setup = TRANSACT2_SETFSINFO;
    544 
     527        uint16_t setup[1];
     528        uint8_t param[4];
     529        uint8_t *rparam=NULL, *rdata=NULL;
     530        uint32_t num_rparam, num_rdata;
     531        NTSTATUS status;
     532
     533        SSVAL(setup+0, 0, TRANSACT2_SETFSINFO);
    545534        SSVAL(param,0,0);
    546535        SSVAL(param,2,SMB_REQUEST_TRANSPORT_ENCRYPTION);
    547536
    548         if (!cli_send_trans(cli, SMBtrans2,
    549                                 NULL,
    550                                 0, 0,
    551                                 &setup, 1, 0,
    552                                 param, 4, 0,
    553                                 (char *)in->data, in->length, CLI_BUFFER_SIZE)) {
    554                 status = cli_nt_error(cli);
    555                 goto out;
    556         }
    557 
    558         if (!cli_receive_trans(cli, SMBtrans2,
    559                                 &rparam, &rparam_count,
    560                                 &rdata, &rdata_count)) {
    561                 status = cli_nt_error(cli);
    562                 goto out;
    563         }
    564 
    565         if (cli_is_error(cli)) {
    566                 status = cli_nt_error(cli);
    567                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    568                         goto out;
    569                 }
    570         }
    571 
    572         *out = data_blob(rdata, rdata_count);
    573         *param_out = data_blob(rparam, rparam_count);
    574 
    575   out:
    576 
    577         SAFE_FREE(rparam);
    578         SAFE_FREE(rdata);
     537        status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0, 0, 0,
     538                           setup, 1, 0,
     539                           param, 4, 2,
     540                           (uint8_t *)in->data, in->length, CLI_BUFFER_SIZE,
     541                           NULL,          /* recv_flags */
     542                           NULL, 0, NULL, /* rsetup */
     543                           &rparam, 0, &num_rparam,
     544                           &rdata, 0, &num_rdata);
     545
     546        if (!NT_STATUS_IS_OK(status) &&
     547            !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     548                return status;
     549        }
     550
     551        *out = data_blob(rdata, num_rdata);
     552        *param_out = data_blob(rparam, num_rparam);
     553
     554        TALLOC_FREE(rparam);
     555        TALLOC_FREE(rdata);
    579556        return status;
    580557}
     
    625602                return NT_STATUS_NO_MEMORY;
    626603        }
    627         status = ntlmssp_client_start(&es->s.ntlmssp_state);
     604        status = ntlmssp_client_start(NULL,
     605                                      global_myname(),
     606                                      lp_workgroup(),
     607                                      lp_client_ntlmv2_auth(),
     608                                      &es->s.ntlmssp_state);
    628609        if (!NT_STATUS_IS_OK(status)) {
    629610                goto fail;
     
    693674******************************************************************************/
    694675
    695 static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es,
     676static NTSTATUS make_cli_gss_blob(TALLOC_CTX *ctx,
     677                                struct smb_trans_enc_state *es,
    696678                                const char *service,
    697679                                const char *host,
     
    740722        } else {
    741723                /* Remove the SPNEGO wrapper */
    742                 if (!spnego_parse_auth_response(spnego_blob_in, status_in, OID_KERBEROS5, &blob_in)) {
     724                if (!spnego_parse_auth_response(ctx, spnego_blob_in, status_in, OID_KERBEROS5, &blob_in)) {
    743725                        status = NT_STATUS_UNSUCCESSFUL;
    744726                        goto fail;
     
    775757        }
    776758
    777         blob_out = data_blob(tok_out.value, tok_out.length);
     759        blob_out = data_blob_talloc(ctx, tok_out.value, tok_out.length);
    778760
    779761        /* Wrap in an SPNEGO wrapper */
    780         *p_blob_out = gen_negTokenTarg(krb_mechs, blob_out);
     762        *p_blob_out = spnego_gen_negTokenInit(ctx, krb_mechs, &blob_out, NULL);
    781763
    782764  fail:
     
    814796
    815797        servicename = "cifs";
    816         status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
     798        status = make_cli_gss_blob(talloc_tos(), es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
    817799        if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    818800                servicename = "host";
    819                 status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
     801                status = make_cli_gss_blob(talloc_tos(), es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
    820802                if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    821803                        goto fail;
     
    830812                }
    831813                data_blob_free(&blob_send);
    832                 status = make_cli_gss_blob(es, servicename, fqdn, status, blob_recv, &blob_send);
     814                status = make_cli_gss_blob(talloc_tos(), es, servicename, fqdn, status, blob_recv, &blob_send);
    833815        } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
    834816        data_blob_free(&blob_recv);
  • vendor/current/source3/libsmb/clikrb5.c

    r594 r740  
    2323#include "includes.h"
    2424#include "smb_krb5.h"
    25 #include "authdata.h"
     25#include "../librpc/gen_ndr/krb5pac.h"
     26#include "../lib/util/asn1.h"
     27#include "libsmb/nmblib.h"
     28
     29#ifndef KRB5_AUTHDATA_WIN2K_PAC
     30#define KRB5_AUTHDATA_WIN2K_PAC 128
     31#endif
     32
     33#ifndef KRB5_AUTHDATA_IF_RELEVANT
     34#define KRB5_AUTHDATA_IF_RELEVANT 1
     35#endif
    2636
    2737#ifdef HAVE_KRB5
     
    348358       
    349359        asn1_start_tag(data, ASN1_CONTEXT(2));
    350         asn1_read_OctetString(data, talloc_autofree_context(), &edata_contents);
     360        asn1_read_OctetString(data, talloc_tos(), &edata_contents);
    351361        asn1_end_tag(data);
    352362        asn1_end_tag(data);
     
    391401        asn1_end_tag(data);
    392402        asn1_start_tag(data, ASN1_CONTEXT(1));
    393         asn1_read_OctetString(data, talloc_autofree_context(), &pac_contents);
     403        asn1_read_OctetString(data, talloc_tos(), &pac_contents);
    394404        asn1_end_tag(data);
    395405        asn1_end_tag(data);
     
    929939
    930940/*
    931   get a kerberos5 ticket for the given service 
     941  get a kerberos5 ticket for the given service
    932942*/
    933 int cli_krb5_get_ticket(const char *principal, time_t time_offset,
    934                         DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
    935                         uint32 extra_ap_opts, const char *ccname,
     943int cli_krb5_get_ticket(TALLOC_CTX *mem_ctx,
     944                        const char *principal, time_t time_offset,
     945                        DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
     946                        uint32_t extra_ap_opts, const char *ccname,
    936947                        time_t *tgs_expire,
    937948                        const char *impersonate_princ_s)
     
    944955        krb5_auth_context auth_context = NULL;
    945956        krb5_enctype enc_types[] = {
    946 #ifdef ENCTYPE_ARCFOUR_HMAC
    947957                ENCTYPE_ARCFOUR_HMAC,
    948 #endif
    949                 ENCTYPE_DES_CBC_MD5,
    950                 ENCTYPE_DES_CBC_CRC,
     958                ENCTYPE_DES_CBC_MD5,
     959                ENCTYPE_DES_CBC_CRC,
    951960                ENCTYPE_NULL};
    952961
     
    954963        retval = krb5_init_context(&context);
    955964        if (retval) {
    956                 DEBUG(1,("cli_krb5_get_ticket: krb5_init_context failed (%s)\n",
     965                DEBUG(1, ("krb5_init_context failed (%s)\n",
    957966                         error_message(retval)));
    958967                goto failed;
     
    965974        if ((retval = krb5_cc_resolve(context, ccname ?
    966975                        ccname : krb5_cc_default_name(context), &ccdef))) {
    967                 DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n",
     976                DEBUG(1, ("krb5_cc_default failed (%s)\n",
    968977                         error_message(retval)));
    969978                goto failed;
     
    971980
    972981        if ((retval = krb5_set_default_tgs_ktypes(context, enc_types))) {
    973                 DEBUG(1,("cli_krb5_get_ticket: krb5_set_default_tgs_ktypes failed (%s)\n",
     982                DEBUG(1, ("krb5_set_default_tgs_ktypes failed (%s)\n",
    974983                         error_message(retval)));
    975984                goto failed;
    976985        }
    977986
    978         if ((retval = ads_krb5_mk_req(context,
    979                                         &auth_context,
    980                                         AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
    981                                         principal,
    982                                         ccdef, &packet,
    983                                         tgs_expire,
    984                                         impersonate_princ_s))) {
     987        retval = ads_krb5_mk_req(context, &auth_context,
     988                                AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
     989                                principal, ccdef, &packet,
     990                                tgs_expire, impersonate_princ_s);
     991        if (retval) {
    985992                goto failed;
    986993        }
    987994
    988         get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
    989 
    990         *ticket = data_blob(packet.data, packet.length);
    991 
    992         kerberos_free_data_contents(context, &packet);
     995        get_krb5_smb_session_key(mem_ctx, context, auth_context,
     996                                 session_key_krb5, false);
     997
     998        *ticket = data_blob_talloc(mem_ctx, packet.data, packet.length);
     999
     1000        kerberos_free_data_contents(context, &packet);
    9931001
    9941002failed:
    9951003
    996         if ( context ) {
     1004        if (context) {
    9971005                if (ccdef)
    9981006                        krb5_cc_close(context, ccdef);
     
    10011009                krb5_free_context(context);
    10021010        }
    1003                
     1011
    10041012        return retval;
    10051013}
    10061014
    1007  bool get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, bool remote)
    1008  {
     1015bool get_krb5_smb_session_key(TALLOC_CTX *mem_ctx,
     1016                              krb5_context context,
     1017                              krb5_auth_context auth_context,
     1018                              DATA_BLOB *session_key, bool remote)
     1019{
    10091020        krb5_keyblock *skey = NULL;
    10101021        krb5_error_code err = 0;
     
    10121023
    10131024        if (remote) {
    1014                 err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);
     1025                err = krb5_auth_con_getremotesubkey(context,
     1026                                                    auth_context, &skey);
    10151027        } else {
    1016                 err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
     1028                err = krb5_auth_con_getlocalsubkey(context,
     1029                                                   auth_context, &skey);
    10171030        }
    10181031
     
    10221035        }
    10231036
    1024         DEBUG(10, ("Got KRB5 session key of length %d\n",  (int)KRB5_KEY_LENGTH(skey)));
    1025         *session_key = data_blob(KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
    1026         dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
     1037        DEBUG(10, ("Got KRB5 session key of length %d\n",
     1038                   (int)KRB5_KEY_LENGTH(skey)));
     1039
     1040        *session_key = data_blob_talloc(mem_ctx,
     1041                                         KRB5_KEY_DATA(skey),
     1042                                         KRB5_KEY_LENGTH(skey));
     1043        dump_data_pw("KRB5 Session Key:\n",
     1044                     session_key->data,
     1045                     session_key->length);
    10271046
    10281047        ret = true;
    10291048
    1030  done:
     1049done:
    10311050        if (skey) {
    10321051                krb5_free_keyblock(context, skey);
     
    10341053
    10351054        return ret;
    1036  }
     1055}
    10371056
    10381057
     
    22522271#else /* HAVE_KRB5 */
    22532272 /* this saves a few linking headaches */
    2254  int cli_krb5_get_ticket(const char *principal, time_t time_offset,
    2255                         DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
     2273 int cli_krb5_get_ticket(TALLOC_CTX *mem_ctx,
     2274                        const char *principal, time_t time_offset,
     2275                        DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
     2276                        uint32_t extra_ap_opts,
    22562277                        const char *ccname, time_t *tgs_expire,
    22572278                        const char *impersonate_princ_s)
     
    22612282}
    22622283
    2263 #endif
     2284bool unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_pac_data)
     2285{
     2286        DEBUG(0,("NO KERBEROS SUPPORT\n"));
     2287        return false;
     2288}
     2289
     2290#endif /* HAVE_KRB5 */
  • vendor/current/source3/libsmb/clilist.c

    r414 r740  
    1919
    2020#include "includes.h"
     21#include "libsmb/libsmb.h"
     22#include "../lib/util/tevent_ntstatus.h"
     23#include "async_smb.h"
     24#include "trans2.h"
    2125
    2226/****************************************************************************
     
    4751                                        struct cli_state *cli,
    4852                                        int level,
     53                                        const char *base_ptr,
     54                                        uint16_t recv_flags2,
    4955                                        const char *p,
    5056                                        const char *pdata_end,
    51                                         file_info *finfo,
     57                                        struct file_info *finfo,
    5258                                        uint32 *p_resume_key,
    5359                                        DATA_BLOB *p_last_name_raw)
     
    6369        }
    6470        ZERO_STRUCTP(finfo);
    65         finfo->cli = cli;
    6671
    6772        switch (level) {
     
    7277                                return pdata_end - base;
    7378                        }
    74                         finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4));
    75                         finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8));
    76                         finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12));
     79                        finfo->ctime_ts = convert_time_t_to_timespec(
     80                                make_unix_date2(p+4, cli->serverzone));
     81                        finfo->atime_ts = convert_time_t_to_timespec(
     82                                make_unix_date2(p+8, cli->serverzone));
     83                        finfo->mtime_ts = convert_time_t_to_timespec(
     84                                make_unix_date2(p+12, cli->serverzone));
    7785                        finfo->size = IVAL(p,16);
    7886                        finfo->mode = CVAL(p,24);
    7987                        len = CVAL(p, 26);
    8088                        p += 27;
    81                         p += clistr_align_in(cli, p, 0);
     89                        p += align_string(base_ptr, p, 0);
    8290
    8391                        /* We can safely use len here (which is required by OS/2)
     
    100108                           (tridge) */
    101109                        ret = clistr_pull_talloc(ctx,
    102                                                 cli->inbuf,
     110                                                base_ptr,
     111                                                recv_flags2,
    103112                                                &finfo->name,
    104113                                                p,
     
    117126                                return pdata_end - base;
    118127                        }
    119                         finfo->ctime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+4));
    120                         finfo->atime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+8));
    121                         finfo->mtime_ts = convert_time_t_to_timespec(cli_make_unix_date2(cli, p+12));
     128                        finfo->ctime_ts = convert_time_t_to_timespec(
     129                                make_unix_date2(p+4, cli->serverzone));
     130                        finfo->atime_ts = convert_time_t_to_timespec(
     131                                make_unix_date2(p+8, cli->serverzone));
     132                        finfo->mtime_ts = convert_time_t_to_timespec(
     133                                make_unix_date2(p+12, cli->serverzone));
    122134                        finfo->size = IVAL(p,16);
    123135                        finfo->mode = CVAL(p,24);
     
    129141                        }
    130142                        ret = clistr_pull_talloc(ctx,
    131                                                 cli->inbuf,
     143                                                base_ptr,
     144                                                recv_flags2,
    132145                                                &finfo->name,
    133146                                                p,
     
    181194                                int flags = 0;
    182195                                if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
    183                                 clistr_pull(cli->inbuf, finfo->short_name, p,
     196                                clistr_pull(base_ptr, finfo->short_name, p,
    184197                                            sizeof(finfo->short_name),
    185198                                            slen, flags);
     
    190203                        }
    191204                        ret = clistr_pull_talloc(ctx,
    192                                                 cli->inbuf,
     205                                                base_ptr,
     206                                                recv_flags2,
    193207                                                &finfo->name,
    194208                                                p,
     
    218232
    219233/****************************************************************************
    220  Do a directory listing, calling fn on each file found.
    221 ****************************************************************************/
    222 
    223 int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
    224                  void (*fn)(const char *, file_info *, const char *, void *), void *state)
    225 {
    226 #if 1
    227         int max_matches = 1366; /* Match W2k - was 512. */
    228 #else
    229         int max_matches = 512;
    230 #endif
    231         int info_level;
    232         char *p, *p2, *rdata_end;
    233         char *mask = NULL;
    234         file_info finfo;
    235         int i;
    236         char *dirlist = NULL;
    237         int dirlist_len = 0;
    238         int total_received = -1;
    239         bool First = True;
    240         int ff_searchcount=0;
    241         int ff_eos=0;
    242         int ff_dir_handle=0;
    243         int loop_count = 0;
    244         char *rparam=NULL, *rdata=NULL;
    245         unsigned int param_len, data_len;
    246         uint16 setup;
    247         char *param;
    248         uint32 resume_key = 0;
    249         TALLOC_CTX *frame = talloc_stackframe();
    250         DATA_BLOB last_name_raw = data_blob(NULL, 0);
    251 
    252         /* NT uses SMB_FIND_FILE_BOTH_DIRECTORY_INFO,
    253            OS/2 uses SMB_FIND_EA_SIZE. Both accept SMB_FIND_INFO_STANDARD. */
    254         info_level = (cli->capabilities&CAP_NT_SMBS)?
    255                 SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_INFO_STANDARD;
    256 
    257         mask = SMB_STRDUP(Mask);
    258         if (!mask) {
    259                 TALLOC_FREE(frame);
    260                 return -1;
    261         }
    262 
    263         while (ff_eos == 0) {
    264                 size_t nlen = 2*(strlen(mask)+1);
    265 
    266                 loop_count++;
    267                 if (loop_count > 200) {
    268                         DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
    269                         break;
    270                 }
    271 
    272                 param = SMB_MALLOC_ARRAY(char, 12+nlen+last_name_raw.length+2);
    273                 if (!param) {
    274                         break;
    275                 }
    276 
    277                 if (First) {
    278                         setup = TRANSACT2_FINDFIRST;
    279                         SSVAL(param,0,attribute); /* attribute */
    280                         SSVAL(param,2,max_matches); /* max count */
    281                         SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
    282                         SSVAL(param,6,info_level);
    283                         SIVAL(param,8,0);
    284                         p = param+12;
    285                         p += clistr_push(cli, param+12, mask,
    286                                          nlen, STR_TERMINATE);
    287                 } else {
    288                         setup = TRANSACT2_FINDNEXT;
    289                         SSVAL(param,0,ff_dir_handle);
    290                         SSVAL(param,2,max_matches); /* max count */
    291                         SSVAL(param,4,info_level);
    292                         /* For W2K servers serving out FAT filesystems we *must* set the
    293                            resume key. If it's not FAT then it's returned as zero. */
    294                         SIVAL(param,6,resume_key); /* ff_resume_key */
    295                         /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
    296                            can miss filenames. Use last filename continue instead. JRA */
    297                         SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END));        /* resume required + close on end */
    298                         p = param+12;
    299                         if (last_name_raw.length) {
    300                                 memcpy(p, last_name_raw.data, last_name_raw.length);
    301                                 p += last_name_raw.length;
    302                         } else {
    303                                 p += clistr_push(cli, param+12, mask,
    304                                                 nlen, STR_TERMINATE);
    305                         }
    306                 }
    307 
    308                 param_len = PTR_DIFF(p, param);
    309 
    310                 if (!cli_send_trans(cli, SMBtrans2,
    311                                     NULL,                   /* Name */
    312                                     -1, 0,                  /* fid, flags */
    313                                     &setup, 1, 0,           /* setup, length, max */
    314                                     param, param_len, 10,   /* param, length, max */
    315                                     NULL, 0,
    316 #if 0
    317                                     /* w2k value. */
    318                                     MIN(16384,cli->max_xmit) /* data, length, max. */
    319 #else
    320                                     cli->max_xmit           /* data, length, max. */
    321 #endif
    322                                     )) {
    323                         SAFE_FREE(param);
    324                         TALLOC_FREE(frame);
    325                         break;
    326                 }
    327 
    328                 SAFE_FREE(param);
    329 
    330                 if (!cli_receive_trans(cli, SMBtrans2,
    331                                        &rparam, &param_len,
    332                                        &rdata, &data_len) &&
    333                     cli_is_dos_error(cli)) {
    334                         /* We need to work around a Win95 bug - sometimes
    335                            it gives ERRSRV/ERRerror temprarily */
    336                         uint8 eclass;
    337                         uint32 ecode;
    338 
    339                         SAFE_FREE(rdata);
    340                         SAFE_FREE(rparam);
    341 
    342                         cli_dos_error(cli, &eclass, &ecode);
    343 
    344                         /*
    345                          * OS/2 might return "no more files",
    346                          * which just tells us, that searchcount is zero
    347                          * in this search.
    348                          * Guenter Kukkukk <linux@kukkukk.com>
    349                          */
    350 
    351                         if (eclass == ERRDOS && ecode == ERRnofiles) {
    352                                 ff_searchcount = 0;
    353                                 cli_reset_error(cli);
    354                                 break;
    355                         }
    356 
    357                         if (eclass != ERRSRV || ecode != ERRerror)
    358                                 break;
    359                         smb_msleep(100);
    360                         continue;
    361                 }
    362 
    363                 if (cli_is_error(cli) || !rdata || !rparam) {
    364                         SAFE_FREE(rdata);
    365                         SAFE_FREE(rparam);
    366                         break;
    367                 }
    368 
    369                 if (total_received == -1)
    370                         total_received = 0;
    371 
    372                 /* parse out some important return info */
    373                 p = rparam;
    374                 if (First) {
    375                         ff_dir_handle = SVAL(p,0);
    376                         ff_searchcount = SVAL(p,2);
    377                         ff_eos = SVAL(p,4);
    378                 } else {
    379                         ff_searchcount = SVAL(p,0);
    380                         ff_eos = SVAL(p,2);
    381                 }
    382 
    383                 if (ff_searchcount == 0) {
    384                         SAFE_FREE(rdata);
    385                         SAFE_FREE(rparam);
    386                         break;
    387                 }
    388 
    389                 /* point to the data bytes */
    390                 p = rdata;
    391                 rdata_end = rdata + data_len;
    392 
    393                 /* we might need the lastname for continuations */
    394                 for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) {
    395                         if ((info_level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) &&
    396                                         (i == ff_searchcount-1)) {
    397                                 /* Last entry - fixup the last offset length. */
    398                                 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
    399                         }
    400                         p2 += interpret_long_filename(frame,
    401                                                         cli,
    402                                                         info_level,
    403                                                         p2,
    404                                                         rdata_end,
    405                                                         &finfo,
    406                                                         &resume_key,
    407                                                         &last_name_raw);
    408 
    409                         if (!finfo.name) {
    410                                 DEBUG(0,("cli_list_new: Error: unable to parse name from info level %d\n",
    411                                         info_level));
    412                                 ff_eos = 1;
    413                                 break;
    414                         }
    415                         if (!First && *mask && strcsequal(finfo.name, mask)) {
    416                                 DEBUG(0,("Error: Looping in FIND_NEXT as name %s has already been seen?\n",
    417                                         finfo.name));
    418                                 ff_eos = 1;
    419                                 break;
    420                         }
    421                 }
    422 
    423                 SAFE_FREE(mask);
    424                 if (ff_searchcount > 0 && ff_eos == 0 && finfo.name) {
    425                         mask = SMB_STRDUP(finfo.name);
    426                 } else {
    427                         mask = SMB_STRDUP("");
    428                 }
    429                 if (!mask) {
    430                         SAFE_FREE(rdata);
    431                         SAFE_FREE(rparam);
    432                         break;
    433                 }
    434 
    435                 /* grab the data for later use */
    436                 /* and add them to the dirlist pool */
    437                 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
    438 
    439                 if (!dirlist) {
    440                         DEBUG(0,("cli_list_new: Failed to expand dirlist\n"));
    441                         SAFE_FREE(rdata);
    442                         SAFE_FREE(rparam);
    443                         break;
    444                 }
    445 
    446                 memcpy(dirlist+dirlist_len,p,data_len);
    447                 dirlist_len += data_len;
    448 
    449                 total_received += ff_searchcount;
    450 
    451                 SAFE_FREE(rdata);
    452                 SAFE_FREE(rparam);
    453 
    454                 DEBUG(3,("received %d entries (eos=%d)\n",
    455                          ff_searchcount,ff_eos));
    456 
    457                 if (ff_searchcount > 0)
    458                         loop_count = 0;
    459 
    460                 First = False;
    461         }
    462 
    463         /* see if the server disconnected or the connection otherwise failed */
    464         if (cli_is_error(cli)) {
    465                 total_received = -1;
    466         } else {
    467                 /* no connection problem.  let user function add each entry */
    468                 rdata_end = dirlist + dirlist_len;
    469                 for (p=dirlist,i=0;i<total_received;i++) {
    470                         p += interpret_long_filename(frame,
    471                                                         cli,
    472                                                         info_level,
    473                                                         p,
    474                                                         rdata_end,
    475                                                         &finfo,
    476                                                         NULL,
    477                                                         NULL);
    478                         if (!finfo.name) {
    479                                 DEBUG(0,("cli_list_new: unable to parse name from info level %d\n",
    480                                         info_level));
    481                                 break;
    482                         }
    483                         fn(cli->dfs_mountpoint, &finfo, Mask, state);
    484                 }
    485         }
    486 
    487         /* free up the dirlist buffer and last name raw blob */
    488         SAFE_FREE(dirlist);
    489         data_blob_free(&last_name_raw);
    490         SAFE_FREE(mask);
    491         TALLOC_FREE(frame);
    492         return(total_received);
    493 }
    494 
    495 /****************************************************************************
    496234 Interpret a short filename structure.
    497235 The length of the structure is returned.
     
    501239                                struct cli_state *cli,
    502240                                char *p,
    503                                 file_info *finfo)
     241                                struct file_info *finfo)
    504242{
    505243        size_t ret;
    506244        ZERO_STRUCTP(finfo);
    507245
    508         finfo->cli = cli;
    509246        finfo->mode = CVAL(p,21);
    510247
    511248        /* this date is converted to GMT by make_unix_date */
    512         finfo->ctime_ts.tv_sec = cli_make_unix_date(cli, p+22);
     249        finfo->ctime_ts.tv_sec = make_unix_date(p+22, cli->serverzone);
    513250        finfo->ctime_ts.tv_nsec = 0;
    514251        finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec;
     
    517254        ret = clistr_pull_talloc(ctx,
    518255                        cli->inbuf,
     256                        SVAL(cli->inbuf, smb_flg2),
    519257                        &finfo->name,
    520258                        p+30,
     
    531269        }
    532270        return true;
    533         return(DIR_STRUCT_SIZE);
    534 }
    535 
    536 /****************************************************************************
    537  Do a directory listing, calling fn on each file found.
    538  this uses the old SMBsearch interface. It is needed for testing Samba,
    539  but should otherwise not be used.
    540 ****************************************************************************/
    541 
    542 int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
    543                  void (*fn)(const char *, file_info *, const char *, void *), void *state)
    544 {
     271}
     272
     273struct cli_list_old_state {
     274        struct tevent_context *ev;
     275        struct cli_state *cli;
     276        uint16_t vwv[2];
     277        char *mask;
     278        int num_asked;
     279        uint16_t attribute;
     280        uint8_t search_status[23];
     281        bool first;
     282        bool done;
     283        uint8_t *dirlist;
     284};
     285
     286static void cli_list_old_done(struct tevent_req *subreq);
     287
     288static struct tevent_req *cli_list_old_send(TALLOC_CTX *mem_ctx,
     289                                            struct tevent_context *ev,
     290                                            struct cli_state *cli,
     291                                            const char *mask,
     292                                            uint16_t attribute)
     293{
     294        struct tevent_req *req, *subreq;
     295        struct cli_list_old_state *state;
     296        uint8_t *bytes;
     297        static const uint16_t zero = 0;
     298
     299        req = tevent_req_create(mem_ctx, &state, struct cli_list_old_state);
     300        if (req == NULL) {
     301                return NULL;
     302        }
     303        state->ev = ev;
     304        state->cli = cli;
     305        state->attribute = attribute;
     306        state->first = true;
     307        state->mask = talloc_strdup(state, mask);
     308        if (tevent_req_nomem(state->mask, req)) {
     309                return tevent_req_post(req, ev);
     310        }
     311        state->num_asked = (cli->max_xmit - 100) / DIR_STRUCT_SIZE;
     312
     313        SSVAL(state->vwv + 0, 0, state->num_asked);
     314        SSVAL(state->vwv + 1, 0, state->attribute);
     315
     316        bytes = talloc_array(state, uint8_t, 1);
     317        if (tevent_req_nomem(bytes, req)) {
     318                return tevent_req_post(req, ev);
     319        }
     320        bytes[0] = 4;
     321        bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), mask,
     322                                   strlen(mask)+1, NULL);
     323
     324        bytes = smb_bytes_push_bytes(bytes, 5, (uint8_t *)&zero, 2);
     325        if (tevent_req_nomem(bytes, req)) {
     326                return tevent_req_post(req, ev);
     327        }
     328
     329        subreq = cli_smb_send(state, state->ev, state->cli, SMBsearch,
     330                              0, 2, state->vwv, talloc_get_size(bytes), bytes);
     331        if (tevent_req_nomem(subreq, req)) {
     332                return tevent_req_post(req, ev);
     333        }
     334        tevent_req_set_callback(subreq, cli_list_old_done, req);
     335        return req;
     336}
     337
     338static void cli_list_old_done(struct tevent_req *subreq)
     339{
     340        struct tevent_req *req = tevent_req_callback_data(
     341                subreq, struct tevent_req);
     342        struct cli_list_old_state *state = tevent_req_data(
     343                req, struct cli_list_old_state);
     344        NTSTATUS status;
     345        uint8_t cmd;
     346        uint8_t wct;
     347        uint16_t *vwv;
     348        uint32_t num_bytes;
     349        uint8_t *bytes;
     350        uint16_t received;
     351        size_t dirlist_len;
     352        uint8_t *tmp;
     353
     354        status = cli_smb_recv(subreq, state, NULL, 0, &wct, &vwv, &num_bytes,
     355                              &bytes);
     356        if (!NT_STATUS_IS_OK(status)
     357            && !NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnofiles))
     358            && !NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) {
     359                TALLOC_FREE(subreq);
     360                tevent_req_nterror(req, status);
     361                return;
     362        }
     363        if (NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnofiles))
     364            || NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) {
     365                received = 0;
     366        } else {
     367                if (wct < 1) {
     368                        TALLOC_FREE(subreq);
     369                        tevent_req_nterror(
     370                                req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     371                        return;
     372                }
     373                received = SVAL(vwv + 0, 0);
     374        }
     375
     376        if (received > 0) {
     377                /*
     378                 * I don't think this can wrap. received is
     379                 * initialized from a 16-bit value.
     380                 */
     381                if (num_bytes < (received * DIR_STRUCT_SIZE + 3)) {
     382                        TALLOC_FREE(subreq);
     383                        tevent_req_nterror(
     384                                req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     385                        return;
     386                }
     387
     388                dirlist_len = talloc_get_size(state->dirlist);
     389
     390                tmp = TALLOC_REALLOC_ARRAY(
     391                        state, state->dirlist, uint8_t,
     392                        dirlist_len + received * DIR_STRUCT_SIZE);
     393                if (tevent_req_nomem(tmp, req)) {
     394                        return;
     395                }
     396                state->dirlist = tmp;
     397                memcpy(state->dirlist + dirlist_len, bytes + 3,
     398                       received * DIR_STRUCT_SIZE);
     399
     400                SSVAL(state->search_status, 0, 21);
     401                memcpy(state->search_status + 2,
     402                       bytes + 3 + (received-1)*DIR_STRUCT_SIZE, 21);
     403                cmd = SMBsearch;
     404        } else {
     405                if (state->first || state->done) {
     406                        tevent_req_done(req);
     407                        return;
     408                }
     409                state->done = true;
     410                state->num_asked = 0;
     411                cmd = SMBfclose;
     412        }
     413        TALLOC_FREE(subreq);
     414
     415        state->first = false;
     416
     417        SSVAL(state->vwv + 0, 0, state->num_asked);
     418        SSVAL(state->vwv + 1, 0, state->attribute);
     419
     420        bytes = talloc_array(state, uint8_t, 1);
     421        if (tevent_req_nomem(bytes, req)) {
     422                return;
     423        }
     424        bytes[0] = 4;
     425        bytes = smb_bytes_push_str(bytes, cli_ucs2(state->cli), "",
     426                                   1, NULL);
     427        bytes = smb_bytes_push_bytes(bytes, 5, state->search_status,
     428                                     sizeof(state->search_status));
     429        if (tevent_req_nomem(bytes, req)) {
     430                return;
     431        }
     432        subreq = cli_smb_send(state, state->ev, state->cli, cmd, 0,
     433                              2, state->vwv, talloc_get_size(bytes), bytes);
     434        if (tevent_req_nomem(subreq, req)) {
     435                return;
     436        }
     437        tevent_req_set_callback(subreq, cli_list_old_done, req);
     438}
     439
     440static NTSTATUS cli_list_old_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     441                                  struct file_info **pfinfo)
     442{
     443        struct cli_list_old_state *state = tevent_req_data(
     444                req, struct cli_list_old_state);
     445        NTSTATUS status;
     446        size_t i, num_received;
     447        struct file_info *finfo;
     448
     449        if (tevent_req_is_nterror(req, &status)) {
     450                return status;
     451        }
     452
     453        num_received = talloc_array_length(state->dirlist) / DIR_STRUCT_SIZE;
     454
     455        finfo = TALLOC_ARRAY(mem_ctx, struct file_info, num_received);
     456        if (finfo == NULL) {
     457                return NT_STATUS_NO_MEMORY;
     458        }
     459
     460        for (i=0; i<num_received; i++) {
     461                if (!interpret_short_filename(
     462                            finfo, state->cli,
     463                            (char *)state->dirlist + i * DIR_STRUCT_SIZE,
     464                            &finfo[i])) {
     465                        TALLOC_FREE(finfo);
     466                        return NT_STATUS_NO_MEMORY;
     467                }
     468        }
     469        *pfinfo = finfo;
     470        return NT_STATUS_OK;
     471}
     472
     473NTSTATUS cli_list_old(struct cli_state *cli, const char *mask,
     474                      uint16 attribute,
     475                      NTSTATUS (*fn)(const char *, struct file_info *,
     476                                 const char *, void *), void *state)
     477{
     478        TALLOC_CTX *frame = talloc_stackframe();
     479        struct event_context *ev;
     480        struct tevent_req *req;
     481        NTSTATUS status = NT_STATUS_NO_MEMORY;
     482        struct file_info *finfo;
     483        size_t i, num_finfo;
     484
     485        if (cli_has_async_calls(cli)) {
     486                /*
     487                 * Can't use sync call while an async call is in flight
     488                 */
     489                status = NT_STATUS_INVALID_PARAMETER;
     490                goto fail;
     491        }
     492        ev = event_context_init(frame);
     493        if (ev == NULL) {
     494                goto fail;
     495        }
     496        req = cli_list_old_send(frame, ev, cli, mask, attribute);
     497        if (req == NULL) {
     498                goto fail;
     499        }
     500        if (!tevent_req_poll(req, ev)) {
     501                status = map_nt_error_from_unix(errno);
     502                goto fail;
     503        }
     504        status = cli_list_old_recv(req, frame, &finfo);
     505        if (!NT_STATUS_IS_OK(status)) {
     506                goto fail;
     507        }
     508        num_finfo = talloc_array_length(finfo);
     509        for (i=0; i<num_finfo; i++) {
     510                status = fn(cli->dfs_mountpoint, &finfo[i], mask, state);
     511                if (!NT_STATUS_IS_OK(status)) {
     512                        goto fail;
     513                }
     514        }
     515 fail:
     516        TALLOC_FREE(frame);
     517        if (!NT_STATUS_IS_OK(status)) {
     518                cli_set_error(cli, status);
     519        }
     520        return status;
     521}
     522
     523struct cli_list_trans_state {
     524        struct tevent_context *ev;
     525        struct cli_state *cli;
     526        char *mask;
     527        uint16_t attribute;
     528        uint16_t info_level;
     529
     530        int loop_count;
     531        int total_received;
     532        uint16_t max_matches;
     533        bool first;
     534
     535        int ff_eos;
     536        int ff_dir_handle;
     537
     538        uint16_t setup[1];
     539        uint8_t *param;
     540
     541        struct file_info *finfo;
     542};
     543
     544static void cli_list_trans_done(struct tevent_req *subreq);
     545
     546static struct tevent_req *cli_list_trans_send(TALLOC_CTX *mem_ctx,
     547                                              struct tevent_context *ev,
     548                                              struct cli_state *cli,
     549                                              const char *mask,
     550                                              uint16_t attribute,
     551                                              uint16_t info_level)
     552{
     553        struct tevent_req *req, *subreq;
     554        struct cli_list_trans_state *state;
     555        size_t nlen, param_len;
    545556        char *p;
    546         int received = 0;
    547         bool first = True;
    548         char status[21];
    549         int num_asked = (cli->max_xmit - 100)/DIR_STRUCT_SIZE;
    550         int num_received = 0;
     557
     558        req = tevent_req_create(mem_ctx, &state,
     559                                struct cli_list_trans_state);
     560        if (req == NULL) {
     561                return NULL;
     562        }
     563        state->ev = ev;
     564        state->cli = cli;
     565        state->mask = talloc_strdup(state, mask);
     566        if (tevent_req_nomem(state->mask, req)) {
     567                return tevent_req_post(req, ev);
     568        }
     569        state->attribute = attribute;
     570        state->info_level = info_level;
     571        state->loop_count = 0;
     572        state->first = true;
     573
     574        state->max_matches = 1366; /* Match W2k */
     575
     576        SSVAL(&state->setup[0], 0, TRANSACT2_FINDFIRST);
     577
     578        nlen = 2*(strlen(mask)+1);
     579        state->param = TALLOC_ARRAY(state, uint8_t, 12+nlen+2);
     580        if (tevent_req_nomem(state->param, req)) {
     581                return tevent_req_post(req, ev);
     582        }
     583
     584        SSVAL(state->param, 0, state->attribute);
     585        SSVAL(state->param, 2, state->max_matches);
     586        SSVAL(state->param, 4,
     587              FLAG_TRANS2_FIND_REQUIRE_RESUME
     588              |FLAG_TRANS2_FIND_CLOSE_IF_END);
     589        SSVAL(state->param, 6, state->info_level);
     590        SIVAL(state->param, 8, 0);
     591
     592        p = ((char *)state->param)+12;
     593        p += clistr_push(state->cli, p, state->mask, nlen,
     594                         STR_TERMINATE);
     595        param_len = PTR_DIFF(p, state->param);
     596
     597        subreq = cli_trans_send(state, state->ev, state->cli,
     598                                SMBtrans2, NULL, -1, 0, 0,
     599                                state->setup, 1, 0,
     600                                state->param, param_len, 10,
     601                                NULL, 0, cli->max_xmit);
     602        if (tevent_req_nomem(subreq, req)) {
     603                return tevent_req_post(req, ev);
     604        }
     605        tevent_req_set_callback(subreq, cli_list_trans_done, req);
     606        return req;
     607}
     608
     609static void cli_list_trans_done(struct tevent_req *subreq)
     610{
     611        struct tevent_req *req = tevent_req_callback_data(
     612                subreq, struct tevent_req);
     613        struct cli_list_trans_state *state = tevent_req_data(
     614                req, struct cli_list_trans_state);
     615        NTSTATUS status;
     616        uint8_t *param;
     617        uint32_t num_param;
     618        uint8_t *data;
     619        char *data_end;
     620        uint32_t num_data;
     621        uint32_t min_param;
     622        struct file_info *tmp;
     623        size_t old_num_finfo;
     624        uint16_t recv_flags2;
     625        int ff_searchcount;
     626        bool ff_eos;
     627        char *p, *p2;
     628        uint32_t resume_key = 0;
    551629        int i;
    552         char *dirlist = NULL;
    553         char *mask = NULL;
    554         TALLOC_CTX *frame = NULL;
    555 
    556         ZERO_ARRAY(status);
    557 
    558         mask = SMB_STRDUP(Mask);
    559         if (!mask) {
    560                 return -1;
    561         }
    562 
    563         while (1) {
    564                 memset(cli->outbuf,'\0',smb_size);
    565                 memset(cli->inbuf,'\0',smb_size);
    566 
    567                 cli_set_message(cli->outbuf,2,0,True);
    568 
    569                 SCVAL(cli->outbuf,smb_com,SMBsearch);
    570 
    571                 SSVAL(cli->outbuf,smb_tid,cli->cnum);
    572                 cli_setup_packet(cli);
    573 
    574                 SSVAL(cli->outbuf,smb_vwv0,num_asked);
    575                 SSVAL(cli->outbuf,smb_vwv1,attribute);
    576 
    577                 p = smb_buf(cli->outbuf);
    578                 *p++ = 4;
    579 
    580                 p += clistr_push(cli, p, first?mask:"",
    581                                 cli->bufsize - PTR_DIFF(p,cli->outbuf),
    582                                 STR_TERMINATE);
    583                 *p++ = 5;
    584                 if (first) {
    585                         SSVAL(p,0,0);
    586                         p += 2;
    587                 } else {
    588                         SSVAL(p,0,21);
    589                         p += 2;
    590                         memcpy(p,status,21);
    591                         p += 21;
    592                 }
    593 
    594                 cli_setup_bcc(cli, p);
    595                 cli_send_smb(cli);
    596                 if (!cli_receive_smb(cli)) break;
    597 
    598                 received = SVAL(cli->inbuf,smb_vwv0);
    599                 if (received <= 0) break;
    600 
    601                 /* Ensure we received enough data. */
    602                 if ((cli->inbuf+4+smb_len(cli->inbuf) - (smb_buf(cli->inbuf)+3)) <
    603                                 received*DIR_STRUCT_SIZE) {
     630        DATA_BLOB last_name_raw;
     631        struct file_info *finfo = NULL;
     632        size_t nlen, param_len;
     633
     634        min_param = (state->first ? 6 : 4);
     635
     636        status = cli_trans_recv(subreq, talloc_tos(), &recv_flags2,
     637                                NULL, 0, NULL,
     638                                &param, min_param, &num_param,
     639                                &data, 0, &num_data);
     640        TALLOC_FREE(subreq);
     641        if (!NT_STATUS_IS_OK(status)) {
     642                /*
     643                 * TODO: retry, OS/2 nofiles
     644                 */
     645                tevent_req_nterror(req, status);
     646                return;
     647        }
     648
     649        if (state->first) {
     650                state->ff_dir_handle = SVAL(param, 0);
     651                ff_searchcount = SVAL(param, 2);
     652                ff_eos = SVAL(param, 4) != 0;
     653        } else {
     654                ff_searchcount = SVAL(param, 0);
     655                ff_eos = SVAL(param, 2) != 0;
     656        }
     657
     658        old_num_finfo = talloc_array_length(state->finfo);
     659
     660        tmp = TALLOC_REALLOC_ARRAY(state, state->finfo, struct file_info,
     661                                   old_num_finfo + ff_searchcount);
     662        if (tevent_req_nomem(tmp, req)) {
     663                return;
     664        }
     665        state->finfo = tmp;
     666
     667        p2 = p = (char *)data;
     668        data_end = (char *)data + num_data;
     669        last_name_raw = data_blob_null;
     670
     671        for (i=0; i<ff_searchcount; i++) {
     672                if (p2 >= data_end) {
     673                        ff_eos = true;
    604674                        break;
    605675                }
    606 
    607                 first = False;
    608 
    609                 dirlist = (char *)SMB_REALLOC(
    610                         dirlist,(num_received + received)*DIR_STRUCT_SIZE);
    611                 if (!dirlist) {
    612                         DEBUG(0,("cli_list_old: failed to expand dirlist"));
    613                         SAFE_FREE(mask);
    614                         return 0;
    615                 }
    616 
    617                 p = smb_buf(cli->inbuf) + 3;
    618 
    619                 memcpy(dirlist+num_received*DIR_STRUCT_SIZE,
    620                        p,received*DIR_STRUCT_SIZE);
    621 
    622                 memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21);
    623 
    624                 num_received += received;
    625 
    626                 if (cli_is_error(cli)) break;
    627         }
    628 
    629         if (!first) {
    630                 memset(cli->outbuf,'\0',smb_size);
    631                 memset(cli->inbuf,'\0',smb_size);
    632 
    633                 cli_set_message(cli->outbuf,2,0,True);
    634                 SCVAL(cli->outbuf,smb_com,SMBfclose);
    635                 SSVAL(cli->outbuf,smb_tid,cli->cnum);
    636                 cli_setup_packet(cli);
    637 
    638                 SSVAL(cli->outbuf, smb_vwv0, 0); /* find count? */
    639                 SSVAL(cli->outbuf, smb_vwv1, attribute);
    640 
    641                 p = smb_buf(cli->outbuf);
    642                 *p++ = 4;
    643                 fstrcpy(p, "");
    644                 p += strlen(p) + 1;
    645                 *p++ = 5;
    646                 SSVAL(p, 0, 21);
    647                 p += 2;
    648                 memcpy(p,status,21);
    649                 p += 21;
    650 
    651                 cli_setup_bcc(cli, p);
    652                 cli_send_smb(cli);
    653                 if (!cli_receive_smb(cli)) {
    654                         DEBUG(0,("Error closing search: %s\n",cli_errstr(cli)));
    655                 }
    656         }
    657 
    658         frame = talloc_stackframe();
    659         for (p=dirlist,i=0;i<num_received;i++) {
    660                 file_info finfo;
    661                 if (!interpret_short_filename(frame, cli, p, &finfo)) {
     676                if ((state->info_level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO)
     677                    && (i == ff_searchcount-1)) {
     678                        /* Last entry - fixup the last offset length. */
     679                        SIVAL(p2, 0, PTR_DIFF((data + num_data), p2));
     680                }
     681
     682                data_blob_free(&last_name_raw);
     683
     684                finfo = &state->finfo[old_num_finfo + i];
     685
     686                p2 += interpret_long_filename(
     687                        state->finfo, /* Stick fname to the array as such */
     688                        state->cli, state->info_level,
     689                        (char *)data, recv_flags2, p2,
     690                        data_end, finfo, &resume_key, &last_name_raw);
     691
     692                if (finfo->name == NULL) {
     693                        DEBUG(1, ("cli_list: Error: unable to parse name from "
     694                                  "info level %d\n", state->info_level));
     695                        ff_eos = true;
    662696                        break;
    663697                }
    664                 p += DIR_STRUCT_SIZE;
    665                 fn("\\", &finfo, Mask, state);
    666         }
     698                if (!state->first && (state->mask[0] != '\0') &&
     699                    strcsequal(finfo->name, state->mask)) {
     700                        DEBUG(1, ("Error: Looping in FIND_NEXT as name %s has "
     701                                  "already been seen?\n", finfo->name));
     702                        ff_eos = true;
     703                        break;
     704                }
     705        }
     706
     707        if (ff_searchcount == 0) {
     708                ff_eos = true;
     709        }
     710
     711        TALLOC_FREE(param);
     712        TALLOC_FREE(data);
     713
     714        /*
     715         * Shrink state->finfo to the real length we received
     716         */
     717        tmp = TALLOC_REALLOC_ARRAY(state, state->finfo, struct file_info,
     718                                   old_num_finfo + i);
     719        if (tevent_req_nomem(tmp, req)) {
     720                return;
     721        }
     722        state->finfo = tmp;
     723
     724        state->first = false;
     725
     726        if (ff_eos) {
     727                data_blob_free(&last_name_raw);
     728                tevent_req_done(req);
     729                return;
     730        }
     731
     732        TALLOC_FREE(state->mask);
     733        state->mask = talloc_strdup(state, finfo->name);
     734        if (tevent_req_nomem(state->mask, req)) {
     735                return;
     736        }
     737
     738        SSVAL(&state->setup[0], 0, TRANSACT2_FINDNEXT);
     739
     740        nlen = 2*(strlen(state->mask) + 1);
     741
     742        param = TALLOC_REALLOC_ARRAY(state, state->param, uint8_t,
     743                                     12 + nlen + last_name_raw.length + 2);
     744        if (tevent_req_nomem(param, req)) {
     745                return;
     746        }
     747        state->param = param;
     748
     749        SSVAL(param, 0, state->ff_dir_handle);
     750        SSVAL(param, 2, state->max_matches); /* max count */
     751        SSVAL(param, 4, state->info_level);
     752        /*
     753         * For W2K servers serving out FAT filesystems we *must* set
     754         * the resume key. If it's not FAT then it's returned as zero.
     755         */
     756        SIVAL(param, 6, resume_key); /* ff_resume_key */
     757        /*
     758         * NB. *DON'T* use continue here. If you do it seems that W2K
     759         * and bretheren can miss filenames. Use last filename
     760         * continue instead. JRA
     761         */
     762        SSVAL(param, 10, (FLAG_TRANS2_FIND_REQUIRE_RESUME
     763                          |FLAG_TRANS2_FIND_CLOSE_IF_END));
     764        p = ((char *)param)+12;
     765        if (last_name_raw.length) {
     766                memcpy(p, last_name_raw.data, last_name_raw.length);
     767                p += last_name_raw.length;
     768                data_blob_free(&last_name_raw);
     769        } else {
     770                p += clistr_push(state->cli, p, state->mask, nlen,
     771                                 STR_TERMINATE);
     772        }
     773
     774        param_len = PTR_DIFF(p, param);
     775
     776        subreq = cli_trans_send(state, state->ev, state->cli,
     777                                SMBtrans2, NULL, -1, 0, 0,
     778                                state->setup, 1, 0,
     779                                state->param, param_len, 10,
     780                                NULL, 0, state->cli->max_xmit);
     781        if (tevent_req_nomem(subreq, req)) {
     782                return;
     783        }
     784        tevent_req_set_callback(subreq, cli_list_trans_done, req);
     785}
     786
     787static NTSTATUS cli_list_trans_recv(struct tevent_req *req,
     788                                    TALLOC_CTX *mem_ctx,
     789                                    struct file_info **finfo)
     790{
     791        struct cli_list_trans_state *state = tevent_req_data(
     792                req, struct cli_list_trans_state);
     793        NTSTATUS status;
     794
     795        if (tevent_req_is_nterror(req, &status)) {
     796                return status;
     797        }
     798        *finfo = talloc_move(mem_ctx, &state->finfo);
     799        return NT_STATUS_OK;
     800}
     801
     802NTSTATUS cli_list_trans(struct cli_state *cli, const char *mask,
     803                        uint16_t attribute, int info_level,
     804                        NTSTATUS (*fn)(const char *mnt, struct file_info *finfo,
     805                                   const char *mask, void *private_data),
     806                        void *private_data)
     807{
     808        TALLOC_CTX *frame = talloc_stackframe();
     809        struct event_context *ev;
     810        struct tevent_req *req;
     811        int i, num_finfo;
     812        struct file_info *finfo = NULL;
     813        NTSTATUS status = NT_STATUS_NO_MEMORY;
     814
     815        if (cli_has_async_calls(cli)) {
     816                /*
     817                 * Can't use sync call while an async call is in flight
     818                 */
     819                status = NT_STATUS_INVALID_PARAMETER;
     820                goto fail;
     821        }
     822        ev = event_context_init(frame);
     823        if (ev == NULL) {
     824                goto fail;
     825        }
     826        req = cli_list_trans_send(frame, ev, cli, mask, attribute, info_level);
     827        if (req == NULL) {
     828                goto fail;
     829        }
     830        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     831                goto fail;
     832        }
     833        status = cli_list_trans_recv(req, frame, &finfo);
     834        if (!NT_STATUS_IS_OK(status)) {
     835                goto fail;
     836        }
     837        num_finfo = talloc_array_length(finfo);
     838        for (i=0; i<num_finfo; i++) {
     839                status = fn(cli->dfs_mountpoint, &finfo[i], mask, private_data);
     840                if (!NT_STATUS_IS_OK(status)) {
     841                        goto fail;
     842                }
     843        }
     844 fail:
    667845        TALLOC_FREE(frame);
    668 
    669         SAFE_FREE(mask);
    670         SAFE_FREE(dirlist);
    671         return(num_received);
    672 }
    673 
    674 /****************************************************************************
    675  Do a directory listing, calling fn on each file found.
    676  This auto-switches between old and new style.
    677 ****************************************************************************/
    678 
    679 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
    680              void (*fn)(const char *, file_info *, const char *, void *), void *state)
    681 {
    682         if (cli->protocol <= PROTOCOL_LANMAN1)
    683                 return cli_list_old(cli, Mask, attribute, fn, state);
    684         return cli_list_new(cli, Mask, attribute, fn, state);
    685 }
     846        if (!NT_STATUS_IS_OK(status)) {
     847                cli_set_error(cli, status);
     848        }
     849        return status;
     850}
     851
     852struct cli_list_state {
     853        NTSTATUS (*recv_fn)(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     854                            struct file_info **finfo);
     855        struct file_info *finfo;
     856};
     857
     858static void cli_list_done(struct tevent_req *subreq);
     859
     860struct tevent_req *cli_list_send(TALLOC_CTX *mem_ctx,
     861                                 struct tevent_context *ev,
     862                                 struct cli_state *cli,
     863                                 const char *mask,
     864                                 uint16_t attribute,
     865                                 uint16_t info_level)
     866{
     867        struct tevent_req *req, *subreq;
     868        struct cli_list_state *state;
     869
     870        req = tevent_req_create(mem_ctx, &state, struct cli_list_state);
     871        if (req == NULL) {
     872                return NULL;
     873        }
     874
     875        if (cli->protocol <= PROTOCOL_LANMAN1) {
     876                subreq = cli_list_old_send(state, ev, cli, mask, attribute);
     877                state->recv_fn = cli_list_old_recv;
     878        } else {
     879                subreq = cli_list_trans_send(state, ev, cli, mask, attribute,
     880                                             info_level);
     881                state->recv_fn = cli_list_trans_recv;
     882        }
     883        if (tevent_req_nomem(subreq, req)) {
     884                return tevent_req_post(req, ev);
     885        }
     886        tevent_req_set_callback(subreq, cli_list_done, req);
     887        return req;
     888}
     889
     890static void cli_list_done(struct tevent_req *subreq)
     891{
     892        struct tevent_req *req = tevent_req_callback_data(
     893                subreq, struct tevent_req);
     894        struct cli_list_state *state = tevent_req_data(
     895                req, struct cli_list_state);
     896        NTSTATUS status;
     897
     898        status = state->recv_fn(subreq, state, &state->finfo);
     899        TALLOC_FREE(subreq);
     900        if (!NT_STATUS_IS_OK(status)) {
     901                tevent_req_nterror(req, status);
     902                return;
     903        }
     904        tevent_req_done(req);
     905}
     906
     907NTSTATUS cli_list_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     908                       struct file_info **finfo, size_t *num_finfo)
     909{
     910        struct cli_list_state *state = tevent_req_data(
     911                req, struct cli_list_state);
     912        NTSTATUS status;
     913
     914        if (tevent_req_is_nterror(req, &status)) {
     915                return status;
     916        }
     917        *num_finfo = talloc_array_length(state->finfo);
     918        *finfo = talloc_move(mem_ctx, &state->finfo);
     919        return NT_STATUS_OK;
     920}
     921
     922NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16 attribute,
     923                  NTSTATUS (*fn)(const char *, struct file_info *, const char *,
     924                             void *), void *state)
     925{
     926        TALLOC_CTX *frame = talloc_stackframe();
     927        struct event_context *ev;
     928        struct tevent_req *req;
     929        NTSTATUS status = NT_STATUS_NO_MEMORY;
     930        struct file_info *finfo;
     931        size_t i, num_finfo;
     932        uint16_t info_level;
     933
     934        if (cli_has_async_calls(cli)) {
     935                /*
     936                 * Can't use sync call while an async call is in flight
     937                 */
     938                status = NT_STATUS_INVALID_PARAMETER;
     939                goto fail;
     940        }
     941        ev = event_context_init(frame);
     942        if (ev == NULL) {
     943                goto fail;
     944        }
     945
     946        info_level = (cli->capabilities & CAP_NT_SMBS)
     947                ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_INFO_STANDARD;
     948
     949        req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
     950        if (req == NULL) {
     951                goto fail;
     952        }
     953        if (!tevent_req_poll(req, ev)) {
     954                status = map_nt_error_from_unix(errno);
     955                goto fail;
     956        }
     957
     958        status = cli_list_recv(req, frame, &finfo, &num_finfo);
     959        if (!NT_STATUS_IS_OK(status)) {
     960                goto fail;
     961        }
     962
     963        for (i=0; i<num_finfo; i++) {
     964                status = fn(cli->dfs_mountpoint, &finfo[i], mask, state);
     965                if (!NT_STATUS_IS_OK(status)) {
     966                        goto fail;
     967                }
     968        }
     969 fail:
     970        TALLOC_FREE(frame);
     971        if (!NT_STATUS_IS_OK(status)) {
     972                cli_set_error(cli, status);
     973        }
     974        return status;
     975}
  • vendor/current/source3/libsmb/climessage.c

    r587 r740  
    1919
    2020#include "includes.h"
     21#include "../lib/util/tevent_ntstatus.h"
     22#include "async_smb.h"
     23#include "libsmb/libsmb.h"
    2124
    2225struct cli_message_start_state {
     
    9497        uint8_t wct;
    9598        uint16_t *vwv;
    96 
    97         status = cli_smb_recv(subreq, 0, &wct, &vwv, NULL, NULL);
     99        uint8_t *inbuf;
     100
     101        status = cli_smb_recv(subreq, state, &inbuf, 0, &wct, &vwv,
     102                              NULL, NULL);
     103        TALLOC_FREE(subreq);
    98104        if (!NT_STATUS_IS_OK(status)) {
    99105                TALLOC_FREE(subreq);
     
    106112                state->grp = 0;
    107113        }
    108         TALLOC_FREE(subreq);
    109114        tevent_req_done(req);
    110115}
     
    186191        NTSTATUS status;
    187192
    188         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     193        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    189194        TALLOC_FREE(subreq);
    190195        if (!NT_STATUS_IS_OK(status)) {
     
    237242        NTSTATUS status;
    238243
    239         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     244        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    240245        TALLOC_FREE(subreq);
    241246        if (!NT_STATUS_IS_OK(status)) {
  • vendor/current/source3/libsmb/clioplock.c

    r414 r740  
    1919
    2020#include "includes.h"
     21#include "../lib/util/tevent_ntstatus.h"
     22#include "async_smb.h"
     23#include "libsmb/libsmb.h"
    2124
    2225/****************************************************************************
     
    3841        struct cli_oplock_ack_state *state;
    3942
    40         req = tevent_req_create(mem_ctx, &state, struct cli_oplock_ack_state);;
     43        req = tevent_req_create(mem_ctx, &state, struct cli_oplock_ack_state);
    4144        if (req == NULL) {
    4245                return NULL;
     
    6770        NTSTATUS status;
    6871
    69         status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
     72        status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
    7073        TALLOC_FREE(subreq);
    7174        if (!NT_STATUS_IS_OK(status)) {
  • vendor/current/source3/libsmb/cliprint.c

    r414 r740  
    1919
    2020#include "includes.h"
     21#include "libsmb/libsmb.h"
     22#include "libsmb/clirap.h"
    2123
    2224/*****************************************************************************
     
    2830                          char *rdata, int rdrcnt)
    2931{
     32        unsigned int offset;
     33
    3034        if (datap == 0) {
    3135                /* turn NULL pointers into zero length strings */
    3236                return "";
    33         } else {
    34                 unsigned int offset = datap - converter;
     37        }
    3538
    36                 if (offset >= rdrcnt) {
    37                         DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
    38                                  datap, converter, rdrcnt));
    39                         return "<ERROR>";
    40                 } else {
    41                         return &rdata[offset];
    42                 }
     39        offset = datap - converter;
     40
     41        if (offset >= rdrcnt) {
     42                DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
     43                         datap, converter, rdrcnt));
     44                return "<ERROR>";
    4345        }
     46        return &rdata[offset];
    4447}
    4548
     
    98101                                        fix_char_ptr(SVAL(p,4), converter,
    99102                                                     rdata, rdrcnt));
    100                                 job.t = cli_make_unix_date3(cli, p + 12);
     103                                job.t = make_unix_date3(
     104                                        p + 12, cli->serverzone);
    101105                                job.size = IVAL(p,16);
    102106                                fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
     
    154158        return ret;
    155159}
    156 
    157 
    158 /****************************************************************************
    159  Open a spool file
    160 ****************************************************************************/
    161 
    162 int cli_spl_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
    163 {
    164         char *p;
    165         unsigned openfn=0;
    166         unsigned accessmode=0;
    167 
    168         if (flags & O_CREAT)
    169                 openfn |= (1<<4);
    170         if (!(flags & O_EXCL)) {
    171                 if (flags & O_TRUNC)
    172                         openfn |= (1<<1);
    173                 else
    174                         openfn |= (1<<0);
    175         }
    176 
    177         accessmode = (share_mode<<4);
    178 
    179         if ((flags & O_ACCMODE) == O_RDWR) {
    180                 accessmode |= 2;
    181         } else if ((flags & O_ACCMODE) == O_WRONLY) {
    182                 accessmode |= 1;
    183         }
    184 
    185 #if defined(O_SYNC)
    186         if ((flags & O_SYNC) == O_SYNC) {
    187                 accessmode |= (1<<14);
    188         }
    189 #endif /* O_SYNC */
    190 
    191         if (share_mode == DENY_FCB) {
    192                 accessmode = 0xFF;
    193         }
    194 
    195         memset(cli->outbuf,'\0',smb_size);
    196         memset(cli->inbuf,'\0',smb_size);
    197 
    198         cli_set_message(cli->outbuf,15,0,True);
    199 
    200         SCVAL(cli->outbuf,smb_com,SMBsplopen);
    201         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    202         cli_setup_packet(cli);
    203 
    204         SSVAL(cli->outbuf,smb_vwv0,0xFF);
    205         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
    206         SSVAL(cli->outbuf,smb_vwv3,accessmode);
    207         SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
    208         SSVAL(cli->outbuf,smb_vwv5,0);
    209         SSVAL(cli->outbuf,smb_vwv8,openfn);
    210 
    211         if (cli->use_oplocks) {
    212                 /* if using oplocks then ask for a batch oplock via
    213                    core and extended methods */
    214                 SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
    215                         FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
    216                 SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
    217         }
    218 
    219         p = smb_buf(cli->outbuf);
    220         p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
    221 
    222         cli_setup_bcc(cli, p);
    223 
    224         cli_send_smb(cli);
    225         if (!cli_receive_smb(cli)) {
    226                 return -1;
    227         }
    228 
    229         if (cli_is_error(cli)) {
    230                 return -1;
    231         }
    232 
    233         return SVAL(cli->inbuf,smb_vwv2);
    234 }
    235 
    236 /****************************************************************************
    237  Close a file.
    238 ****************************************************************************/
    239 
    240 bool cli_spl_close(struct cli_state *cli, uint16_t fnum)
    241 {
    242         memset(cli->outbuf,'\0',smb_size);
    243         memset(cli->inbuf,'\0',smb_size);
    244 
    245         cli_set_message(cli->outbuf,3,0,True);
    246 
    247         SCVAL(cli->outbuf,smb_com,SMBsplclose);
    248         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    249         cli_setup_packet(cli);
    250 
    251         SSVAL(cli->outbuf,smb_vwv0,fnum);
    252         SIVALS(cli->outbuf,smb_vwv1,-1);
    253 
    254         cli_send_smb(cli);
    255         if (!cli_receive_smb(cli)) {
    256                 return False;
    257         }
    258 
    259         return !cli_is_error(cli);
    260 }
  • vendor/current/source3/libsmb/cliquota.c

    r581 r740  
    1919
    2020#include "includes.h"
     21#include "libsmb/libsmb.h"
     22#include "../librpc/gen_ndr/ndr_security.h"
     23#include "fake_file.h"
     24#include "../libcli/security/security.h"
     25#include "trans2.h"
    2126
    2227NTSTATUS cli_get_quota_handle(struct cli_state *cli, uint16_t *quota_fnum)
     
    4146}
    4247
    43 static bool parse_user_quota_record(const char *rdata, unsigned int rdata_count, unsigned int *offset, SMB_NTQUOTA_STRUCT *pqt)
     48static bool parse_user_quota_record(const uint8_t *rdata,
     49                                    unsigned int rdata_count,
     50                                    unsigned int *offset,
     51                                    SMB_NTQUOTA_STRUCT *pqt)
    4452{
    4553        int sid_len;
     
    7482
    7583        /* the used space 8 bytes (uint64_t)*/
    76         qt.usedspace = (uint64_t)IVAL(rdata,16);
    77 #ifdef LARGE_SMB_OFF_T
    78         qt.usedspace |= (((uint64_t)IVAL(rdata,20)) << 32);
    79 #else /* LARGE_SMB_OFF_T */
    80         if ((IVAL(rdata,20) != 0)&&
    81                 ((qt.usedspace != 0xFFFFFFFF)||
    82                  (IVAL(rdata,20)!=0xFFFFFFFF))) {
    83                 /* more than 32 bits? */
    84                 return False;
    85         }
    86 #endif /* LARGE_SMB_OFF_T */
     84        qt.usedspace = BVAL(rdata,16);
    8785
    8886        /* the soft quotas 8 bytes (uint64_t)*/
    89         qt.softlim = (uint64_t)IVAL(rdata,24);
    90 #ifdef LARGE_SMB_OFF_T
    91         qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
    92 #else /* LARGE_SMB_OFF_T */
    93         if ((IVAL(rdata,28) != 0)&&
    94                 ((qt.softlim != 0xFFFFFFFF)||
    95                  (IVAL(rdata,28)!=0xFFFFFFFF))) {
    96                 /* more than 32 bits? */
    97                 return False;
    98         }
    99 #endif /* LARGE_SMB_OFF_T */
     87        qt.softlim = BVAL(rdata,24);
    10088
    10189        /* the hard quotas 8 bytes (uint64_t)*/
    102         qt.hardlim = (uint64_t)IVAL(rdata,32);
    103 #ifdef LARGE_SMB_OFF_T
    104         qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
    105 #else /* LARGE_SMB_OFF_T */
    106         if ((IVAL(rdata,36) != 0)&&
    107                 ((qt.hardlim != 0xFFFFFFFF)||
    108                  (IVAL(rdata,36)!=0xFFFFFFFF))) {
    109                 /* more than 32 bits? */
    110                 return False;
    111         }
    112 #endif /* LARGE_SMB_OFF_T */
    113 
    114         if (!sid_parse(rdata+40,sid_len,&qt.sid)) {
     90        qt.hardlim = BVAL(rdata,32);
     91
     92        if (!sid_parse((char *)rdata+40,sid_len,&qt.sid)) {
    11593                return false;
    11694        }
     
    123101}
    124102
    125 bool cli_get_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
    126 {
    127         bool ret = False;
    128         uint16 setup;
    129         char params[16];
     103NTSTATUS cli_get_user_quota(struct cli_state *cli, int quota_fnum,
     104                            SMB_NTQUOTA_STRUCT *pqt)
     105{
     106        uint16_t setup[1];
     107        uint8_t params[16];
    130108        unsigned int data_len;
    131         char data[SID_MAX_SIZE+8];
    132         char *rparam=NULL, *rdata=NULL;
    133         unsigned int rparam_count=0, rdata_count=0;
     109        uint8_t data[SID_MAX_SIZE+8];
     110        uint8_t *rparam, *rdata;
     111        uint32_t rparam_count, rdata_count;
    134112        unsigned int sid_len;
    135113        unsigned int offset;
     114        NTSTATUS status;
    136115
    137116        if (!cli||!pqt) {
     
    139118        }
    140119
    141         setup = NT_TRANSACT_GET_USER_QUOTA;
     120        SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
    142121
    143122        SSVAL(params, 0,quota_fnum);
     
    147126        SIVAL(params,12,0x00000024);
    148127
    149         sid_len = ndr_size_dom_sid(&pqt->sid, NULL, 0);
     128        sid_len = ndr_size_dom_sid(&pqt->sid, 0);
    150129        data_len = sid_len+8;
    151130        SIVAL(data, 0, 0x00000000);
    152131        SIVAL(data, 4, sid_len);
    153         sid_linearize(data+8, sid_len, &pqt->sid);
    154 
    155         if (!cli_send_nt_trans(cli,
    156                                NT_TRANSACT_GET_USER_QUOTA,
    157                                0,
    158                                &setup, 1, 0,
    159                                params, 16, 4,
    160                                data, data_len, 112)) {
    161                 DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
    162                 goto cleanup;
    163         }
    164 
    165 
    166         if (!cli_receive_nt_trans(cli,
    167                                   &rparam, &rparam_count,
    168                                   &rdata, &rdata_count)) {
    169                 DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
    170                 goto cleanup;
    171         }
    172 
    173         if (cli_is_error(cli)) {
    174                 ret = False;
    175                 goto cleanup;
    176         } else {
    177                 ret = True;
    178         }
    179 
    180         if ((rparam&&rdata)&&(rparam_count>=4&&rdata_count>=8)) {
    181                 ret = parse_user_quota_record(rdata, rdata_count, &offset, pqt);
    182         } else {
     132        sid_linearize((char *)data+8, sid_len, &pqt->sid);
     133
     134        status = cli_trans(talloc_tos(), cli, SMBnttrans,
     135                           NULL, -1, /* name, fid */
     136                           NT_TRANSACT_GET_USER_QUOTA, 0,
     137                           setup, 1, 0, /* setup */
     138                           params, 16, 4, /* params */
     139                           data, data_len, 112, /* data */
     140                           NULL,                /* recv_flags2 */
     141                           NULL, 0, NULL,       /* rsetup */
     142                           &rparam, 4, &rparam_count,
     143                           &rdata, 8, &rdata_count);
     144        if (!NT_STATUS_IS_OK(status)) {
     145                DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
     146                          nt_errstr(status)));
     147                return status;
     148        }
     149
     150        if (!parse_user_quota_record(rdata, rdata_count, &offset, pqt)) {
     151                status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    183152                DEBUG(0,("Got INVALID NT_TRANSACT_GET_USER_QUOTA reply.\n"));
    184                 ret = False;
    185         }
    186 
    187  cleanup:
    188         SAFE_FREE(rparam);
    189         SAFE_FREE(rdata);
    190         return ret;
    191 }
    192 
    193 bool cli_set_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
    194 {
    195         bool ret = False;
    196         uint16 setup;
    197         char params[2];
    198         char data[112];
    199         char *rparam=NULL, *rdata=NULL;
    200         unsigned int rparam_count=0, rdata_count=0;
     153        }
     154
     155        TALLOC_FREE(rparam);
     156        TALLOC_FREE(rdata);
     157        return status;
     158}
     159
     160NTSTATUS cli_set_user_quota(struct cli_state *cli, int quota_fnum,
     161                            SMB_NTQUOTA_STRUCT *pqt)
     162{
     163        uint16_t setup[1];
     164        uint8_t params[2];
     165        uint8_t data[112];
    201166        unsigned int sid_len;   
     167        NTSTATUS status;
     168
    202169        memset(data,'\0',112);
    203170
     
    206173        }
    207174
    208         setup = NT_TRANSACT_SET_USER_QUOTA;
     175        SSVAL(setup + 0, 0, NT_TRANSACT_SET_USER_QUOTA);
    209176
    210177        SSVAL(params,0,quota_fnum);
    211178
    212         sid_len = ndr_size_dom_sid(&pqt->sid, NULL, 0);
     179        sid_len = ndr_size_dom_sid(&pqt->sid, 0);
    213180        SIVAL(data,0,0);
    214181        SIVAL(data,4,sid_len);
     
    217184        SBIG_UINT(data,24,pqt->softlim);
    218185        SBIG_UINT(data,32,pqt->hardlim);
    219         sid_linearize(data+40, sid_len, &pqt->sid);
    220 
    221         if (!cli_send_nt_trans(cli,
    222                                NT_TRANSACT_SET_USER_QUOTA,
    223                                0,
    224                                &setup, 1, 0,
    225                                params, 2, 0,
    226                                data, 112, 0)) {
    227                 DEBUG(1,("Failed to send NT_TRANSACT_SET_USER_QUOTA\n"));
    228                 goto cleanup;
    229         }
    230 
    231 
    232         if (!cli_receive_nt_trans(cli,
    233                                   &rparam, &rparam_count,
    234                                   &rdata, &rdata_count)) {
    235                 DEBUG(1,("NT_TRANSACT_SET_USER_QUOTA failed\n"));
    236                 goto cleanup;
    237         }
    238 
    239         if (cli_is_error(cli)) {
    240                 ret = False;
    241                 goto cleanup;
    242         } else {
    243                 ret = True;
    244         }
    245 
    246   cleanup:
    247         SAFE_FREE(rparam);
    248         SAFE_FREE(rdata);
    249         return ret;
    250 }
    251 
    252 bool cli_list_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST **pqt_list)
    253 {
    254         bool ret = False;
    255         uint16 setup;
    256         char params[16];
    257         char *rparam=NULL, *rdata=NULL;
    258         unsigned int rparam_count=0, rdata_count=0;
     186        sid_linearize((char *)data+40, sid_len, &pqt->sid);
     187
     188        status = cli_trans(talloc_tos(), cli, SMBnttrans,
     189                           NULL, -1, /* name, fid */
     190                           NT_TRANSACT_SET_USER_QUOTA, 0,
     191                           setup, 1, 0, /* setup */
     192                           params, 2, 0, /* params */
     193                           data, 112, 0, /* data */
     194                           NULL,                /* recv_flags2 */
     195                           NULL, 0, NULL,       /* rsetup */
     196                           NULL, 0, NULL,       /* rparams */
     197                           NULL, 0, NULL);      /* rdata */
     198
     199        if (!NT_STATUS_IS_OK(status)) {
     200                DEBUG(1, ("NT_TRANSACT_SET_USER_QUOTA failed: %s\n",
     201                          nt_errstr(status)));
     202        }
     203
     204        return status;
     205}
     206
     207NTSTATUS cli_list_user_quota(struct cli_state *cli, int quota_fnum,
     208                             SMB_NTQUOTA_LIST **pqt_list)
     209{
     210        uint16_t setup[1];
     211        uint8_t params[16];
     212        uint8_t *rparam=NULL, *rdata=NULL;
     213        uint32_t rparam_count=0, rdata_count=0;
    259214        unsigned int offset;
    260         const char *curdata = NULL;
     215        const uint8_t *curdata = NULL;
    261216        unsigned int curdata_count = 0;
    262217        TALLOC_CTX *mem_ctx = NULL;
    263218        SMB_NTQUOTA_STRUCT qt;
    264219        SMB_NTQUOTA_LIST *tmp_list_ent;
     220        NTSTATUS status;
    265221
    266222        if (!cli||!pqt_list) {
     
    268224        }
    269225
    270         setup = NT_TRANSACT_GET_USER_QUOTA;
     226        SSVAL(setup + 0, 0, NT_TRANSACT_GET_USER_QUOTA);
    271227
    272228        SSVAL(params, 0,quota_fnum);
     
    276232        SIVAL(params,12,0x00000000);
    277233
    278         if (!cli_send_nt_trans(cli,
    279                                NT_TRANSACT_GET_USER_QUOTA,
    280                                0,
    281                                &setup, 1, 0,
    282                                params, 16, 4,
    283                                NULL, 0, 2048)) {
    284                 DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
     234        status = cli_trans(talloc_tos(), cli, SMBnttrans,
     235                           NULL, -1, /* name, fid */
     236                           NT_TRANSACT_GET_USER_QUOTA, 0,
     237                           setup, 1, 0, /* setup */
     238                           params, 16, 4, /* params */
     239                           NULL, 0, 2048, /* data */
     240                           NULL,                /* recv_flags2 */
     241                           NULL, 0, NULL,       /* rsetup */
     242                           &rparam, 0, &rparam_count,
     243                           &rdata, 0, &rdata_count);
     244
     245        if (!NT_STATUS_IS_OK(status)) {
     246                DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
     247                          nt_errstr(status)));
    285248                goto cleanup;
    286         }
    287 
    288 
    289         if (!cli_receive_nt_trans(cli,
    290                                   &rparam, &rparam_count,
    291                                   &rdata, &rdata_count)) {
    292                 DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
    293                 goto cleanup;
    294         }
    295 
    296         if (cli_is_error(cli)) {
    297                 ret = False;
    298                 goto cleanup;
    299         } else {
    300                 ret = True;
    301249        }
    302250
    303251        if (rdata_count == 0) {
    304252                *pqt_list = NULL;
    305                 return True;
     253                return NT_STATUS_OK;
    306254        }
    307255
    308256        if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
    309257                DEBUG(0,("talloc_init() failed\n"));
    310                 return (-1);
     258                return NT_STATUS_NO_MEMORY;
    311259        }
    312260
     
    316264                curdata +=offset,curdata_count -= offset) {
    317265                ZERO_STRUCT(qt);
    318                 if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
     266                if (!parse_user_quota_record((uint8_t *)curdata, curdata_count,
     267                                             &offset, &qt)) {
    319268                        DEBUG(1,("Failed to parse the quota record\n"));
    320269                        goto cleanup;
     
    324273                        DEBUG(0,("TALLOC_ZERO() failed\n"));
    325274                        talloc_destroy(mem_ctx);
    326                         return (-1);
     275                        return NT_STATUS_NO_MEMORY;
    327276                }
    328277
     
    330279                        DEBUG(0,("TALLOC_ZERO() failed\n"));
    331280                        talloc_destroy(mem_ctx);
    332                         return (-1);
     281                        return NT_STATUS_NO_MEMORY;
    333282                }
    334283
     
    341290        SSVAL(params, 2,TRANSACT_GET_USER_QUOTA_LIST_CONTINUE);
    342291        while(1) {
    343                 if (!cli_send_nt_trans(cli,
    344                                        NT_TRANSACT_GET_USER_QUOTA,
    345                                        0,
    346                                        &setup, 1, 0,
    347                                        params, 16, 4,
    348                                        NULL, 0, 2048)) {
    349                         DEBUG(1,("Failed to send NT_TRANSACT_GET_USER_QUOTA\n"));
     292
     293                TALLOC_FREE(rparam);
     294                TALLOC_FREE(rdata);
     295
     296                status = cli_trans(talloc_tos(), cli, SMBnttrans,
     297                                   NULL, -1, /* name, fid */
     298                                   NT_TRANSACT_GET_USER_QUOTA, 0,
     299                                   setup, 1, 0, /* setup */
     300                                   params, 16, 4, /* params */
     301                                   NULL, 0, 2048, /* data */
     302                                   NULL,                /* recv_flags2 */
     303                                   NULL, 0, NULL,       /* rsetup */
     304                                   &rparam, 0, &rparam_count,
     305                                   &rdata, 0, &rdata_count);
     306
     307                if (!NT_STATUS_IS_OK(status)) {
     308                        DEBUG(1, ("NT_TRANSACT_GET_USER_QUOTA failed: %s\n",
     309                                  nt_errstr(status)));
    350310                        goto cleanup;
    351311                }
    352312
    353                 SAFE_FREE(rparam);
    354                 SAFE_FREE(rdata);
    355                 if (!cli_receive_nt_trans(cli,
    356                                           &rparam, &rparam_count,
    357                                           &rdata, &rdata_count)) {
    358                         DEBUG(1,("Failed to recv NT_TRANSACT_GET_USER_QUOTA\n"));
    359                         goto cleanup;
    360                 }
    361 
    362                 if (cli_is_error(cli)) {
    363                         ret = False;
    364                         goto cleanup;
    365                 } else {
    366                         ret = True;
    367                 }
    368 
    369313                if (rdata_count == 0) {
    370                         break; 
     314                        break;
    371315                }
    372316
     
    376320                        curdata +=offset,curdata_count -= offset) {
    377321                        ZERO_STRUCT(qt);
    378                         if (!parse_user_quota_record(curdata, curdata_count, &offset, &qt)) {
     322                        if (!parse_user_quota_record((uint8_t *)curdata,
     323                                                     curdata_count, &offset,
     324                                                     &qt)) {
    379325                                DEBUG(1,("Failed to parse the quota record\n"));
    380326                                goto cleanup;
     
    400346        }
    401347
    402 
    403         ret = True;
    404348 cleanup:
    405         SAFE_FREE(rparam);
    406         SAFE_FREE(rdata);
    407 
    408         return ret;
    409 }
    410 
    411 bool cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
    412 {
    413         bool ret = False;
    414         uint16 setup;
    415         char param[2];
    416         char *rparam=NULL, *rdata=NULL;
    417         unsigned int rparam_count=0, rdata_count=0;
     349        TALLOC_FREE(rparam);
     350        TALLOC_FREE(rdata);
     351
     352        return status;
     353}
     354
     355NTSTATUS cli_get_fs_quota_info(struct cli_state *cli, int quota_fnum,
     356                               SMB_NTQUOTA_STRUCT *pqt)
     357{
     358        uint16_t setup[1];
     359        uint8_t param[2];
     360        uint8_t *rdata=NULL;
     361        uint32_t rdata_count=0;
    418362        SMB_NTQUOTA_STRUCT qt;
     363        NTSTATUS status;
     364
    419365        ZERO_STRUCT(qt);
    420366
     
    423369        }
    424370
    425         setup = TRANSACT2_QFSINFO;
     371        SSVAL(setup + 0, 0, TRANSACT2_QFSINFO);
    426372
    427373        SSVAL(param,0,SMB_FS_QUOTA_INFORMATION);
    428374
    429         if (!cli_send_trans(cli, SMBtrans2,
    430                     NULL,
    431                     0, 0,
    432                     &setup, 1, 0,
    433                     param, 2, 0,
    434                     NULL, 0, 560)) {
    435                 goto cleanup;
    436         }
    437 
    438         if (!cli_receive_trans(cli, SMBtrans2,
    439                               &rparam, &rparam_count,
    440                               &rdata, &rdata_count)) {
    441                 goto cleanup;
    442         }
    443 
    444         if (cli_is_error(cli)) {
    445                 ret = False;
    446                 goto cleanup;
    447         } else {
    448                 ret = True;
    449         }
    450 
    451         if (rdata_count < 48) {
    452                 goto cleanup;
     375        status = cli_trans(talloc_tos(), cli, SMBtrans2,
     376                           NULL, -1, /* name, fid */
     377                           0, 0,     /* function, flags */
     378                           setup, 1, 0, /* setup */
     379                           param, 2, 0, /* param */
     380                           NULL, 0, 560, /* data */
     381                           NULL,         /* recv_flags2 */
     382                           NULL, 0, NULL, /* rsetup */
     383                           NULL, 0, NULL, /* rparam */
     384                           &rdata, 48, &rdata_count);
     385
     386        if (!NT_STATUS_IS_OK(status)) {
     387                DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
     388                          nt_errstr(status)));
     389                return status;
    453390        }
    454391
     
    456393
    457394        /* the soft quotas 8 bytes (uint64_t)*/
    458         qt.softlim = (uint64_t)IVAL(rdata,24);
    459 #ifdef LARGE_SMB_OFF_T
    460         qt.softlim |= (((uint64_t)IVAL(rdata,28)) << 32);
    461 #else /* LARGE_SMB_OFF_T */
    462         if ((IVAL(rdata,28) != 0)&&
    463                 ((qt.softlim != 0xFFFFFFFF)||
    464                  (IVAL(rdata,28)!=0xFFFFFFFF))) {
    465                 /* more than 32 bits? */
    466                 goto cleanup;
    467         }
    468 #endif /* LARGE_SMB_OFF_T */
     395        qt.softlim = BVAL(rdata,24);
    469396
    470397        /* the hard quotas 8 bytes (uint64_t)*/
    471         qt.hardlim = (uint64_t)IVAL(rdata,32);
    472 #ifdef LARGE_SMB_OFF_T
    473         qt.hardlim |= (((uint64_t)IVAL(rdata,36)) << 32);
    474 #else /* LARGE_SMB_OFF_T */
    475         if ((IVAL(rdata,36) != 0)&&
    476                 ((qt.hardlim != 0xFFFFFFFF)||
    477                  (IVAL(rdata,36)!=0xFFFFFFFF))) {
    478                 /* more than 32 bits? */
    479                 goto cleanup;
    480         }
    481 #endif /* LARGE_SMB_OFF_T */
     398        qt.hardlim = BVAL(rdata,32);
    482399
    483400        /* quota_flags 2 bytes **/
     
    488405        *pqt = qt;
    489406
    490         ret = True;
    491 cleanup:
    492         SAFE_FREE(rparam);
    493         SAFE_FREE(rdata);
    494 
    495         return ret;     
    496 }
    497 
    498 bool cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_STRUCT *pqt)
    499 {
    500         bool ret = False;
    501         uint16 setup;
    502         char param[4];
    503         char data[48];
    504         char *rparam=NULL, *rdata=NULL;
    505         unsigned int rparam_count=0, rdata_count=0;
     407        TALLOC_FREE(rdata);
     408        return status;
     409}
     410
     411NTSTATUS cli_set_fs_quota_info(struct cli_state *cli, int quota_fnum,
     412                               SMB_NTQUOTA_STRUCT *pqt)
     413{
     414        uint16_t setup[1];
     415        uint8_t param[4];
     416        uint8_t data[48];
    506417        SMB_NTQUOTA_STRUCT qt;
     418        NTSTATUS status;
    507419        ZERO_STRUCT(qt);
    508420        memset(data,'\0',48);
     
    512424        }
    513425
    514         setup = TRANSACT2_SETFSINFO;
     426        SSVAL(setup + 0, 0,TRANSACT2_SETFSINFO);
    515427
    516428        SSVAL(param,0,quota_fnum);
     
    530442        /* Unknown3 6 NULL bytes */
    531443
    532         if (!cli_send_trans(cli, SMBtrans2,
    533                     NULL,
    534                     0, 0,
    535                     &setup, 1, 0,
    536                     param, 4, 0,
    537                     data, 48, 0)) {
    538                 goto cleanup;
    539         }
    540 
    541         if (!cli_receive_trans(cli, SMBtrans2,
    542                               &rparam, &rparam_count,
    543                               &rdata, &rdata_count)) {
    544                 goto cleanup;
    545         }
    546 
    547         if (cli_is_error(cli)) {
    548                 ret = False;
    549                 goto cleanup;
    550         } else {
    551                 ret = True;
    552         }
    553 
    554 cleanup:
    555         SAFE_FREE(rparam);
    556         SAFE_FREE(rdata);
    557 
    558         return ret;     
    559 }
    560 
    561 static const char *quota_str_static(uint64_t val, bool special, bool _numeric)
    562 {
    563         const char *result;
    564 
    565         if (!_numeric&&special&&(val == SMB_NTQUOTAS_NO_LIMIT)) {
    566                 return "NO LIMIT";
    567         }
    568         result = talloc_asprintf(talloc_tos(), "%"PRIu64, val);
    569         SMB_ASSERT(result != NULL);
    570         return result;
    571 }
    572 
    573 void dump_ntquota(SMB_NTQUOTA_STRUCT *qt, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, DOM_SID *sid, bool _numeric))
    574 {
    575         TALLOC_CTX *frame = talloc_stackframe();
    576 
    577         if (!qt) {
    578                 smb_panic("dump_ntquota() called with NULL pointer");
    579         }
    580 
    581         switch (qt->qtype) {
    582                 case SMB_USER_FS_QUOTA_TYPE:
    583                         {
    584                                 d_printf("File System QUOTAS:\n");
    585                                 d_printf("Limits:\n");
    586                                 d_printf(" Default Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
    587                                 d_printf(" Default Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
    588                                 d_printf("Quota Flags:\n");
    589                                 d_printf(" Quotas Enabled: %s\n",
    590                                         ((qt->qflags&QUOTAS_ENABLED)||(qt->qflags&QUOTAS_DENY_DISK))?"On":"Off");
    591                                 d_printf(" Deny Disk:      %s\n",(qt->qflags&QUOTAS_DENY_DISK)?"On":"Off");
    592                                 d_printf(" Log Soft Limit: %s\n",(qt->qflags&QUOTAS_LOG_THRESHOLD)?"On":"Off");
    593                                 d_printf(" Log Hard Limit: %s\n",(qt->qflags&QUOTAS_LOG_LIMIT)?"On":"Off");
    594                         }
    595                         break;
    596                 case SMB_USER_QUOTA_TYPE:
    597                         {
    598                                 fstring username_str = {0};
    599 
    600                                 if (_sidtostring) {
    601                                         _sidtostring(username_str,&qt->sid,_numeric);
    602                                 } else {
    603                                         sid_to_fstring(username_str, &qt->sid);
    604                                 }
    605 
    606                                 if (_verbose) {
    607                                         d_printf("Quotas for User: %s\n",username_str);
    608                                         d_printf("Used Space: %15s\n",quota_str_static(qt->usedspace,False,_numeric));
    609                                         d_printf("Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
    610                                         d_printf("Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
    611                                 } else {
    612                                         d_printf("%-30s: ",username_str);
    613                                         d_printf("%15s/",quota_str_static(qt->usedspace,False,_numeric));
    614                                         d_printf("%15s/",quota_str_static(qt->softlim,True,_numeric));
    615                                         d_printf("%15s\n",quota_str_static(qt->hardlim,True,_numeric));
    616                                 }
    617                         }
    618                         break;
    619                 default:
    620                         d_printf("dump_ntquota() invalid qtype(%d)\n",qt->qtype);
    621         }
    622         TALLOC_FREE(frame);
    623         return;
    624 }
    625 
    626 void dump_ntquota_list(SMB_NTQUOTA_LIST **qtl, bool _verbose, bool _numeric, void (*_sidtostring)(fstring str, DOM_SID *sid, bool _numeric))
    627 {
    628         SMB_NTQUOTA_LIST *cur;
    629 
    630         for (cur = *qtl;cur;cur = cur->next) {
    631                 if (cur->quotas)
    632                         dump_ntquota(cur->quotas,_verbose,_numeric,_sidtostring);
    633         }       
    634 }
     444        status = cli_trans(talloc_tos(), cli, SMBtrans2,
     445                           NULL, -1, /* name, fid */
     446                           0, 0,     /* function, flags */
     447                           setup, 1, 0, /* setup */
     448                           param, 8, 0, /* param */
     449                           data, 48, 0, /* data */
     450                           NULL,         /* recv_flags2 */
     451                           NULL, 0, NULL, /* rsetup */
     452                           NULL, 0, NULL, /* rparam */
     453                           NULL, 0, NULL); /* rdata */
     454
     455        if (!NT_STATUS_IS_OK(status)) {
     456                DEBUG(1, ("SMB_FS_QUOTA_INFORMATION failed: %s\n",
     457                          nt_errstr(status)));
     458        }
     459
     460        return status;
     461}
  • vendor/current/source3/libsmb/clirap.c

    r414 r740  
    2222#include "includes.h"
    2323#include "../libcli/auth/libcli_auth.h"
     24#include "../librpc/gen_ndr/rap.h"
     25#include "../lib/crypto/arcfour.h"
     26#include "../lib/util/tevent_ntstatus.h"
     27#include "async_smb.h"
     28#include "libsmb/libsmb.h"
     29#include "libsmb/clirap.h"
     30#include "trans2.h"
     31
     32#define PIPE_LANMAN   "\\PIPE\\LANMAN"
    2433
    2534/****************************************************************************
     
    3342             char **rdata, unsigned int *rdrcnt)
    3443{
    35         cli_send_trans(cli,SMBtrans,
    36                  PIPE_LANMAN,             /* Name */
    37                  0,0,                     /* fid, flags */
    38                  NULL,0,0,                /* Setup, length, max */
    39                  param, prcnt, mprcnt,    /* Params, length, max */
    40                  data, drcnt, mdrcnt      /* Data, length, max */
    41                 );
    42 
    43         return (cli_receive_trans(cli,SMBtrans,
    44                             rparam, rprcnt,
    45                             rdata, rdrcnt));
     44        NTSTATUS status;
     45
     46        uint8_t *my_rparam, *my_rdata;
     47        uint32_t num_my_rparam, num_my_rdata;
     48
     49        status = cli_trans(talloc_tos(), cli, SMBtrans,
     50                           PIPE_LANMAN, 0, /* name, fid */
     51                           0, 0,           /* function, flags */
     52                           NULL, 0, 0,     /* setup */
     53                           (uint8_t *)param, prcnt, mprcnt, /* Params, length, max */
     54                           (uint8_t *)data, drcnt, mdrcnt,  /* Data, length, max */
     55                           NULL,                 /* recv_flags2 */
     56                           NULL, 0, NULL,        /* rsetup */
     57                           &my_rparam, 0, &num_my_rparam,
     58                           &my_rdata, 0, &num_my_rdata);
     59        if (!NT_STATUS_IS_OK(status)) {
     60                return false;
     61        }
     62
     63        /*
     64         * I know this memcpy massively hurts, but there are just tons
     65         * of callers of cli_api that eventually need changing to
     66         * talloc
     67         */
     68
     69        *rparam = (char *)memdup(my_rparam, num_my_rparam);
     70        if (*rparam == NULL) {
     71                goto fail;
     72        }
     73        *rprcnt = num_my_rparam;
     74        TALLOC_FREE(my_rparam);
     75
     76        *rdata = (char *)memdup(my_rdata, num_my_rdata);
     77        if (*rdata == NULL) {
     78                goto fail;
     79        }
     80        *rdrcnt = num_my_rdata;
     81        TALLOC_FREE(my_rdata);
     82
     83        return true;
     84fail:
     85        TALLOC_FREE(my_rdata);
     86        TALLOC_FREE(my_rparam);
     87        *rparam = NULL;
     88        *rprcnt = 0;
     89        *rdata = NULL;
     90        *rdrcnt = 0;
     91        return false;
    4692}
    4793
     
    496542        data_len = 532;
    497543
    498         if (cli_send_trans(cli,SMBtrans,
    499                     PIPE_LANMAN,                          /* name */
    500                     0,0,                                  /* fid, flags */
    501                     NULL,0,0,                             /* setup, length, max */
    502                     param,param_len,2,                    /* param, length, max */
    503                     (char *)data,data_len,0                       /* data, length, max */
    504                    ) == False) {
     544        if (!cli_api(cli,
     545                     param, param_len, 4,               /* param, length, max */
     546                     (char *)data, data_len, 0,         /* data, length, max */
     547                     &rparam, &rprcnt,
     548                     &rdata, &rdrcnt)) {
    505549                DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
    506550                        user ));
     
    508552        }
    509553
    510         if (!cli_receive_trans(cli,SMBtrans,
    511                        &rparam, &rprcnt,
    512                        &rdata, &rdrcnt)) {
    513                 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
    514                         user ));
    515                 return False;
    516         }
    517 
    518554        if (rparam) {
    519555                cli->rap_error = SVAL(rparam,0);
     
    530566****************************************************************************/
    531567
    532 bool cli_qpathinfo(struct cli_state *cli,
     568struct cli_qpathinfo1_state {
     569        struct cli_state *cli;
     570        uint32_t num_data;
     571        uint8_t *data;
     572};
     573
     574static void cli_qpathinfo1_done(struct tevent_req *subreq);
     575
     576struct tevent_req *cli_qpathinfo1_send(TALLOC_CTX *mem_ctx,
     577                                       struct event_context *ev,
     578                                       struct cli_state *cli,
     579                                       const char *fname)
     580{
     581        struct tevent_req *req = NULL, *subreq = NULL;
     582        struct cli_qpathinfo1_state *state = NULL;
     583
     584        req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo1_state);
     585        if (req == NULL) {
     586                return NULL;
     587        }
     588        state->cli = cli;
     589        subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_INFO_STANDARD,
     590                                    22, cli->max_xmit);
     591        if (tevent_req_nomem(subreq, req)) {
     592                return tevent_req_post(req, ev);
     593        }
     594        tevent_req_set_callback(subreq, cli_qpathinfo1_done, req);
     595        return req;
     596}
     597
     598static void cli_qpathinfo1_done(struct tevent_req *subreq)
     599{
     600        struct tevent_req *req = tevent_req_callback_data(
     601                subreq, struct tevent_req);
     602        struct cli_qpathinfo1_state *state = tevent_req_data(
     603                req, struct cli_qpathinfo1_state);
     604        NTSTATUS status;
     605
     606        status = cli_qpathinfo_recv(subreq, state, &state->data,
     607                                    &state->num_data);
     608        TALLOC_FREE(subreq);
     609        if (!NT_STATUS_IS_OK(status)) {
     610                tevent_req_nterror(req, status);
     611                return;
     612        }
     613        tevent_req_done(req);
     614}
     615
     616NTSTATUS cli_qpathinfo1_recv(struct tevent_req *req,
     617                             time_t *change_time,
     618                             time_t *access_time,
     619                             time_t *write_time,
     620                             SMB_OFF_T *size,
     621                             uint16 *mode)
     622{
     623        struct cli_qpathinfo1_state *state = tevent_req_data(
     624                req, struct cli_qpathinfo1_state);
     625        NTSTATUS status;
     626
     627        time_t (*date_fn)(const void *buf, int serverzone);
     628
     629        if (tevent_req_is_nterror(req, &status)) {
     630                return status;
     631        }
     632
     633        if (state->cli->win95) {
     634                date_fn = make_unix_date;
     635        } else {
     636                date_fn = make_unix_date2;
     637        }
     638
     639        if (change_time) {
     640                *change_time = date_fn(state->data+0, state->cli->serverzone);
     641        }
     642        if (access_time) {
     643                *access_time = date_fn(state->data+4, state->cli->serverzone);
     644        }
     645        if (write_time) {
     646                *write_time = date_fn(state->data+8, state->cli->serverzone);
     647        }
     648        if (size) {
     649                *size = IVAL(state->data, 12);
     650        }
     651        if (mode) {
     652                *mode = SVAL(state->data, l1_attrFile);
     653        }
     654        return NT_STATUS_OK;
     655}
     656
     657NTSTATUS cli_qpathinfo1(struct cli_state *cli,
    533658                        const char *fname,
    534659                        time_t *change_time,
     
    538663                        uint16 *mode)
    539664{
    540         unsigned int data_len = 0;
    541         unsigned int param_len = 0;
    542         unsigned int rparam_len, rdata_len;
    543         uint16 setup = TRANSACT2_QPATHINFO;
    544         char *param;
    545         char *rparam=NULL, *rdata=NULL;
    546         int count=8;
    547         bool ret;
    548         time_t (*date_fn)(struct cli_state *, const void *);
    549         char *p;
    550         size_t nlen = 2*(strlen(fname)+1);
    551 
    552         param = SMB_MALLOC_ARRAY(char, 6+nlen+2);
    553         if (!param) {
    554                 return false;
    555         }
    556         p = param;
    557         memset(p, '\0', 6);
    558         SSVAL(p, 0, SMB_INFO_STANDARD);
    559         p += 6;
    560         p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);
    561         param_len = PTR_DIFF(p, param);
    562 
    563         do {
    564                 ret = (cli_send_trans(cli, SMBtrans2,
    565                                       NULL,           /* Name */
    566                                       -1, 0,          /* fid, flags */
    567                                       &setup, 1, 0,   /* setup, length, max */
    568                                       param, param_len, 10, /* param, length, max */
    569                                       NULL, data_len, cli->max_xmit /* data, length, max */
    570                                       ) &&
    571                        cli_receive_trans(cli, SMBtrans2,
    572                                          &rparam, &rparam_len,
    573                                          &rdata, &rdata_len));
    574                 if (!cli_is_dos_error(cli)) break;
    575                 if (!ret) {
    576                         /* we need to work around a Win95 bug - sometimes
    577                            it gives ERRSRV/ERRerror temprarily */
    578                         uint8 eclass;
    579                         uint32 ecode;
    580                         cli_dos_error(cli, &eclass, &ecode);
    581                         if (eclass != ERRSRV || ecode != ERRerror) break;
    582                         smb_msleep(100);
    583                 }
    584         } while (count-- && ret==False);
    585 
    586         SAFE_FREE(param);
    587         if (!ret || !rdata || rdata_len < 22) {
    588                 return False;
    589         }
    590 
    591         if (cli->win95) {
    592                 date_fn = cli_make_unix_date;
    593         } else {
    594                 date_fn = cli_make_unix_date2;
    595         }
    596 
    597         if (change_time) {
    598                 *change_time = date_fn(cli, rdata+0);
    599         }
    600         if (access_time) {
    601                 *access_time = date_fn(cli, rdata+4);
    602         }
    603         if (write_time) {
    604                 *write_time = date_fn(cli, rdata+8);
    605         }
    606         if (size) {
    607                 *size = IVAL(rdata, 12);
    608         }
    609         if (mode) {
    610                 *mode = SVAL(rdata,l1_attrFile);
    611         }
    612 
    613         SAFE_FREE(rdata);
    614         SAFE_FREE(rparam);
    615         return True;
     665        TALLOC_CTX *frame = talloc_stackframe();
     666        struct event_context *ev;
     667        struct tevent_req *req;
     668        NTSTATUS status = NT_STATUS_NO_MEMORY;
     669
     670        if (cli_has_async_calls(cli)) {
     671                /*
     672                 * Can't use sync call while an async call is in flight
     673                 */
     674                status = NT_STATUS_INVALID_PARAMETER;
     675                goto fail;
     676        }
     677        ev = event_context_init(frame);
     678        if (ev == NULL) {
     679                goto fail;
     680        }
     681        req = cli_qpathinfo1_send(frame, ev, cli, fname);
     682        if (req == NULL) {
     683                goto fail;
     684        }
     685        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     686                goto fail;
     687        }
     688        status = cli_qpathinfo1_recv(req, change_time, access_time,
     689                                     write_time, size, mode);
     690 fail:
     691        TALLOC_FREE(frame);
     692        if (!NT_STATUS_IS_OK(status)) {
     693                cli_set_error(cli, status);
     694        }
     695        return status;
    616696}
    617697
     
    620700****************************************************************************/
    621701
    622 bool cli_setpathinfo(struct cli_state *cli, const char *fname,
    623                      time_t create_time,
    624                      time_t access_time,
    625                      time_t write_time,
    626                      time_t change_time,
    627                      uint16 mode)
     702NTSTATUS cli_setpathinfo_basic(struct cli_state *cli, const char *fname,
     703                               time_t create_time,
     704                               time_t access_time,
     705                               time_t write_time,
     706                               time_t change_time,
     707                               uint16 mode)
    628708{
    629709        unsigned int data_len = 0;
    630         unsigned int param_len = 0;
    631         unsigned int rparam_len, rdata_len;
    632         uint16 setup = TRANSACT2_SETPATHINFO;
    633         char *param;
    634710        char data[40];
    635         char *rparam=NULL, *rdata=NULL;
    636         int count=8;
    637         bool ret;
    638711        char *p;
    639         size_t nlen = 2*(strlen(fname)+1);
    640 
    641         param = SMB_MALLOC_ARRAY(char, 6+nlen+2);
    642         if (!param) {
    643                 return false;
    644         }
    645         memset(param, '\0', 6);
    646         memset(data, 0, sizeof(data));
    647 
    648         p = param;
    649 
    650         /* Add the information level */
    651         SSVAL(p, 0, SMB_FILE_BASIC_INFORMATION);
    652 
    653         /* Skip reserved */
    654         p += 6;
    655 
    656         /* Add the file name */
    657         p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);
    658 
    659         param_len = PTR_DIFF(p, param);
    660712
    661713        p = data;
     
    686738        data_len = PTR_DIFF(p, data);
    687739
    688         do {
    689                 ret = (cli_send_trans(cli, SMBtrans2,
    690                                       NULL,           /* Name */
    691                                       -1, 0,          /* fid, flags */
    692                                       &setup, 1, 0,   /* setup, length, max */
    693                                       param, param_len, 10, /* param, length, max */
    694                                       data, data_len, cli->max_xmit /* data, length, max */
    695                                       ) &&
    696                        cli_receive_trans(cli, SMBtrans2,
    697                                          &rparam, &rparam_len,
    698                                          &rdata, &rdata_len));
    699                 if (!cli_is_dos_error(cli)) break;
    700                 if (!ret) {
    701                         /* we need to work around a Win95 bug - sometimes
    702                            it gives ERRSRV/ERRerror temprarily */
    703                         uint8 eclass;
    704                         uint32 ecode;
    705                         cli_dos_error(cli, &eclass, &ecode);
    706                         if (eclass != ERRSRV || ecode != ERRerror) break;
    707                         smb_msleep(100);
    708                 }
    709         } while (count-- && ret==False);
    710 
    711         SAFE_FREE(param);
    712         if (!ret) {
    713                 return False;
    714         }
    715 
    716         SAFE_FREE(rdata);
    717         SAFE_FREE(rparam);
    718         return True;
     740        return cli_setpathinfo(cli, SMB_FILE_BASIC_INFORMATION, fname,
     741                               (uint8_t *)data, data_len);
    719742}
    720743
     
    723746****************************************************************************/
    724747
    725 bool cli_qpathinfo2(struct cli_state *cli, const char *fname,
    726                     struct timespec *create_time,
    727                     struct timespec *access_time,
    728                     struct timespec *write_time,
    729                     struct timespec *change_time,
    730                     SMB_OFF_T *size, uint16 *mode,
    731                     SMB_INO_T *ino)
    732 {
    733         unsigned int data_len = 0;
    734         unsigned int param_len = 0;
    735         uint16 setup = TRANSACT2_QPATHINFO;
    736         char *param;
    737         char *rparam=NULL, *rdata=NULL;
    738         char *p;
    739         size_t nlen = 2*(strlen(fname)+1);
    740 
    741         param = SMB_MALLOC_ARRAY(char, 6+nlen+2);
    742         if (!param) {
    743                 return false;
    744         }
    745         p = param;
    746         memset(param, '\0', 6);
    747         SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
    748         p += 6;
    749         p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);
    750 
    751         param_len = PTR_DIFF(p, param);
    752 
    753         if (!cli_send_trans(cli, SMBtrans2,
    754                             NULL,                         /* name */
    755                             -1, 0,                        /* fid, flags */
    756                             &setup, 1, 0,                 /* setup, length, max */
    757                             param, param_len, 10,         /* param, length, max */
    758                             NULL, data_len, cli->max_xmit /* data, length, max */
    759                            )) {
    760                 SAFE_FREE(param);
    761                 return False;
    762         }
    763 
    764         SAFE_FREE(param);
    765         if (!cli_receive_trans(cli, SMBtrans2,
    766                                &rparam, &param_len,
    767                                &rdata, &data_len)) {
    768                 return False;
    769         }
    770 
    771         if (!rdata || data_len < 22) {
    772                 return False;
     748struct cli_qpathinfo2_state {
     749        uint32_t num_data;
     750        uint8_t *data;
     751};
     752
     753static void cli_qpathinfo2_done(struct tevent_req *subreq);
     754
     755struct tevent_req *cli_qpathinfo2_send(TALLOC_CTX *mem_ctx,
     756                                       struct event_context *ev,
     757                                       struct cli_state *cli,
     758                                       const char *fname)
     759{
     760        struct tevent_req *req = NULL, *subreq = NULL;
     761        struct cli_qpathinfo2_state *state = NULL;
     762
     763        req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo2_state);
     764        if (req == NULL) {
     765                return NULL;
     766        }
     767        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     768                                    SMB_QUERY_FILE_ALL_INFO,
     769                                    68, cli->max_xmit);
     770        if (tevent_req_nomem(subreq, req)) {
     771                return tevent_req_post(req, ev);
     772        }
     773        tevent_req_set_callback(subreq, cli_qpathinfo2_done, req);
     774        return req;
     775}
     776
     777static void cli_qpathinfo2_done(struct tevent_req *subreq)
     778{
     779        struct tevent_req *req = tevent_req_callback_data(
     780                subreq, struct tevent_req);
     781        struct cli_qpathinfo2_state *state = tevent_req_data(
     782                req, struct cli_qpathinfo2_state);
     783        NTSTATUS status;
     784
     785        status = cli_qpathinfo_recv(subreq, state, &state->data,
     786                                    &state->num_data);
     787        TALLOC_FREE(subreq);
     788        if (!NT_STATUS_IS_OK(status)) {
     789                tevent_req_nterror(req, status);
     790                return;
     791        }
     792        tevent_req_done(req);
     793}
     794
     795NTSTATUS cli_qpathinfo2_recv(struct tevent_req *req,
     796                             struct timespec *create_time,
     797                             struct timespec *access_time,
     798                             struct timespec *write_time,
     799                             struct timespec *change_time,
     800                             SMB_OFF_T *size, uint16 *mode,
     801                             SMB_INO_T *ino)
     802{
     803        struct cli_qpathinfo2_state *state = tevent_req_data(
     804                req, struct cli_qpathinfo2_state);
     805        NTSTATUS status;
     806
     807        if (tevent_req_is_nterror(req, &status)) {
     808                return status;
    773809        }
    774810
    775811        if (create_time) {
    776                 *create_time = interpret_long_date(rdata+0);
     812                *create_time = interpret_long_date((char *)state->data+0);
    777813        }
    778814        if (access_time) {
    779                 *access_time = interpret_long_date(rdata+8);
     815                *access_time = interpret_long_date((char *)state->data+8);
    780816        }
    781817        if (write_time) {
    782                 *write_time = interpret_long_date(rdata+16);
     818                *write_time = interpret_long_date((char *)state->data+16);
    783819        }
    784820        if (change_time) {
    785                 *change_time = interpret_long_date(rdata+24);
     821                *change_time = interpret_long_date((char *)state->data+24);
    786822        }
    787823        if (mode) {
    788                 *mode = SVAL(rdata, 32);
     824                *mode = SVAL(state->data, 32);
    789825        }
    790826        if (size) {
    791                 *size = IVAL2_TO_SMB_BIG_UINT(rdata,48);
     827                *size = IVAL2_TO_SMB_BIG_UINT(state->data,48);
    792828        }
    793829        if (ino) {
    794                 *ino = IVAL(rdata, 64);
    795         }
    796 
    797         SAFE_FREE(rdata);
    798         SAFE_FREE(rparam);
    799         return True;
     830                *ino = IVAL(state->data, 64);
     831        }
     832        return NT_STATUS_OK;
     833}
     834
     835NTSTATUS cli_qpathinfo2(struct cli_state *cli, const char *fname,
     836                        struct timespec *create_time,
     837                        struct timespec *access_time,
     838                        struct timespec *write_time,
     839                        struct timespec *change_time,
     840                        SMB_OFF_T *size, uint16 *mode,
     841                        SMB_INO_T *ino)
     842{
     843        TALLOC_CTX *frame = talloc_stackframe();
     844        struct event_context *ev;
     845        struct tevent_req *req;
     846        NTSTATUS status = NT_STATUS_NO_MEMORY;
     847
     848        if (cli_has_async_calls(cli)) {
     849                /*
     850                 * Can't use sync call while an async call is in flight
     851                 */
     852                status = NT_STATUS_INVALID_PARAMETER;
     853                goto fail;
     854        }
     855        ev = event_context_init(frame);
     856        if (ev == NULL) {
     857                goto fail;
     858        }
     859        req = cli_qpathinfo2_send(frame, ev, cli, fname);
     860        if (req == NULL) {
     861                goto fail;
     862        }
     863        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     864                goto fail;
     865        }
     866        status = cli_qpathinfo2_recv(req, create_time, access_time,
     867                                     write_time, change_time, size, mode, ino);
     868 fail:
     869        TALLOC_FREE(frame);
     870        if (!NT_STATUS_IS_OK(status)) {
     871                cli_set_error(cli, status);
     872        }
     873        return status;
    800874}
    801875
     
    804878****************************************************************************/
    805879
    806 bool cli_qpathinfo_streams(struct cli_state *cli, const char *fname,
    807                            TALLOC_CTX *mem_ctx,
    808                            unsigned int *pnum_streams,
    809                            struct stream_struct **pstreams)
    810 {
    811         unsigned int data_len = 0;
    812         unsigned int param_len = 0;
    813         uint16 setup = TRANSACT2_QPATHINFO;
    814         char *param;
    815         char *rparam=NULL, *rdata=NULL;
    816         char *p;
     880static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *data,
     881                               size_t data_len,
     882                               unsigned int *pnum_streams,
     883                               struct stream_struct **pstreams);
     884
     885struct cli_qpathinfo_streams_state {
     886        uint32_t num_data;
     887        uint8_t *data;
     888};
     889
     890static void cli_qpathinfo_streams_done(struct tevent_req *subreq);
     891
     892struct tevent_req *cli_qpathinfo_streams_send(TALLOC_CTX *mem_ctx,
     893                                              struct tevent_context *ev,
     894                                              struct cli_state *cli,
     895                                              const char *fname)
     896{
     897        struct tevent_req *req = NULL, *subreq = NULL;
     898        struct cli_qpathinfo_streams_state *state = NULL;
     899
     900        req = tevent_req_create(mem_ctx, &state,
     901                                struct cli_qpathinfo_streams_state);
     902        if (req == NULL) {
     903                return NULL;
     904        }
     905        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     906                                    SMB_FILE_STREAM_INFORMATION,
     907                                    0, cli->max_xmit);
     908        if (tevent_req_nomem(subreq, req)) {
     909                return tevent_req_post(req, ev);
     910        }
     911        tevent_req_set_callback(subreq, cli_qpathinfo_streams_done, req);
     912        return req;
     913}
     914
     915static void cli_qpathinfo_streams_done(struct tevent_req *subreq)
     916{
     917        struct tevent_req *req = tevent_req_callback_data(
     918                subreq, struct tevent_req);
     919        struct cli_qpathinfo_streams_state *state = tevent_req_data(
     920                req, struct cli_qpathinfo_streams_state);
     921        NTSTATUS status;
     922
     923        status = cli_qpathinfo_recv(subreq, state, &state->data,
     924                                    &state->num_data);
     925        TALLOC_FREE(subreq);
     926        if (!NT_STATUS_IS_OK(status)) {
     927                tevent_req_nterror(req, status);
     928                return;
     929        }
     930        tevent_req_done(req);
     931}
     932
     933NTSTATUS cli_qpathinfo_streams_recv(struct tevent_req *req,
     934                                    TALLOC_CTX *mem_ctx,
     935                                    unsigned int *pnum_streams,
     936                                    struct stream_struct **pstreams)
     937{
     938        struct cli_qpathinfo_streams_state *state = tevent_req_data(
     939                req, struct cli_qpathinfo_streams_state);
     940        NTSTATUS status;
     941
     942        if (tevent_req_is_nterror(req, &status)) {
     943                return status;
     944        }
     945        if (!parse_streams_blob(mem_ctx, state->data, state->num_data,
     946                                pnum_streams, pstreams)) {
     947                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     948        }
     949        return NT_STATUS_OK;
     950}
     951
     952NTSTATUS cli_qpathinfo_streams(struct cli_state *cli, const char *fname,
     953                               TALLOC_CTX *mem_ctx,
     954                               unsigned int *pnum_streams,
     955                               struct stream_struct **pstreams)
     956{
     957        TALLOC_CTX *frame = talloc_stackframe();
     958        struct event_context *ev;
     959        struct tevent_req *req;
     960        NTSTATUS status = NT_STATUS_NO_MEMORY;
     961
     962        if (cli_has_async_calls(cli)) {
     963                /*
     964                 * Can't use sync call while an async call is in flight
     965                 */
     966                status = NT_STATUS_INVALID_PARAMETER;
     967                goto fail;
     968        }
     969        ev = event_context_init(frame);
     970        if (ev == NULL) {
     971                goto fail;
     972        }
     973        req = cli_qpathinfo_streams_send(frame, ev, cli, fname);
     974        if (req == NULL) {
     975                goto fail;
     976        }
     977        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     978                goto fail;
     979        }
     980        status = cli_qpathinfo_streams_recv(req, mem_ctx, pnum_streams,
     981                                            pstreams);
     982 fail:
     983        TALLOC_FREE(frame);
     984        if (!NT_STATUS_IS_OK(status)) {
     985                cli_set_error(cli, status);
     986        }
     987        return status;
     988}
     989
     990static bool parse_streams_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata,
     991                               size_t data_len,
     992                               unsigned int *pnum_streams,
     993                               struct stream_struct **pstreams)
     994{
    817995        unsigned int num_streams;
    818996        struct stream_struct *streams;
    819997        unsigned int ofs;
    820         size_t namelen = 2*(strlen(fname)+1);
    821 
    822         param = SMB_MALLOC_ARRAY(char, 6+namelen+2);
    823         if (param == NULL) {
    824                 return false;
    825         }
    826         p = param;
    827         memset(p, 0, 6);
    828         SSVAL(p, 0, SMB_FILE_STREAM_INFORMATION);
    829         p += 6;
    830         p += clistr_push(cli, p, fname, namelen, STR_TERMINATE);
    831 
    832         param_len = PTR_DIFF(p, param);
    833 
    834         if (!cli_send_trans(cli, SMBtrans2,
    835                             NULL,                     /* name */
    836                             -1, 0,                    /* fid, flags */
    837                             &setup, 1, 0,             /* setup, len, max */
    838                             param, param_len, 10,     /* param, len, max */
    839                             NULL, data_len, cli->max_xmit /* data, len, max */
    840                            )) {
    841                 return false;
    842         }
    843 
    844         if (!cli_receive_trans(cli, SMBtrans2,
    845                                &rparam, &param_len,
    846                                &rdata, &data_len)) {
    847                 return false;
    848         }
    849 
    850         if (!rdata) {
    851                 SAFE_FREE(rparam);
    852                 return false;
    853         }
    854998
    855999        num_streams = 0;
     
    9171061        }
    9181062
    919         SAFE_FREE(rdata);
    920         SAFE_FREE(rparam);
    921 
    9221063        *pnum_streams = num_streams;
    9231064        *pstreams = streams;
     
    9261067 fail:
    9271068        TALLOC_FREE(streams);
    928         SAFE_FREE(rdata);
    929         SAFE_FREE(rparam);
    9301069        return false;
    9311070}
     
    9351074****************************************************************************/
    9361075
    937 bool cli_qfilename(struct cli_state *cli, uint16_t fnum, char *name, size_t namelen)
    938 {
    939         unsigned int data_len = 0;
    940         unsigned int param_len = 0;
    941         uint16 setup = TRANSACT2_QFILEINFO;
    942         char param[4];
    943         char *rparam=NULL, *rdata=NULL;
    944 
    945         param_len = 4;
    946         SSVAL(param, 0, fnum);
    947         SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
    948 
    949         if (!cli_send_trans(cli, SMBtrans2,
    950                             NULL,                         /* name */
    951                             -1, 0,                        /* fid, flags */
    952                             &setup, 1, 0,                 /* setup, length, max */
    953                             param, param_len, 2,          /* param, length, max */
    954                             NULL, data_len, cli->max_xmit /* data, length, max */
    955                            )) {
    956                 return False;
    957         }
    958 
    959         if (!cli_receive_trans(cli, SMBtrans2,
    960                                &rparam, &param_len,
    961                                &rdata, &data_len)) {
    962                 return False;
    963         }
    964 
    965         if (!rdata || data_len < 4) {
    966                 SAFE_FREE(rparam);
    967                 SAFE_FREE(rdata);
    968                 return False;
     1076NTSTATUS cli_qfilename(struct cli_state *cli, uint16_t fnum, char *name,
     1077                       size_t namelen)
     1078{
     1079        uint8_t *rdata;
     1080        uint32_t num_rdata;
     1081        NTSTATUS status;
     1082
     1083        status = cli_qfileinfo(talloc_tos(), cli, fnum,
     1084                               SMB_QUERY_FILE_NAME_INFO,
     1085                               4, cli->max_xmit,
     1086                               &rdata, &num_rdata);
     1087        if (!NT_STATUS_IS_OK(status)) {
     1088                return status;
    9691089        }
    9701090
    9711091        clistr_pull(cli->inbuf, name, rdata+4, namelen, IVAL(rdata, 0),
    9721092                    STR_UNICODE);
    973 
    974         SAFE_FREE(rparam);
    975         SAFE_FREE(rdata);
    976 
    977         return True;
     1093        TALLOC_FREE(rdata);
     1094        return NT_STATUS_OK;
    9781095}
    9791096
     
    9821099****************************************************************************/
    9831100
    984 bool cli_qfileinfo(struct cli_state *cli, uint16_t fnum,
    985                    uint16 *mode, SMB_OFF_T *size,
    986                    struct timespec *create_time,
    987                    struct timespec *access_time,
    988                    struct timespec *write_time,
    989                    struct timespec *change_time,
    990                    SMB_INO_T *ino)
    991 {
    992         unsigned int data_len = 0;
    993         unsigned int param_len = 0;
    994         uint16 setup;
    995         uint8_t param[4];
    996         uint8_t *rparam=NULL, *rdata=NULL;
     1101NTSTATUS cli_qfileinfo_basic(struct cli_state *cli, uint16_t fnum,
     1102                             uint16 *mode, SMB_OFF_T *size,
     1103                             struct timespec *create_time,
     1104                             struct timespec *access_time,
     1105                             struct timespec *write_time,
     1106                             struct timespec *change_time,
     1107                             SMB_INO_T *ino)
     1108{
     1109        uint8_t *rdata;
     1110        uint32_t num_rdata;
    9971111        NTSTATUS status;
    9981112
    9991113        /* if its a win95 server then fail this - win95 totally screws it
    10001114           up */
    1001         if (cli->win95) return False;
    1002 
    1003         param_len = 4;
    1004 
    1005         SSVAL(param, 0, fnum);
    1006         SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
    1007 
    1008         SSVAL(&setup, 0, TRANSACT2_QFILEINFO);
    1009 
    1010         status = cli_trans(talloc_tos(), cli, SMBtrans2,
    1011                            NULL, -1, 0, 0, /* name, fid, function, flags */
    1012                            &setup, 1, 0,          /* setup, length, max */
    1013                            param, param_len, 2,   /* param, length, max */
    1014                            NULL, 0, MIN(cli->max_xmit, 0xffff), /* data, length, max */
    1015                            NULL, NULL, /* rsetup, length */
    1016                            &rparam, &param_len, /* rparam, length */
    1017                            &rdata, &data_len);
    1018 
     1115        if (cli->win95) {
     1116                return NT_STATUS_NOT_SUPPORTED;
     1117        }
     1118
     1119        status = cli_qfileinfo(talloc_tos(), cli, fnum,
     1120                               SMB_QUERY_FILE_ALL_INFO,
     1121                               68, MIN(cli->max_xmit, 0xffff),
     1122                               &rdata, &num_rdata);
    10191123        if (!NT_STATUS_IS_OK(status)) {
    1020                 return false;
    1021         }
    1022 
    1023         if (!rdata || data_len < 68) {
    1024                 return False;
     1124                return status;
    10251125        }
    10261126
     
    10481148
    10491149        TALLOC_FREE(rdata);
    1050         TALLOC_FREE(rparam);
    1051         return True;
     1150        return NT_STATUS_OK;
    10521151}
    10531152
     
    10561155****************************************************************************/
    10571156
    1058 bool cli_qpathinfo_basic( struct cli_state *cli, const char *name,
    1059                           SMB_STRUCT_STAT *sbuf, uint32 *attributes )
    1060 {
    1061         unsigned int param_len = 0;
    1062         unsigned int data_len = 0;
    1063         uint16 setup = TRANSACT2_QPATHINFO;
    1064         char *param;
    1065         char *rparam=NULL, *rdata=NULL;
    1066         char *p;
    1067         char *path;
    1068         int len;
    1069         size_t nlen;
     1157struct cli_qpathinfo_basic_state {
     1158        uint32_t num_data;
     1159        uint8_t *data;
     1160};
     1161
     1162static void cli_qpathinfo_basic_done(struct tevent_req *subreq);
     1163
     1164struct tevent_req *cli_qpathinfo_basic_send(TALLOC_CTX *mem_ctx,
     1165                                            struct event_context *ev,
     1166                                            struct cli_state *cli,
     1167                                            const char *fname)
     1168{
     1169        struct tevent_req *req = NULL, *subreq = NULL;
     1170        struct cli_qpathinfo_basic_state *state = NULL;
     1171
     1172        req = tevent_req_create(mem_ctx, &state,
     1173                                struct cli_qpathinfo_basic_state);
     1174        if (req == NULL) {
     1175                return NULL;
     1176        }
     1177        subreq = cli_qpathinfo_send(state, ev, cli, fname,
     1178                                    SMB_QUERY_FILE_BASIC_INFO,
     1179                                    36, cli->max_xmit);
     1180        if (tevent_req_nomem(subreq, req)) {
     1181                return tevent_req_post(req, ev);
     1182        }
     1183        tevent_req_set_callback(subreq, cli_qpathinfo_basic_done, req);
     1184        return req;
     1185}
     1186
     1187static void cli_qpathinfo_basic_done(struct tevent_req *subreq)
     1188{
     1189        struct tevent_req *req = tevent_req_callback_data(
     1190                subreq, struct tevent_req);
     1191        struct cli_qpathinfo_basic_state *state = tevent_req_data(
     1192                req, struct cli_qpathinfo_basic_state);
     1193        NTSTATUS status;
     1194
     1195        status = cli_qpathinfo_recv(subreq, state, &state->data,
     1196                                    &state->num_data);
     1197        TALLOC_FREE(subreq);
     1198        if (!NT_STATUS_IS_OK(status)) {
     1199                tevent_req_nterror(req, status);
     1200                return;
     1201        }
     1202        tevent_req_done(req);
     1203}
     1204
     1205NTSTATUS cli_qpathinfo_basic_recv(struct tevent_req *req,
     1206                                  SMB_STRUCT_STAT *sbuf, uint32 *attributes)
     1207{
     1208        struct cli_qpathinfo_basic_state *state = tevent_req_data(
     1209                req, struct cli_qpathinfo_basic_state);
     1210        NTSTATUS status;
     1211
     1212        if (tevent_req_is_nterror(req, &status)) {
     1213                return status;
     1214        }
     1215
     1216        sbuf->st_ex_atime = interpret_long_date((char *)state->data+8);
     1217        sbuf->st_ex_mtime = interpret_long_date((char *)state->data+16);
     1218        sbuf->st_ex_ctime = interpret_long_date((char *)state->data+24);
     1219        *attributes = IVAL(state->data, 32);
     1220        return NT_STATUS_OK;
     1221}
     1222
     1223NTSTATUS cli_qpathinfo_basic(struct cli_state *cli, const char *name,
     1224                             SMB_STRUCT_STAT *sbuf, uint32 *attributes)
     1225{
    10701226        TALLOC_CTX *frame = talloc_stackframe();
    1071 
    1072         path = talloc_strdup(frame, name);
    1073         if (!path) {
    1074                 TALLOC_FREE(frame);
    1075                 return false;
    1076         }
    1077         /* cleanup */
    1078 
    1079         len = strlen(path);
    1080         if ( path[len-1] == '\\' || path[len-1] == '/') {
    1081                 path[len-1] = '\0';
    1082         }
    1083         nlen = 2*(strlen(path)+1);
    1084 
    1085         param = TALLOC_ARRAY(frame,char,6+nlen+2);
    1086         if (!param) {
    1087                 return false;
    1088         }
    1089         p = param;
    1090         memset(param, '\0', 6);
    1091 
    1092         SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
    1093         p += 6;
    1094         p += clistr_push(cli, p, path, nlen, STR_TERMINATE);
    1095         param_len = PTR_DIFF(p, param);
    1096 
    1097 
    1098         if (!cli_send_trans(cli, SMBtrans2,
    1099                         NULL,                        /* name */
    1100                         -1, 0,                       /* fid, flags */
    1101                         &setup, 1, 0,                /* setup, length, max */
    1102                         param, param_len, 2,         /* param, length, max */
    1103                         NULL,  0, cli->max_xmit      /* data, length, max */
    1104                         )) {
    1105                 TALLOC_FREE(frame);
    1106                 return False;
    1107         }
    1108 
     1227        struct event_context *ev;
     1228        struct tevent_req *req;
     1229        NTSTATUS status = NT_STATUS_NO_MEMORY;
     1230
     1231        if (cli_has_async_calls(cli)) {
     1232                /*
     1233                 * Can't use sync call while an async call is in flight
     1234                 */
     1235                status = NT_STATUS_INVALID_PARAMETER;
     1236                goto fail;
     1237        }
     1238        ev = event_context_init(frame);
     1239        if (ev == NULL) {
     1240                goto fail;
     1241        }
     1242        req = cli_qpathinfo_basic_send(frame, ev, cli, name);
     1243        if (req == NULL) {
     1244                goto fail;
     1245        }
     1246        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     1247                goto fail;
     1248        }
     1249        status = cli_qpathinfo_basic_recv(req, sbuf, attributes);
     1250 fail:
    11091251        TALLOC_FREE(frame);
    1110 
    1111         if (!cli_receive_trans(cli, SMBtrans2,
    1112                 &rparam, &param_len,
    1113                 &rdata, &data_len)) {
    1114                         return False;
    1115         }
    1116 
    1117         if (data_len < 36) {
    1118                 SAFE_FREE(rdata);
    1119                 SAFE_FREE(rparam);
    1120                 return False;
    1121         }
    1122 
    1123         sbuf->st_ex_atime = interpret_long_date( rdata+8 ); /* Access time. */
    1124         sbuf->st_ex_mtime = interpret_long_date( rdata+16 ); /* Write time. */
    1125         sbuf->st_ex_ctime = interpret_long_date( rdata+24 ); /* Change time. */
    1126 
    1127         *attributes = IVAL( rdata, 32 );
    1128 
    1129         SAFE_FREE(rparam);
    1130         SAFE_FREE(rdata);
    1131 
    1132         return True;
    1133 }
    1134 
    1135 /****************************************************************************
    1136  Send a qfileinfo call.
    1137 ****************************************************************************/
    1138 
    1139 bool cli_qfileinfo_test(struct cli_state *cli, uint16_t fnum, int level, char **poutdata, uint32 *poutlen)
    1140 {
    1141         unsigned int data_len = 0;
    1142         unsigned int param_len = 0;
    1143         uint16 setup = TRANSACT2_QFILEINFO;
    1144         char param[4];
    1145         char *rparam=NULL, *rdata=NULL;
    1146 
    1147         *poutdata = NULL;
    1148         *poutlen = 0;
    1149 
    1150         /* if its a win95 server then fail this - win95 totally screws it
    1151            up */
    1152         if (cli->win95)
    1153                 return False;
    1154 
    1155         param_len = 4;
    1156 
    1157         SSVAL(param, 0, fnum);
    1158         SSVAL(param, 2, level);
    1159 
    1160         if (!cli_send_trans(cli, SMBtrans2,
    1161                             NULL,                           /* name */
    1162                             -1, 0,                          /* fid, flags */
    1163                             &setup, 1, 0,                   /* setup, length, max */
    1164                             param, param_len, 2,            /* param, length, max */
    1165                             NULL, data_len, cli->max_xmit   /* data, length, max */
    1166                            )) {
    1167                 return False;
    1168         }
    1169 
    1170         if (!cli_receive_trans(cli, SMBtrans2,
    1171                                &rparam, &param_len,
    1172                                &rdata, &data_len)) {
    1173                 return False;
    1174         }
    1175 
    1176         *poutdata = (char *)memdup(rdata, data_len);
    1177         if (!*poutdata) {
    1178                 SAFE_FREE(rdata);
    1179                 SAFE_FREE(rparam);
    1180                 return False;
    1181         }
    1182 
    1183         *poutlen = data_len;
    1184 
    1185         SAFE_FREE(rdata);
    1186         SAFE_FREE(rparam);
    1187         return True;
     1252        if (!NT_STATUS_IS_OK(status)) {
     1253                cli_set_error(cli, status);
     1254        }
     1255        return status;
    11881256}
    11891257
     
    11941262NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
    11951263{
    1196         unsigned int data_len = 0;
    1197         unsigned int param_len = 0;
    1198         uint16 setup = TRANSACT2_QPATHINFO;
    1199         char *param;
    1200         char *rparam=NULL, *rdata=NULL;
    1201         int count=8;
    1202         char *p;
    1203         bool ret;
     1264        uint8_t *rdata;
     1265        uint32_t num_rdata;
    12041266        unsigned int len;
    1205         size_t nlen = 2*(strlen(fname)+1);
    1206 
    1207         param = SMB_MALLOC_ARRAY(char, 6+nlen+2);
    1208         if (!param) {
     1267        char *converted = NULL;
     1268        size_t converted_size = 0;
     1269        NTSTATUS status;
     1270
     1271        status = cli_qpathinfo(talloc_tos(), cli, fname,
     1272                               SMB_QUERY_FILE_ALT_NAME_INFO,
     1273                               4, cli->max_xmit, &rdata, &num_rdata);
     1274        if (!NT_STATUS_IS_OK(status)) {
     1275                return status;
     1276        }
     1277
     1278        len = IVAL(rdata, 0);
     1279
     1280        if (len > num_rdata - 4) {
     1281                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     1282        }
     1283
     1284        /* The returned data is a pushed string, not raw data. */
     1285        if (!convert_string_talloc(talloc_tos(),
     1286                                   cli_ucs2(cli) ? CH_UTF16LE : CH_DOS,
     1287                                   CH_UNIX,
     1288                                   rdata + 4,
     1289                                   len,
     1290                                   &converted,
     1291                                   &converted_size,
     1292                                   true)) {
    12091293                return NT_STATUS_NO_MEMORY;
    12101294        }
    1211         p = param;
    1212         memset(param, '\0', 6);
    1213         SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
    1214         p += 6;
    1215         p += clistr_push(cli, p, fname, nlen, STR_TERMINATE);
    1216         param_len = PTR_DIFF(p, param);
    1217 
    1218         do {
    1219                 ret = (cli_send_trans(cli, SMBtrans2,
    1220                                       NULL,           /* Name */
    1221                                       -1, 0,          /* fid, flags */
    1222                                       &setup, 1, 0,   /* setup, length, max */
    1223                                       param, param_len, 10, /* param, length, max */
    1224                                       NULL, data_len, cli->max_xmit /* data, length, max */
    1225                                       ) &&
    1226                        cli_receive_trans(cli, SMBtrans2,
    1227                                          &rparam, &param_len,
    1228                                          &rdata, &data_len));
    1229                 if (!ret && cli_is_dos_error(cli)) {
    1230                         /* we need to work around a Win95 bug - sometimes
    1231                            it gives ERRSRV/ERRerror temprarily */
    1232                         uint8 eclass;
    1233                         uint32 ecode;
    1234                         cli_dos_error(cli, &eclass, &ecode);
    1235                         if (eclass != ERRSRV || ecode != ERRerror) break;
    1236                         smb_msleep(100);
    1237                 }
    1238         } while (count-- && ret==False);
    1239 
    1240         SAFE_FREE(param);
    1241 
    1242         if (!ret || !rdata || data_len < 4) {
    1243                 return NT_STATUS_UNSUCCESSFUL;
    1244         }
    1245 
    1246         len = IVAL(rdata, 0);
    1247 
    1248         if (len > data_len - 4) {
    1249                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    1250         }
    1251 
    1252         clistr_pull(cli->inbuf, alt_name, rdata+4, sizeof(fstring), len,
    1253                     STR_UNICODE);
    1254 
    1255         SAFE_FREE(rdata);
    1256         SAFE_FREE(rparam);
     1295        fstrcpy(alt_name, converted);
     1296
     1297        TALLOC_FREE(converted);
     1298        TALLOC_FREE(rdata);
    12571299
    12581300        return NT_STATUS_OK;
  • vendor/current/source3/libsmb/clirap2.c

    r597 r740  
    7777
    7878#include "includes.h"
     79#include "libsmb/libsmb.h"
     80#include "../librpc/gen_ndr/rap.h"
     81#include "../librpc/gen_ndr/svcctl.h"
     82#include "libsmb/clirap.h"
    7983
    8084#define WORDSIZE 2
     
    285289****************************************************************************/
    286290
    287 int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 *grinfo)
     291int cli_NetGroupAdd(struct cli_state *cli, struct rap_group_info_1 *grinfo)
    288292{
    289293        char *rparam = NULL;
     
    321325
    322326        p = data;
    323         PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
     327        PUTSTRINGF(p, (const char *)grinfo->group_name, RAP_GROUPNAME_LEN);
    324328        PUTBYTE(p, 0); /* pad byte 0 */
    325329        PUTSTRINGP(p, grinfo->comment, data, soffset);
     
    831835****************************************************************************/
    832836
    833 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
     837int cli_NetUserAdd(struct cli_state *cli, struct rap_user_info_1 * userinfo )
    834838{
    835839        char *rparam = NULL;
     
    864868        PUTWORD(p, 0); /* pwencrypt */
    865869        if(userinfo->passwrd)
    866                 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
     870                PUTWORD(p,MIN(strlen((const char *)userinfo->passwrd), RAP_UPASSWD_LEN));
    867871        else
    868872                PUTWORD(p, 0); /* password length */
     
    871875        memset(data, '\0', soffset);
    872876
    873         PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
     877        PUTSTRINGF(p, (const char *)userinfo->user_name, RAP_USERNAME_LEN);
    874878        PUTBYTE(p, 0); /* pad byte 0 */
    875         PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
     879        PUTSTRINGF(p, (const char *)userinfo->passwrd, RAP_UPASSWD_LEN);
    876880        PUTDWORD(p, 0); /* pw age - n.a. on user add */
    877881        PUTWORD(p, userinfo->priv);
     
    13341338****************************************************************************/
    13351339
    1336 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
     1340int cli_NetShareAdd(struct cli_state *cli, struct rap_share_info_2 * sinfo )
    13371341{
    13381342        char *rparam = NULL;
     
    13661370
    13671371        p = data;
    1368         PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
     1372        PUTSTRINGF(p, (const char *)sinfo->share_name, RAP_SHARENAME_LEN);
    13691373        PUTBYTE(p, 0); /* pad byte 0 */
    13701374
     
    13751379        PUTWORD(p, sinfo->active_users);
    13761380        PUTSTRINGP(p, sinfo->path, data, soffset);
    1377         PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
     1381        PUTSTRINGF(p, (const char *)sinfo->password, RAP_SPASSWD_LEN);
    13781382        SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
    13791383
     
    19001904int cli_NetPrintQEnum(struct cli_state *cli,
    19011905                void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
    1902                 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint_t,uint_t,const char*))
     1906                void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,unsigned int,unsigned int,const char*))
    19031907{
    19041908        char param[WORDSIZE                         /* api number    */
     
    20762080int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
    20772081        void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
    2078         void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint_t,uint_t,const char*))
     2082        void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,unsigned int,unsigned int,const char*))
    20792083{
    20802084        char param[WORDSIZE                         /* api number    */
     
    23362340****************************************************************************/
    23372341
    2338 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint_t, uint_t, uint_t, char *))
     2342int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, unsigned int, unsigned int, unsigned int, char *))
    23392343{
    23402344        char param[WORDSIZE                       /* api number    */
     
    24362440
    24372441int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation,
    2438                 void (*fn)(const char *, const char *, uint16, uint16, uint16, uint_t, uint_t, uint_t, const char *))
     2442                void (*fn)(const char *, const char *, uint16, uint16, uint16, unsigned int, unsigned int, unsigned int, const char *))
    24392443{
    24402444        char param[WORDSIZE                          /* api number    */
  • vendor/current/source3/libsmb/clireadwrite.c

    r594 r740  
    1919
    2020#include "includes.h"
     21#include "libsmb/libsmb.h"
     22#include "../lib/util/tevent_ntstatus.h"
     23#include "async_smb.h"
     24#include "trans2.h"
    2125
    2226/****************************************************************************
     
    2529static size_t cli_read_max_bufsize(struct cli_state *cli)
    2630{
     31        size_t data_offset = smb_size - 4;
     32        size_t wct = 12;
     33
     34        size_t useable_space;
     35
    2736        if (!client_is_signing_on(cli) && !cli_encryption_on(cli)
    28             && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
     37            && (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
    2938                return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE;
    3039        }
     
    3443                        : CLI_WINDOWS_MAX_LARGE_READX_SIZE;
    3544        }
    36         return (cli->max_xmit - (smb_size+32)) & ~1023;
     45
     46        data_offset += wct * sizeof(uint16_t);
     47        data_offset += 1; /* pad */
     48
     49        useable_space = cli->max_xmit - data_offset;
     50
     51        return useable_space;
    3752}
    3853
     
    4055  Calculate the recommended write buffer size
    4156****************************************************************************/
    42 static size_t cli_write_max_bufsize(struct cli_state *cli, uint16_t write_mode)
     57static size_t cli_write_max_bufsize(struct cli_state *cli,
     58                                    uint16_t write_mode,
     59                                    uint8_t wct)
    4360{
    4461        if (write_mode == 0 &&
    4562            !client_is_signing_on(cli) &&
    4663            !cli_encryption_on(cli) &&
    47             (cli->posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) &&
     64            (cli->server_posix_capabilities & CIFS_UNIX_LARGE_WRITE_CAP) &&
    4865            (cli->capabilities & CAP_LARGE_FILES)) {
    4966                /* Only do massive writes if we can do them direct
     
    5976            || client_is_signing_on(cli)
    6077            || strequal(cli->dev, "LPT1:")) {
    61 
    62                 /*
    63                  * Printer devices are restricted to max_xmit writesize in
    64                  * Vista and XPSP3 as are signing connections.
    65                  */
    66 
    67                 return (cli->max_xmit - (smb_size+32)) & ~1023;
     78                size_t data_offset = smb_size - 4;
     79                size_t useable_space;
     80
     81                data_offset += wct * sizeof(uint16_t);
     82                data_offset += 1; /* pad */
     83
     84                useable_space = cli->max_xmit - data_offset;
     85
     86                return useable_space;
    6887        }
    6988
     
    89108        struct tevent_req *req, *subreq;
    90109        struct cli_read_andx_state *state;
    91         bool bigoffset = False;
    92110        uint8_t wct = 10;
    93111
     
    117135
    118136        if ((uint64_t)offset >> 32) {
    119                 bigoffset = true;
    120137                SIVAL(state->vwv + 10, 0,
    121138                      (((uint64_t)offset)>>32) & 0xffffffff);
     
    149166
    150167        status = cli_smb_req_send(subreq);
    151         if (!NT_STATUS_IS_OK(status)) {
    152                 tevent_req_nterror(req, status);
     168        if (tevent_req_nterror(req, status)) {
    153169                return tevent_req_post(req, ev);
    154170        }
     
    168184        uint8_t *bytes;
    169185
    170         state->status = cli_smb_recv(subreq, 12, &wct, &vwv, &num_bytes,
    171                                      &bytes);
     186        state->status = cli_smb_recv(subreq, state, &inbuf, 12, &wct, &vwv,
     187                                     &num_bytes, &bytes);
     188        TALLOC_FREE(subreq);
    172189        if (NT_STATUS_IS_ERR(state->status)) {
    173190                tevent_req_nterror(req, state->status);
     
    197214        }
    198215
    199         inbuf = cli_smb_inbuf(subreq);
    200216        state->buf = (uint8_t *)smb_base(inbuf) + SVAL(vwv+6, 0);
    201217
     
    283299
    284300        status = cli_read_andx_recv(subreq, &received, &buf);
    285         if (!NT_STATUS_IS_OK(status)) {
    286                 tevent_req_nterror(req, status);
     301        if (tevent_req_nterror(req, status)) {
    287302                return;
    288303        }
     
    411426        char *result;
    412427
    413         result = tevent_req_print(mem_ctx, req);
     428        result = tevent_req_default_print(req, mem_ctx);
    414429        if (result == NULL) {
    415430                return NULL;
     
    570585                status = state->sink((char *)top_subreq->buf,
    571586                                     top_subreq->received, state->priv);
    572                 if (!NT_STATUS_IS_OK(status)) {
    573                         tevent_req_nterror(state->req, status);
     587                if (tevent_req_nterror(state->req, status)) {
    574588                        return;
    575589                }
     
    697711
    698712/****************************************************************************
    699  Issue a single SMBwrite and don't wait for a reply.
    700 ****************************************************************************/
    701 
    702 static bool cli_issue_write(struct cli_state *cli,
    703                                 uint16_t fnum,
    704                                 off_t offset,
    705                                 uint16 mode,
    706                                 const char *buf,
    707                                 size_t size)
    708 {
    709         char *p;
    710         bool large_writex = false;
    711         /* We can only do direct writes if not signing and not encrypting. */
    712         bool direct_writes = !client_is_signing_on(cli) && !cli_encryption_on(cli);
    713 
    714         if (!direct_writes && size + 1 > cli->bufsize) {
    715                 cli->outbuf = (char *)SMB_REALLOC(cli->outbuf, size + 1024);
    716                 if (!cli->outbuf) {
    717                         return False;
    718                 }
    719                 cli->inbuf = (char *)SMB_REALLOC(cli->inbuf, size + 1024);
    720                 if (cli->inbuf == NULL) {
    721                         SAFE_FREE(cli->outbuf);
    722                         return False;
    723                 }
    724                 cli->bufsize = size + 1024;
    725         }
    726 
    727         memset(cli->outbuf,'\0',smb_size);
    728         memset(cli->inbuf,'\0',smb_size);
    729 
    730         if (cli->capabilities & CAP_LARGE_FILES) {
    731                 large_writex = True;
    732         }
    733 
    734         if (large_writex) {
    735                 cli_set_message(cli->outbuf,14,0,True);
    736         } else {
    737                 cli_set_message(cli->outbuf,12,0,True);
    738         }
    739 
    740         SCVAL(cli->outbuf,smb_com,SMBwriteX);
    741         SSVAL(cli->outbuf,smb_tid,cli->cnum);
    742         cli_setup_packet(cli);
    743 
    744         SCVAL(cli->outbuf,smb_vwv0,0xFF);
    745         SSVAL(cli->outbuf,smb_vwv2,fnum);
    746 
    747         SIVAL(cli->outbuf,smb_vwv3,offset);
    748         SIVAL(cli->outbuf,smb_vwv5,0);
    749         SSVAL(cli->outbuf,smb_vwv7,mode);
    750 
    751         SSVAL(cli->outbuf,smb_vwv8,(mode & 0x0008) ? size : 0);
    752         /*
    753          * According to CIFS-TR-1p00, this following field should only
    754          * be set if CAP_LARGE_WRITEX is set. We should check this
    755          * locally. However, this check might already have been
    756          * done by our callers.
    757          */
    758         SSVAL(cli->outbuf,smb_vwv9,(size>>16));
    759         SSVAL(cli->outbuf,smb_vwv10,size);
    760         /* +1 is pad byte. */
    761         SSVAL(cli->outbuf,smb_vwv11,
    762               smb_buf(cli->outbuf) - smb_base(cli->outbuf) + 1);
    763 
    764         if (large_writex) {
    765                 SIVAL(cli->outbuf,smb_vwv12,(((uint64_t)offset)>>32) & 0xffffffff);
    766         }
    767 
    768         p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11) -1;
    769         *p++ = '\0'; /* pad byte. */
    770         if (!direct_writes) {
    771                 memcpy(p, buf, size);
    772         }
    773         if (size > 0x1FFFF) {
    774                 /* This is a POSIX 14 word large write. */
    775                 set_message_bcc(cli->outbuf, 0); /* Set bcc to zero. */
    776                 _smb_setlen_large(cli->outbuf,smb_size + 28 + 1 /* pad */ + size - 4);
    777         } else {
    778                 cli_setup_bcc(cli, p+size);
    779         }
    780 
    781         show_msg(cli->outbuf);
    782         if (direct_writes) {
    783                 /* For direct writes we now need to write the data
    784                  * directly out of buf. */
    785                 return cli_send_smb_direct_writeX(cli, buf, size);
    786         } else {
    787                 return cli_send_smb(cli);
    788         }
    789 }
    790 
    791 /****************************************************************************
    792   write to a file
    793   write_mode: 0x0001 disallow write cacheing
    794               0x0002 return bytes remaining
    795               0x0004 use raw named pipe protocol
    796               0x0008 start of message mode named pipe protocol
    797 ****************************************************************************/
    798 
    799 ssize_t cli_write(struct cli_state *cli,
    800                  uint16_t fnum, uint16 write_mode,
    801                  const char *buf, off_t offset, size_t size)
    802 {
    803         ssize_t bwritten = 0;
    804         unsigned int issued = 0;
    805         unsigned int received = 0;
    806         int mpx = 1;
    807         size_t writesize;
    808         int blocks;
    809 
    810         if(cli->max_mux > 1) {
    811                 mpx = cli->max_mux-1;
    812         } else {
    813                 mpx = 1;
    814         }
    815 
    816         writesize = cli_write_max_bufsize(cli, write_mode);
    817 
    818         blocks = (size + (writesize-1)) / writesize;
    819 
    820         while (received < blocks) {
    821 
    822                 while ((issued - received < mpx) && (issued < blocks)) {
    823                         ssize_t bsent = issued * writesize;
    824                         ssize_t size1 = MIN(writesize, size - bsent);
    825 
    826                         if (!cli_issue_write(cli, fnum, offset + bsent,
    827                                         write_mode,
    828                                         buf + bsent,
    829                                         size1))
    830                                 return -1;
    831                         issued++;
    832                 }
    833 
    834                 if (!cli_receive_smb(cli)) {
    835                         return bwritten;
    836                 }
    837 
    838                 received++;
    839 
    840                 if (cli_is_error(cli))
    841                         break;
    842 
    843                 bwritten += SVAL(cli->inbuf, smb_vwv2);
    844                 if (writesize > 0xFFFF) {
    845                         bwritten += (((int)(SVAL(cli->inbuf, smb_vwv4)))<<16);
    846                 }
    847         }
    848 
    849         while (received < issued && cli_receive_smb(cli)) {
    850                 received++;
    851         }
    852 
    853         return bwritten;
    854 }
    855 
    856 /****************************************************************************
    857713  write to a file using a SMBwrite and not bypassing 0 byte writes
    858714****************************************************************************/
    859715
    860 ssize_t cli_smbwrite(struct cli_state *cli,
    861                      uint16_t fnum, char *buf, off_t offset, size_t size1)
    862 {
    863         char *p;
     716NTSTATUS cli_smbwrite(struct cli_state *cli, uint16_t fnum, char *buf,
     717                      off_t offset, size_t size1, size_t *ptotal)
     718{
     719        uint8_t *bytes;
    864720        ssize_t total = 0;
     721
     722        /*
     723         * 3 bytes prefix
     724         */
     725
     726        bytes = TALLOC_ARRAY(talloc_tos(), uint8_t, 3);
     727        if (bytes == NULL) {
     728                return NT_STATUS_NO_MEMORY;
     729        }
     730        bytes[0] = 1;
    865731
    866732        do {
    867733                size_t size = MIN(size1, cli->max_xmit - 48);
    868 
    869                 memset(cli->outbuf,'\0',smb_size);
    870                 memset(cli->inbuf,'\0',smb_size);
    871 
    872                 cli_set_message(cli->outbuf,5, 0,True);
    873 
    874                 SCVAL(cli->outbuf,smb_com,SMBwrite);
    875                 SSVAL(cli->outbuf,smb_tid,cli->cnum);
    876                 cli_setup_packet(cli);
    877 
    878                 SSVAL(cli->outbuf,smb_vwv0,fnum);
    879                 SSVAL(cli->outbuf,smb_vwv1,size);
    880                 SIVAL(cli->outbuf,smb_vwv2,offset);
    881                 SSVAL(cli->outbuf,smb_vwv4,0);
    882 
    883                 p = smb_buf(cli->outbuf);
    884                 *p++ = 1;
    885                 SSVAL(p, 0, size); p += 2;
    886                 memcpy(p, buf + total, size); p += size;
    887 
    888                 cli_setup_bcc(cli, p);
    889 
    890                 if (!cli_send_smb(cli))
    891                         return -1;
    892 
    893                 if (!cli_receive_smb(cli))
    894                         return -1;
    895 
    896                 if (cli_is_error(cli))
    897                         return -1;
    898 
    899                 size = SVAL(cli->inbuf,smb_vwv0);
    900                 if (size == 0)
     734                struct tevent_req *req;
     735                uint16_t vwv[5];
     736                uint16_t *ret_vwv;
     737                NTSTATUS status;
     738
     739                SSVAL(vwv+0, 0, fnum);
     740                SSVAL(vwv+1, 0, size);
     741                SIVAL(vwv+2, 0, offset);
     742                SSVAL(vwv+4, 0, 0);
     743
     744                bytes = TALLOC_REALLOC_ARRAY(talloc_tos(), bytes, uint8_t,
     745                                             size+3);
     746                if (bytes == NULL) {
     747                        return NT_STATUS_NO_MEMORY;
     748                }
     749                SSVAL(bytes, 1, size);
     750                memcpy(bytes + 3, buf + total, size);
     751
     752                status = cli_smb(talloc_tos(), cli, SMBwrite, 0, 5, vwv,
     753                                 size+3, bytes, &req, 1, NULL, &ret_vwv,
     754                                 NULL, NULL);
     755                if (!NT_STATUS_IS_OK(status)) {
     756                        TALLOC_FREE(bytes);
     757                        return status;
     758                }
     759
     760                size = SVAL(ret_vwv+0, 0);
     761                TALLOC_FREE(req);
     762                if (size == 0) {
    901763                        break;
    902 
     764                }
    903765                size1 -= size;
    904766                total += size;
     
    907769        } while (size1);
    908770
    909         return total;
     771        TALLOC_FREE(bytes);
     772
     773        if (ptotal != NULL) {
     774                *ptotal = total;
     775        }
     776        return NT_STATUS_OK;
    910777}
    911778
     
    937804        bool bigoffset = ((cli->capabilities & CAP_LARGE_FILES) != 0);
    938805        uint8_t wct = bigoffset ? 14 : 12;
    939         size_t max_write = cli_write_max_bufsize(cli, mode);
     806        size_t max_write = cli_write_max_bufsize(cli, mode, wct);
    940807        uint16_t *vwv;
    941808
     
    1003870
    1004871        status = cli_smb_req_send(subreq);
    1005         if (!NT_STATUS_IS_OK(status)) {
    1006                 tevent_req_nterror(req, status);
     872        if (tevent_req_nterror(req, status)) {
    1007873                return tevent_req_post(req, ev);
    1008874        }
     
    1018884        uint8_t wct;
    1019885        uint16_t *vwv;
    1020         NTSTATUS status;
    1021 
    1022         status = cli_smb_recv(subreq, 6, &wct, &vwv, NULL, NULL);
     886        uint8_t *inbuf;
     887        NTSTATUS status;
     888
     889        status = cli_smb_recv(subreq, state, &inbuf, 6, &wct, &vwv,
     890                              NULL, NULL);
     891        TALLOC_FREE(subreq);
    1023892        if (NT_STATUS_IS_ERR(status)) {
    1024                 TALLOC_FREE(subreq);
    1025893                tevent_req_nterror(req, status);
    1026894                return;
     
    1102970        status = cli_write_andx_recv(subreq, &written);
    1103971        TALLOC_FREE(subreq);
    1104         if (!NT_STATUS_IS_OK(status)) {
    1105                 tevent_req_nterror(req, status);
     972        if (tevent_req_nterror(req, status)) {
    1106973                return;
    1107974        }
     
    1131998}
    1132999
    1133 static NTSTATUS cli_writeall_recv(struct tevent_req *req)
    1134 {
    1135         return tevent_req_simple_recv_ntstatus(req);
     1000static NTSTATUS cli_writeall_recv(struct tevent_req *req,
     1001                                  size_t *pwritten)
     1002{
     1003        struct cli_writeall_state *state = tevent_req_data(
     1004                req, struct cli_writeall_state);
     1005        NTSTATUS status;
     1006
     1007        if (tevent_req_is_nterror(req, &status)) {
     1008                return status;
     1009        }
     1010        if (pwritten != NULL) {
     1011                *pwritten = state->written;
     1012        }
     1013        return NT_STATUS_OK;
     1014}
     1015
     1016NTSTATUS cli_writeall(struct cli_state *cli, uint16_t fnum, uint16_t mode,
     1017                      const uint8_t *buf, off_t offset, size_t size,
     1018                      size_t *pwritten)
     1019{
     1020        TALLOC_CTX *frame = talloc_stackframe();
     1021        struct event_context *ev;
     1022        struct tevent_req *req;
     1023        NTSTATUS status = NT_STATUS_NO_MEMORY;
     1024
     1025        if (cli_has_async_calls(cli)) {
     1026                /*
     1027                 * Can't use sync call while an async call is in flight
     1028                 */
     1029                status = NT_STATUS_INVALID_PARAMETER;
     1030                goto fail;
     1031        }
     1032        ev = event_context_init(frame);
     1033        if (ev == NULL) {
     1034                goto fail;
     1035        }
     1036        req = cli_writeall_send(frame, ev, cli, fnum, mode, buf, offset, size);
     1037        if (req == NULL) {
     1038                goto fail;
     1039        }
     1040        if (!tevent_req_poll(req, ev)) {
     1041                status = map_nt_error_from_unix(errno);
     1042                goto fail;
     1043        }
     1044        status = cli_writeall_recv(req, pwritten);
     1045 fail:
     1046        TALLOC_FREE(frame);
     1047        if (!NT_STATUS_IS_OK(status)) {
     1048                cli_set_error(cli, status);
     1049        }
     1050        return status;
    11361051}
    11371052
     
    12451160        state->next_offset = start_offset;
    12461161
    1247         state->chunk_size = cli_write_max_bufsize(cli, mode);
     1162        state->chunk_size = cli_write_max_bufsize(cli, mode, 14);
    12481163
    12491164        if (window_size == 0) {
     
    12981213        state->pending -= 1;
    12991214
    1300         status = cli_writeall_recv(subreq);
     1215        status = cli_writeall_recv(subreq, NULL);
    13011216        TALLOC_FREE(subreq);
    13021217        TALLOC_FREE(substate);
    1303         if (!NT_STATUS_IS_OK(status)) {
    1304                 tevent_req_nterror(req, status);
     1218        if (tevent_req_nterror(req, status)) {
    13051219                return;
    13061220        }
  • vendor/current/source3/libsmb/clisecdesc.c

    r414 r740  
    33   client security descriptor functions
    44   Copyright (C) Andrew Tridgell 2000
    5    
     5
    66   This program is free software; you can redistribute it and/or modify
    77   it under the terms of the GNU General Public License as published by
    88   the Free Software Foundation; either version 3 of the License, or
    99   (at your option) any later version.
    10    
     10
    1111   This program is distributed in the hope that it will be useful,
    1212   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1313   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1414   GNU General Public License for more details.
    15    
     15
    1616   You should have received a copy of the GNU General Public License
    1717   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    1919
    2020#include "includes.h"
     21#include "libsmb/libsmb.h"
    2122
    2223/****************************************************************************
    2324  query the security descriptor for a open file
    2425 ****************************************************************************/
    25 SEC_DESC *cli_query_secdesc(struct cli_state *cli, uint16_t fnum,
     26struct security_descriptor *cli_query_secdesc(struct cli_state *cli, uint16_t fnum,
    2627                            TALLOC_CTX *mem_ctx)
    2728{
    2829        uint8_t param[8];
    29         uint8_t *rparam=NULL, *rdata=NULL;
    30         unsigned int rparam_count=0, rdata_count=0;
    31         SEC_DESC *psd = NULL;
     30        uint8_t *rdata=NULL;
     31        uint32_t rdata_count=0;
     32        struct security_descriptor *psd = NULL;
    3233        NTSTATUS status;
    3334
     
    4142                           param, 8, 4, /* param, length, max */
    4243                           NULL, 0, 0x10000, /* data, length, max */
    43                            NULL, NULL, /* rsetup, length */
    44                            &rparam, &rparam_count,
    45                            &rdata, &rdata_count);
     44                           NULL,             /* recv_flags2 */
     45                           NULL, 0, NULL, /* rsetup, length */
     46                           NULL, 0, NULL,
     47                           &rdata, 0, &rdata_count);
    4648
    4749        if (!NT_STATUS_IS_OK(status)) {
     
    6264 cleanup:
    6365
    64         TALLOC_FREE(rparam);
    6566        TALLOC_FREE(rdata);
    6667
     
    7172  set the security descriptor for a open file
    7273 ****************************************************************************/
    73 bool cli_set_secdesc(struct cli_state *cli, uint16_t fnum, SEC_DESC *sd)
     74NTSTATUS cli_set_secdesc(struct cli_state *cli, uint16_t fnum,
     75                         struct security_descriptor *sd)
    7476{
    75         char param[8];
    76         char *rparam=NULL, *rdata=NULL;
    77         unsigned int rparam_count=0, rdata_count=0;
     77        uint8_t param[8];
    7878        uint32 sec_info = 0;
    79         TALLOC_CTX *frame = talloc_stackframe();
    80         bool ret = False;
    8179        uint8 *data;
    8280        size_t len;
     
    8785                DEBUG(10, ("marshall_sec_desc failed: %s\n",
    8886                           nt_errstr(status)));
    89                 goto cleanup;
     87                return status;
    9088        }
    9189
     
    9391
    9492        if (sd->dacl)
    95                 sec_info |= DACL_SECURITY_INFORMATION;
     93                sec_info |= SECINFO_DACL;
    9694        if (sd->owner_sid)
    97                 sec_info |= OWNER_SECURITY_INFORMATION;
     95                sec_info |= SECINFO_OWNER;
    9896        if (sd->group_sid)
    99                 sec_info |= GROUP_SECURITY_INFORMATION;
     97                sec_info |= SECINFO_GROUP;
    10098        SSVAL(param, 4, sec_info);
    10199
    102         if (!cli_send_nt_trans(cli,
    103                                NT_TRANSACT_SET_SECURITY_DESC,
    104                                0,
    105                                NULL, 0, 0,
    106                                param, 8, 0,
    107                                (char *)data, len, 0)) {
    108                 DEBUG(1,("Failed to send NT_TRANSACT_SET_SECURITY_DESC\n"));
    109                 goto cleanup;
     100        status = cli_trans(talloc_tos(), cli, SMBnttrans,
     101                           NULL, -1, /* name, fid */
     102                           NT_TRANSACT_SET_SECURITY_DESC, 0,
     103                           NULL, 0, 0, /* setup */
     104                           param, 8, 0, /* param */
     105                           data, len, 0, /* data */
     106                           NULL,         /* recv_flags2 */
     107                           NULL, 0, NULL, /* rsetup */
     108                           NULL, 0, NULL, /* rparam */
     109                           NULL, 0, NULL); /* rdata */
     110        TALLOC_FREE(data);
     111        if (!NT_STATUS_IS_OK(status)) {
     112                DEBUG(1, ("Failed to send NT_TRANSACT_SET_SECURITY_DESC: %s\n",
     113                          nt_errstr(status)));
    110114        }
    111 
    112 
    113         if (!cli_receive_nt_trans(cli,
    114                                   &rparam, &rparam_count,
    115                                   &rdata, &rdata_count)) {
    116                 DEBUG(1,("NT_TRANSACT_SET_SECURITY_DESC failed\n"));
    117                 goto cleanup;
    118         }
    119 
    120         ret = True;
    121 
    122   cleanup:
    123 
    124         SAFE_FREE(rparam);
    125         SAFE_FREE(rdata);
    126 
    127         TALLOC_FREE(frame);
    128 
    129         return ret;
     115        return status;
    130116}
  • vendor/current/source3/libsmb/clisigning.c

    r414 r740  
    2121
    2222#include "includes.h"
     23#include "libsmb/libsmb.h"
     24#include "smb_signing.h"
    2325
    2426bool cli_simple_set_signing(struct cli_state *cli,
  • vendor/current/source3/libsmb/clispnego.c

    r587 r740  
    55   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
    66   Copyright (C) Luke Howard     2003
     7   Copyright (C) Jeremy Allison 2010
    78
    89   This program is free software; you can redistribute it and/or modify
     
    2324#include "../libcli/auth/spnego.h"
    2425#include "smb_krb5.h"
    25 
    26 /*
    27   generate a negTokenInit packet given a GUID, a list of supported
    28   OIDs (the mechanisms) and a principal name string
    29 */
    30 DATA_BLOB spnego_gen_negTokenInit(char guid[16],
    31                                   const char *OIDs[],
     26#include "../lib/util/asn1.h"
     27
     28/*
     29  generate a negTokenInit packet given a list of supported
     30  OIDs (the mechanisms) a blob, and a principal name string
     31*/
     32
     33DATA_BLOB spnego_gen_negTokenInit(TALLOC_CTX *ctx,
     34                                  const char *OIDs[],
     35                                  DATA_BLOB *psecblob,
    3236                                  const char *principal)
    3337{
     
    4145        }
    4246
    43         asn1_write(data, guid, 16);
    4447        asn1_push_tag(data,ASN1_APPLICATION(0));
    4548        asn1_write_OID(data,OID_SPNEGO);
     
    5558        asn1_pop_tag(data);
    5659
    57         asn1_push_tag(data, ASN1_CONTEXT(3));
    58         asn1_push_tag(data, ASN1_SEQUENCE(0));
    59         asn1_push_tag(data, ASN1_CONTEXT(0));
    60         asn1_write_GeneralString(data,principal);
    61         asn1_pop_tag(data);
    62         asn1_pop_tag(data);
    63         asn1_pop_tag(data);
     60        if (psecblob && psecblob->length && psecblob->data) {
     61                asn1_push_tag(data, ASN1_CONTEXT(2));
     62                asn1_write_OctetString(data,psecblob->data,
     63                        psecblob->length);
     64                asn1_pop_tag(data);
     65        }
     66
     67        if (principal) {
     68                asn1_push_tag(data, ASN1_CONTEXT(3));
     69                asn1_push_tag(data, ASN1_SEQUENCE(0));
     70                asn1_push_tag(data, ASN1_CONTEXT(0));
     71                asn1_write_GeneralString(data,principal);
     72                asn1_pop_tag(data);
     73                asn1_pop_tag(data);
     74                asn1_pop_tag(data);
     75        }
    6476
    6577        asn1_pop_tag(data);
     
    7284        }
    7385
    74         ret = data_blob(data->data, data->length);
    75         asn1_free(data);
    76 
    77         return ret;
    78 }
    79 
    80 /*
    81   Generate a negTokenInit as used by the client side ... It has a mechType
    82   (OID), and a mechToken (a security blob) ...
    83 
    84   Really, we need to break out the NTLMSSP stuff as well, because it could be
    85   raw in the packets!
    86 */
    87 DATA_BLOB gen_negTokenInit(const char *OID, DATA_BLOB blob)
    88 {
    89         ASN1_DATA *data;
    90         DATA_BLOB ret;
    91 
    92         data = asn1_init(talloc_tos());
    93         if (data == NULL) {
    94                 return data_blob_null;
    95         }
    96 
    97         asn1_push_tag(data, ASN1_APPLICATION(0));
    98         asn1_write_OID(data,OID_SPNEGO);
    99         asn1_push_tag(data, ASN1_CONTEXT(0));
    100         asn1_push_tag(data, ASN1_SEQUENCE(0));
    101 
    102         asn1_push_tag(data, ASN1_CONTEXT(0));
    103         asn1_push_tag(data, ASN1_SEQUENCE(0));
    104         asn1_write_OID(data, OID);
    105         asn1_pop_tag(data);
    106         asn1_pop_tag(data);
    107 
    108         asn1_push_tag(data, ASN1_CONTEXT(2));
    109         asn1_write_OctetString(data,blob.data,blob.length);
    110         asn1_pop_tag(data);
    111 
    112         asn1_pop_tag(data);
    113         asn1_pop_tag(data);
    114 
    115         asn1_pop_tag(data);
    116 
    117         if (data->has_error) {
    118                 DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data->ofs));
    119         }
    120 
    121         ret = data_blob(data->data, data->length);
     86        ret = data_blob_talloc(ctx, data->data, data->length);
    12287        asn1_free(data);
    12388
     
    12994  OIDs (the mechanisms) and a principal name string
    13095*/
    131 bool spnego_parse_negTokenInit(DATA_BLOB blob,
     96bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
     97                               DATA_BLOB blob,
    13298                               char *OIDs[ASN1_MAX_OIDS],
    133                                char **principal)
     99                               char **principal,
     100                               DATA_BLOB *secblob)
    134101{
    135102        int i;
     
    160127        asn1_start_tag(data,ASN1_SEQUENCE(0));
    161128        for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) {
    162                 const char *oid_str = NULL;
    163                 asn1_read_OID(data,talloc_autofree_context(),&oid_str);
    164                 OIDs[i] = CONST_DISCARD(char *, oid_str);
     129                asn1_read_OID(data,ctx, &OIDs[i]);
    165130        }
    166131        OIDs[i] = NULL;
     
    168133        asn1_end_tag(data);
    169134
    170         *principal = NULL;
     135        if (principal) {
     136                *principal = NULL;
     137        }
     138        if (secblob) {
     139                *secblob = data_blob_null;
     140        }
    171141
    172142        /*
     
    191161
    192162        if (asn1_peek_tag(data, ASN1_CONTEXT(2))) {
     163                DATA_BLOB sblob = data_blob_null;
    193164                /* mechToken [2] OCTET STRING  OPTIONAL */
    194                 DATA_BLOB token;
    195165                asn1_start_tag(data, ASN1_CONTEXT(2));
    196                 asn1_read_OctetString(data, talloc_autofree_context(),
    197                         &token);
    198                 asn1_end_tag(data);
    199                 /* Throw away the token - not used. */
    200                 data_blob_free(&token);
     166                asn1_read_OctetString(data, ctx, &sblob);
     167                asn1_end_tag(data);
     168                if (secblob) {
     169                        *secblob = sblob;
     170                } else {
     171                        data_blob_free(&sblob);
     172                }
    201173        }
    202174
    203175        if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
     176                char *princ = NULL;
    204177                /* mechListMIC [3] OCTET STRING  OPTIONAL */
    205178                asn1_start_tag(data, ASN1_CONTEXT(3));
    206179                asn1_start_tag(data, ASN1_SEQUENCE(0));
    207180                asn1_start_tag(data, ASN1_CONTEXT(0));
    208                 asn1_read_GeneralString(data,talloc_autofree_context(),
    209                         principal);
    210                 asn1_end_tag(data);
    211                 asn1_end_tag(data);
    212                 asn1_end_tag(data);
     181                asn1_read_GeneralString(data, ctx, &princ);
     182                asn1_end_tag(data);
     183                asn1_end_tag(data);
     184                asn1_end_tag(data);
     185                if (principal) {
     186                        *principal = princ;
     187                } else {
     188                        TALLOC_FREE(princ);
     189                }
    213190        }
    214191
     
    221198        if (data->has_error) {
    222199                int j;
    223                 TALLOC_FREE(*principal);
     200                if (principal) {
     201                        TALLOC_FREE(*principal);
     202                }
     203                if (secblob) {
     204                        data_blob_free(secblob);
     205                }
    224206                for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) {
    225207                        TALLOC_FREE(OIDs[j]);
     
    232214
    233215/*
    234   generate a negTokenTarg packet given a list of OIDs and a security blob
    235 */
    236 DATA_BLOB gen_negTokenTarg(const char *OIDs[], DATA_BLOB blob)
    237 {
    238         int i;
    239         ASN1_DATA *data;
    240         DATA_BLOB ret;
    241 
    242         data = asn1_init(talloc_tos());
    243         if (data == NULL) {
    244                 return data_blob_null;
    245         }
    246 
    247         asn1_push_tag(data, ASN1_APPLICATION(0));
    248         asn1_write_OID(data,OID_SPNEGO);
    249         asn1_push_tag(data, ASN1_CONTEXT(0));
    250         asn1_push_tag(data, ASN1_SEQUENCE(0));
    251 
    252         asn1_push_tag(data, ASN1_CONTEXT(0));
    253         asn1_push_tag(data, ASN1_SEQUENCE(0));
    254         for (i=0; OIDs[i]; i++) {
    255                 asn1_write_OID(data,OIDs[i]);
    256         }
    257         asn1_pop_tag(data);
    258         asn1_pop_tag(data);
    259 
    260         asn1_push_tag(data, ASN1_CONTEXT(2));
    261         asn1_write_OctetString(data,blob.data,blob.length);
    262         asn1_pop_tag(data);
    263 
    264         asn1_pop_tag(data);
    265         asn1_pop_tag(data);
    266 
    267         asn1_pop_tag(data);
    268 
    269         if (data->has_error) {
    270                 DEBUG(1,("Failed to build negTokenTarg at offset %d\n", (int)data->ofs));
    271         }
    272 
    273         ret = data_blob(data->data, data->length);
    274         asn1_free(data);
    275 
    276         return ret;
    277 }
    278 
    279 /*
    280   parse a negTokenTarg packet giving a list of OIDs and a security blob
    281 */
    282 bool parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *secblob)
    283 {
    284         int i;
    285         ASN1_DATA *data;
    286 
    287         data = asn1_init(talloc_tos());
    288         if (data == NULL) {
    289                 return false;
    290         }
    291 
    292         asn1_load(data, blob);
    293         asn1_start_tag(data, ASN1_APPLICATION(0));
    294         asn1_check_OID(data,OID_SPNEGO);
    295         asn1_start_tag(data, ASN1_CONTEXT(0));
    296         asn1_start_tag(data, ASN1_SEQUENCE(0));
    297 
    298         asn1_start_tag(data, ASN1_CONTEXT(0));
    299         asn1_start_tag(data, ASN1_SEQUENCE(0));
    300         for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) {
    301                 const char *oid_str = NULL;
    302                 asn1_read_OID(data,talloc_autofree_context(),&oid_str);
    303                 OIDs[i] = CONST_DISCARD(char *, oid_str);
    304         }
    305         OIDs[i] = NULL;
    306         asn1_end_tag(data);
    307         asn1_end_tag(data);
    308 
    309         /* Skip any optional req_flags that are sent per RFC 4178 */
    310         if (asn1_peek_tag(data, ASN1_CONTEXT(1))) {
    311                 uint8 flags;
    312 
    313                 asn1_start_tag(data, ASN1_CONTEXT(1));
    314                 asn1_start_tag(data, ASN1_BIT_STRING);
    315                 while (asn1_tag_remaining(data) > 0)
    316                         asn1_read_uint8(data, &flags);
    317                 asn1_end_tag(data);
    318                 asn1_end_tag(data);
    319         }
    320 
    321         asn1_start_tag(data, ASN1_CONTEXT(2));
    322         asn1_read_OctetString(data,talloc_autofree_context(),secblob);
    323         asn1_end_tag(data);
    324 
    325         asn1_end_tag(data);
    326         asn1_end_tag(data);
    327 
    328         asn1_end_tag(data);
    329 
    330         if (data->has_error) {
    331                 int j;
    332                 data_blob_free(secblob);
    333                 for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) {
    334                         TALLOC_FREE(OIDs[j]);
    335                 }
    336                 DEBUG(1,("Failed to parse negTokenTarg at offset %d\n", (int)data->ofs));
    337                 asn1_free(data);
    338                 return False;
    339         }
    340 
    341         asn1_free(data);
    342         return True;
    343 }
    344 
    345 /*
    346216  generate a krb5 GSS-API wrapper packet given a ticket
    347217*/
    348 DATA_BLOB spnego_gen_krb5_wrap(const DATA_BLOB ticket, const uint8 tok_id[2])
     218DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const uint8 tok_id[2])
    349219{
    350220        ASN1_DATA *data;
     
    367237        }
    368238
    369         ret = data_blob(data->data, data->length);
     239        ret = data_blob_talloc(ctx, data->data, data->length);
    370240        asn1_free(data);
    371241
     
    376246  parse a krb5 GSS-API wrapper packet giving a ticket
    377247*/
    378 bool spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
     248bool spnego_parse_krb5_wrap(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
    379249{
    380250        bool ret;
     
    398268                asn1_read(data, tok_id, 2);
    399269                data_remaining -= 2;
    400                 *ticket = data_blob(NULL, data_remaining);
     270                *ticket = data_blob_talloc(ctx, NULL, data_remaining);
    401271                asn1_read(data, ticket->data, ticket->length);
    402272        }
     
    417287
    418288/*
    419    generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
    420    kerberos session setup
    421 */
    422 int spnego_gen_negTokenTarg(const char *principal, int time_offset,
    423                             DATA_BLOB *targ,
     289   generate a SPNEGO krb5 negTokenInit packet, ready for a EXTENDED_SECURITY
     290   kerberos session setup
     291*/
     292int spnego_gen_krb5_negTokenInit(TALLOC_CTX *ctx,
     293                            const char *principal, int time_offset,
     294                            DATA_BLOB *targ,
    424295                            DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
    425296                            time_t *expire_time)
     
    430301
    431302        /* get a kerberos ticket for the service and extract the session key */
    432         retval = cli_krb5_get_ticket(principal, time_offset,
    433                                         &tkt, session_key_krb5, extra_ap_opts, NULL,
    434                                         expire_time, NULL);
    435 
    436         if (retval)
     303        retval = cli_krb5_get_ticket(ctx, principal, time_offset,
     304                                          &tkt, session_key_krb5,
     305                                          extra_ap_opts, NULL,
     306                                          expire_time, NULL);
     307        if (retval) {
    437308                return retval;
     309        }
    438310
    439311        /* wrap that up in a nice GSS-API wrapping */
    440         tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
     312        tkt_wrapped = spnego_gen_krb5_wrap(ctx, tkt, TOK_ID_KRB_AP_REQ);
    441313
    442314        /* and wrap that in a shiny SPNEGO wrapper */
    443         *targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
     315        *targ = spnego_gen_negTokenInit(ctx, krb_mechs, &tkt_wrapped, NULL);
    444316
    445317        data_blob_free(&tkt_wrapped);
     
    453325  parse a spnego NTLMSSP challenge packet giving two security blobs
    454326*/
    455 bool spnego_parse_challenge(const DATA_BLOB blob,
     327bool spnego_parse_challenge(TALLOC_CTX *ctx, const DATA_BLOB blob,
    456328                            DATA_BLOB *chal1, DATA_BLOB *chal2)
    457329{
     
    480352
    481353        asn1_start_tag(data,ASN1_CONTEXT(2));
    482         asn1_read_OctetString(data, talloc_autofree_context(), chal1);
     354        asn1_read_OctetString(data, ctx, chal1);
    483355        asn1_end_tag(data);
    484356
     
    486358        if (asn1_tag_remaining(data)) {
    487359                asn1_start_tag(data,ASN1_CONTEXT(3));
    488                 asn1_read_OctetString(data, talloc_autofree_context(), chal2);
     360                asn1_read_OctetString(data, ctx, chal2);
    489361                asn1_end_tag(data);
    490362        }
     
    508380 generate a SPNEGO auth packet. This will contain the encrypted passwords
    509381*/
    510 DATA_BLOB spnego_gen_auth(DATA_BLOB blob)
     382DATA_BLOB spnego_gen_auth(TALLOC_CTX *ctx, DATA_BLOB blob)
    511383{
    512384        ASN1_DATA *data;
     
    526398        asn1_pop_tag(data);
    527399
    528         ret = data_blob(data->data, data->length);
     400        ret = data_blob_talloc(ctx, data->data, data->length);
    529401
    530402        asn1_free(data);
     
    536408 parse a SPNEGO auth packet. This contains the encrypted passwords
    537409*/
    538 bool spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
     410bool spnego_parse_auth_and_mic(TALLOC_CTX *ctx, DATA_BLOB blob,
     411                                DATA_BLOB *auth, DATA_BLOB *signature)
    539412{
    540413        ssize_t len;
     
    554427        }
    555428
    556         *auth = data_blob_talloc(talloc_tos(),
     429        *auth = data_blob_talloc(ctx,
    557430                                 token.negTokenTarg.responseToken.data,
    558431                                 token.negTokenTarg.responseToken.length);
     432
     433        if (!signature) {
     434                goto done;
     435        }
     436
     437        *signature = data_blob_talloc(ctx,
     438                                 token.negTokenTarg.mechListMIC.data,
     439                                 token.negTokenTarg.mechListMIC.length);
     440
     441done:
    559442        spnego_free_data(&token);
    560443
     
    562445}
    563446
     447bool spnego_parse_auth(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *auth)
     448{
     449        return spnego_parse_auth_and_mic(ctx, blob, auth, NULL);
     450}
     451
    564452/*
    565453  generate a minimal SPNEGO response packet.  Doesn't contain much.
    566454*/
    567 DATA_BLOB spnego_gen_auth_response(DATA_BLOB *reply, NTSTATUS nt_status,
    568                                    const char *mechOID)
     455DATA_BLOB spnego_gen_auth_response_and_mic(TALLOC_CTX *ctx,
     456                                           NTSTATUS nt_status,
     457                                           const char *mechOID,
     458                                           DATA_BLOB *reply,
     459                                           DATA_BLOB *mechlistMIC)
    569460{
    570461        ASN1_DATA *data;
     
    603494        }
    604495
    605         asn1_pop_tag(data);
    606         asn1_pop_tag(data);
    607 
    608         ret = data_blob(data->data, data->length);
     496        if (mechlistMIC && mechlistMIC->data != NULL) {
     497                asn1_push_tag(data, ASN1_CONTEXT(3));
     498                asn1_write_OctetString(data,
     499                                        mechlistMIC->data,
     500                                        mechlistMIC->length);
     501                asn1_pop_tag(data);
     502        }
     503
     504        asn1_pop_tag(data);
     505        asn1_pop_tag(data);
     506
     507        ret = data_blob_talloc(ctx, data->data, data->length);
    609508        asn1_free(data);
    610509        return ret;
    611510}
    612511
     512DATA_BLOB spnego_gen_auth_response(TALLOC_CTX *ctx, DATA_BLOB *reply,
     513                                   NTSTATUS nt_status, const char *mechOID)
     514{
     515        return spnego_gen_auth_response_and_mic(ctx, nt_status,
     516                                                mechOID, reply, NULL);
     517}
     518
    613519/*
    614520 parse a SPNEGO auth packet. This contains the encrypted passwords
    615521*/
    616 bool spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status,
     522bool spnego_parse_auth_response(TALLOC_CTX *ctx,
     523                                DATA_BLOB blob, NTSTATUS nt_status,
    617524                                const char *mechOID,
    618525                                DATA_BLOB *auth)
     
    650557                if (asn1_tag_remaining(data)) {
    651558                        asn1_start_tag(data,ASN1_CONTEXT(2));
    652                         asn1_read_OctetString(data, talloc_autofree_context(), auth);
     559                        asn1_read_OctetString(data, ctx, auth);
    653560                        asn1_end_tag(data);
    654561                }
     
    664571                DATA_BLOB mechList = data_blob_null;
    665572                asn1_start_tag(data, ASN1_CONTEXT(3));
    666                 asn1_read_OctetString(data, talloc_autofree_context(), &mechList);
     573                asn1_read_OctetString(data, ctx, &mechList);
    667574                asn1_end_tag(data);
    668575                data_blob_free(&mechList);
     
    684591        return True;
    685592}
     593
     594bool spnego_mech_list_blob(TALLOC_CTX *mem_ctx,
     595                           char **oid_list, DATA_BLOB *raw_data)
     596{
     597        ASN1_DATA *data;
     598        unsigned int idx;
     599
     600        if (!oid_list || !oid_list[0] || !raw_data) {
     601                return false;
     602        }
     603
     604        data = asn1_init(talloc_tos());
     605        if (data == NULL) {
     606                return false;
     607        }
     608
     609        asn1_push_tag(data, ASN1_SEQUENCE(0));
     610        for (idx = 0; oid_list[idx]; idx++) {
     611                asn1_write_OID(data, oid_list[idx]);
     612        }
     613        asn1_pop_tag(data);
     614
     615        if (data->has_error) {
     616                DEBUG(3, (__location__ " failed at %d\n", (int)data->ofs));
     617                asn1_free(data);
     618                return false;
     619        }
     620
     621        *raw_data = data_blob_talloc(mem_ctx, data->data, data->length);
     622        if (!raw_data->data) {
     623                DEBUG(3, (__location__": data_blob_talloc() failed!\n"));
     624                asn1_free(data);
     625                return false;
     626        }
     627
     628        asn1_free(data);
     629        return true;
     630}
  • vendor/current/source3/libsmb/clistr.c

    r414 r740  
    2020
    2121#include "includes.h"
     22#include "libsmb/libsmb.h"
    2223
    2324size_t clistr_push_fn(const char *function,
     
    3536                        return push_string_base(function, line,
    3637                                                cli->outbuf,
    37                                                 SVAL(cli->outbuf, smb_flg2),
     38                                                (uint16_t)(cli_ucs2(cli) ? FLAGS2_UNICODE_STRINGS : 0),
    3839                                                dest, src, -1, flags);
    3940                }
    4041                return push_string_base(function, line,
    4142                                        cli->outbuf,
    42                                         SVAL(cli->outbuf, smb_flg2),
     43                                        (uint16_t)(cli_ucs2(cli) ? FLAGS2_UNICODE_STRINGS : 0),
    4344                                        dest, src, cli->bufsize - buf_used,
    4445                                        flags);
     
    4849        return push_string_base(function, line,
    4950                                cli->outbuf,
    50                                 SVAL(cli->outbuf, smb_flg2),
     51                                (uint16_t)(cli_ucs2(cli) ? FLAGS2_UNICODE_STRINGS : 0),
    5152                                dest, src, dest_len, flags);
    5253}
     
    6970                                unsigned int line,
    7071                                TALLOC_CTX *ctx,
    71                                 const char *inbuf,
     72                                const char *base,
     73                                uint16_t flags2,
    7274                                char **pp_dest,
    7375                                const void *src,
     
    7880                                        line,
    7981                                        ctx,
    80                                         inbuf,
    81                                         SVAL(inbuf, smb_flg2),
     82                                        base,
     83                                        flags2,
    8284                                        pp_dest,
    8385                                        src,
     
    9092        return align_string(cli->outbuf, (const char *)p, flags);
    9193}
    92 
    93 size_t clistr_align_in(struct cli_state *cli, const void *p, int flags)
    94 {
    95         return align_string(cli->inbuf, (const char *)p, flags);
    96 }
  • vendor/current/source3/libsmb/clitrans.c

    r414 r740  
    1919
    2020#include "includes.h"
    21 
    22 
    23 /****************************************************************************
    24  Send a SMB trans or trans2 request.
    25 ****************************************************************************/
    26 
    27 bool cli_send_trans(struct cli_state *cli, int trans,
    28                     const char *pipe_name,
    29                     int fid, int flags,
    30                     uint16 *setup, unsigned int lsetup, unsigned int msetup,
    31                     const char *param, unsigned int lparam, unsigned int mparam,
    32                     const char *data, unsigned int ldata, unsigned int mdata)
    33 {
    34         unsigned int i;
    35         unsigned int this_ldata,this_lparam;
    36         unsigned int tot_data=0,tot_param=0;
    37         char *outdata,*outparam;
    38         char *p;
    39         int pipe_name_len=0;
    40         uint16 mid;
    41 
    42         this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
    43         this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
    44 
    45         memset(cli->outbuf,'\0',smb_size);
    46         cli_set_message(cli->outbuf,14+lsetup,0,True);
    47         SCVAL(cli->outbuf,smb_com,trans);
    48         SSVAL(cli->outbuf,smb_tid, cli->cnum);
    49         cli_setup_packet(cli);
    50 
    51         /*
    52          * Save the mid we're using. We need this for finding
    53          * signing replies.
    54          */
    55 
    56         mid = cli->mid;
    57 
    58         if (pipe_name) {
    59                 pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE);
    60         }
    61 
    62         outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len : 3);
    63         outdata = outparam+this_lparam;
    64 
    65         /* primary request */
    66         SSVAL(cli->outbuf,smb_tpscnt,lparam);   /* tpscnt */
    67         SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
    68         SSVAL(cli->outbuf,smb_mprcnt,mparam);   /* mprcnt */
    69         SSVAL(cli->outbuf,smb_mdrcnt,mdata);    /* mdrcnt */
    70         SCVAL(cli->outbuf,smb_msrcnt,msetup);   /* msrcnt */
    71         SSVAL(cli->outbuf,smb_flags,flags);     /* flags */
    72         SIVAL(cli->outbuf,smb_timeout,0);               /* timeout */
    73         SSVAL(cli->outbuf,smb_pscnt,this_lparam);       /* pscnt */
    74         SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
    75         SSVAL(cli->outbuf,smb_dscnt,this_ldata);        /* dscnt */
    76         SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
    77         SCVAL(cli->outbuf,smb_suwcnt,lsetup);   /* suwcnt */
    78         for (i=0;i<lsetup;i++)          /* setup[] */
    79                 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
    80         p = smb_buf(cli->outbuf);
    81         if (trans != SMBtrans) {
    82                 *p++ = 0;  /* put in a null smb_name */
    83                 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
    84         }
    85         if (this_lparam)                        /* param[] */
    86                 memcpy(outparam,param,this_lparam);
    87         if (this_ldata)                 /* data[] */
    88                 memcpy(outdata,data,this_ldata);
    89         cli_setup_bcc(cli, outdata+this_ldata);
    90 
    91         show_msg(cli->outbuf);
    92 
    93         if (!cli_send_smb(cli)) {
    94                 return False;
    95         }
    96 
    97         cli_state_seqnum_persistent(cli, mid);
    98 
    99         if (this_ldata < ldata || this_lparam < lparam) {
    100                 /* receive interim response */
    101                 if (!cli_receive_smb(cli) || cli_is_error(cli)) {
    102                         cli_state_seqnum_remove(cli, mid);
    103                         return(False);
    104                 }
    105 
    106                 tot_data = this_ldata;
    107                 tot_param = this_lparam;
    108 
    109                 while (tot_data < ldata || tot_param < lparam)  {
    110                         this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
    111                         this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
    112 
    113                         cli_set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
    114                         SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2));
    115 
    116                         outparam = smb_buf(cli->outbuf);
    117                         outdata = outparam+this_lparam;
    118 
    119                         /* secondary request */
    120                         SSVAL(cli->outbuf,smb_tpscnt,lparam);   /* tpscnt */
    121                         SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
    122                         SSVAL(cli->outbuf,smb_spscnt,this_lparam);      /* pscnt */
    123                         SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
    124                         SSVAL(cli->outbuf,smb_spsdisp,tot_param);       /* psdisp */
    125                         SSVAL(cli->outbuf,smb_sdscnt,this_ldata);       /* dscnt */
    126                         SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
    127                         SSVAL(cli->outbuf,smb_sdsdisp,tot_data);        /* dsdisp */
    128                         if (trans==SMBtrans2)
    129                                 SSVALS(cli->outbuf,smb_sfid,fid);               /* fid */
    130                         if (this_lparam)                        /* param[] */
    131                                 memcpy(outparam,param+tot_param,this_lparam);
    132                         if (this_ldata)                 /* data[] */
    133                                 memcpy(outdata,data+tot_data,this_ldata);
    134                         cli_setup_bcc(cli, outdata+this_ldata);
    135 
    136                         show_msg(cli->outbuf);
    137 
    138                         cli->mid = mid;
    139                         if (!cli_send_smb(cli)) {
    140                                 cli_state_seqnum_remove(cli, mid);
    141                                 return False;
    142                         }
    143 
    144                         tot_data += this_ldata;
    145                         tot_param += this_lparam;
    146                 }
    147         }
    148 
    149         return(True);
    150 }
    151 
    152 /****************************************************************************
    153  Receive a SMB trans or trans2 response allocating the necessary memory.
    154 ****************************************************************************/
    155 
    156 bool cli_receive_trans(struct cli_state *cli,int trans,
    157                               char **param, unsigned int *param_len,
    158                               char **data, unsigned int *data_len)
    159 {
    160         unsigned int total_data=0;
    161         unsigned int total_param=0;
    162         unsigned int this_data,this_param;
    163         NTSTATUS status;
    164         bool ret = False;
    165         uint16_t mid;
    166 
    167         *data_len = *param_len = 0;
    168 
    169         mid = SVAL(cli->outbuf,smb_mid);
    170 
    171         if (!cli_receive_smb(cli)) {
    172                 cli_state_seqnum_remove(cli, mid);
    173                 return False;
    174         }
    175 
    176         show_msg(cli->inbuf);
    177 
    178         /* sanity check */
    179         if (CVAL(cli->inbuf,smb_com) != trans) {
    180                 DEBUG(0,("Expected %s response, got command 0x%02x\n",
    181                          trans==SMBtrans?"SMBtrans":"SMBtrans2",
    182                          CVAL(cli->inbuf,smb_com)));
    183                 cli_state_seqnum_remove(cli, mid);
    184                 return False;
    185         }
    186 
    187         /*
    188          * An NT RPC pipe call can return ERRDOS, ERRmoredata
    189          * to a trans call. This is not an error and should not
    190          * be treated as such. Note that STATUS_NO_MORE_FILES is
    191          * returned when a trans2 findfirst/next finishes.
    192          * When setting up an encrypted transport we can also
    193          * see NT_STATUS_MORE_PROCESSING_REQUIRED here.
    194          *
    195          * Vista returns NT_STATUS_INACCESSIBLE_SYSTEM_SHORTCUT if the folder
    196          * "<share>/Users/All Users" is enumerated.  This is a special pseudo
    197          * folder, and the response does not have parameters (nor a parameter
    198          * length).
    199          */
    200         status = cli_nt_error(cli);
    201 
    202         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    203                 if (NT_STATUS_IS_ERR(status) ||
    204                     NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES) ||
    205                     NT_STATUS_EQUAL(status,NT_STATUS_INACCESSIBLE_SYSTEM_SHORTCUT)) {
    206                         goto out;
    207                 }
    208         }
    209 
    210         /* parse out the lengths */
    211         total_data = SVAL(cli->inbuf,smb_tdrcnt);
    212         total_param = SVAL(cli->inbuf,smb_tprcnt);
    213 
    214         /* allocate it */
    215         if (total_data!=0) {
    216                 /* We know adding 2 is safe as total_data is an
    217                  * SVAL <= 0xFFFF. */
    218                 *data = (char *)SMB_REALLOC(*data,total_data+2);
    219                 if (!(*data)) {
    220                         DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
    221                         goto out;
    222                 }
    223         }
    224 
    225         if (total_param!=0) {
    226                 /* We know adding 2 is safe as total_param is an
    227                  * SVAL <= 0xFFFF. */
    228                 *param = (char *)SMB_REALLOC(*param,total_param+2);
    229                 if (!(*param)) {
    230                         DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
    231                         goto out;
    232                 }
    233         }
    234 
    235         for (;;)  {
    236                 this_data = SVAL(cli->inbuf,smb_drcnt);
    237                 this_param = SVAL(cli->inbuf,smb_prcnt);
    238 
    239                 if (this_data + *data_len > total_data ||
    240                     this_param + *param_len > total_param) {
    241                         DEBUG(1,("Data overflow in cli_receive_trans\n"));
    242                         goto out;
    243                 }
    244 
    245                 if (this_data + *data_len < this_data ||
    246                                 this_data + *data_len < *data_len ||
    247                                 this_param + *param_len < this_param ||
    248                                 this_param + *param_len < *param_len) {
    249                         DEBUG(1,("Data overflow in cli_receive_trans\n"));
    250                         goto out;
    251                 }
    252 
    253                 if (this_data) {
    254                         unsigned int data_offset_out = SVAL(cli->inbuf,smb_drdisp);
    255                         unsigned int data_offset_in = SVAL(cli->inbuf,smb_droff);
    256 
    257                         if (data_offset_out > total_data ||
    258                                         data_offset_out + this_data > total_data ||
    259                                         data_offset_out + this_data < data_offset_out ||
    260                                         data_offset_out + this_data < this_data) {
    261                                 DEBUG(1,("Data overflow in cli_receive_trans\n"));
    262                                 goto out;
    263                         }
    264                         if (data_offset_in > cli->bufsize ||
    265                                         data_offset_in + this_data >  cli->bufsize ||
    266                                         data_offset_in + this_data < data_offset_in ||
    267                                         data_offset_in + this_data < this_data) {
    268                                 DEBUG(1,("Data overflow in cli_receive_trans\n"));
    269                                 goto out;
    270                         }
    271 
    272                         memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
    273                 }
    274                 if (this_param) {
    275                         unsigned int param_offset_out = SVAL(cli->inbuf,smb_prdisp);
    276                         unsigned int param_offset_in = SVAL(cli->inbuf,smb_proff);
    277 
    278                         if (param_offset_out > total_param ||
    279                                         param_offset_out + this_param > total_param ||
    280                                         param_offset_out + this_param < param_offset_out ||
    281                                         param_offset_out + this_param < this_param) {
    282                                 DEBUG(1,("Param overflow in cli_receive_trans\n"));
    283                                 goto out;
    284                         }
    285                         if (param_offset_in > cli->bufsize ||
    286                                         param_offset_in + this_param >  cli->bufsize ||
    287                                         param_offset_in + this_param < param_offset_in ||
    288                                         param_offset_in + this_param < this_param) {
    289                                 DEBUG(1,("Param overflow in cli_receive_trans\n"));
    290                                 goto out;
    291                         }
    292 
    293                         memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
    294                 }
    295                 *data_len += this_data;
    296                 *param_len += this_param;
    297 
    298                 if (total_data <= *data_len && total_param <= *param_len) {
    299                         ret = True;
    300                         break;
    301                 }
    302 
    303                 if (!cli_receive_smb(cli)) {
    304                         goto out;
    305                 }
    306 
    307                 show_msg(cli->inbuf);
    308 
    309                 /* sanity check */
    310                 if (CVAL(cli->inbuf,smb_com) != trans) {
    311                         DEBUG(0,("Expected %s response, got command 0x%02x\n",
    312                                  trans==SMBtrans?"SMBtrans":"SMBtrans2",
    313                                  CVAL(cli->inbuf,smb_com)));
    314                         goto out;
    315                 }
    316                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    317                         if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
    318                                 goto out;
    319                         }
    320                 }
    321 
    322                 /* parse out the total lengths again - they can shrink! */
    323                 if (SVAL(cli->inbuf,smb_tdrcnt) < total_data)
    324                         total_data = SVAL(cli->inbuf,smb_tdrcnt);
    325                 if (SVAL(cli->inbuf,smb_tprcnt) < total_param)
    326                         total_param = SVAL(cli->inbuf,smb_tprcnt);
    327 
    328                 if (total_data <= *data_len && total_param <= *param_len) {
    329                         ret = True;
    330                         break;
    331                 }
    332         }
    333 
    334   out:
    335 
    336         cli_state_seqnum_remove(cli, mid);
    337 
    338         if (ret) {
    339                 /* Ensure the last 2 bytes of param and data are 2 null
    340                  * bytes. These are malloc'ed, but not included in any
    341                  * length counts. This allows cli_XX string reading functions
    342                  * to safely null terminate. */
    343                 if (total_data) {
    344                         SSVAL(*data,total_data,0);
    345                 }
    346                 if (total_param) {
    347                         SSVAL(*param,total_param,0);
    348                 }
    349         }
    350 
    351         return ret;
    352 }
    353 
    354 /****************************************************************************
    355  Send a SMB nttrans request.
    356 ****************************************************************************/
    357 
    358 bool cli_send_nt_trans(struct cli_state *cli,
    359                        int function,
    360                        int flags,
    361                        uint16 *setup, unsigned int lsetup, unsigned int msetup,
    362                        char *param, unsigned int lparam, unsigned int mparam,
    363                        char *data, unsigned int ldata, unsigned int mdata)
    364 {
    365         unsigned int i;
    366         unsigned int this_ldata,this_lparam;
    367         unsigned int tot_data=0,tot_param=0;
    368         uint16 mid;
    369         char *outdata,*outparam;
    370 
    371         this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
    372         this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
    373 
    374         memset(cli->outbuf,'\0',smb_size);
    375         cli_set_message(cli->outbuf,19+lsetup,0,True);
    376         SCVAL(cli->outbuf,smb_com,SMBnttrans);
    377         SSVAL(cli->outbuf,smb_tid, cli->cnum);
    378         cli_setup_packet(cli);
    379 
    380         /*
    381          * Save the mid we're using. We need this for finding
    382          * signing replies.
    383          */
    384 
    385         mid = cli->mid;
    386 
    387         outparam = smb_buf(cli->outbuf)+3;
    388         outdata = outparam+this_lparam;
    389 
    390         /* primary request */
    391         SCVAL(cli->outbuf,smb_nt_MaxSetupCount,msetup);
    392         SCVAL(cli->outbuf,smb_nt_Flags,flags);
    393         SIVAL(cli->outbuf,smb_nt_TotalParameterCount, lparam);
    394         SIVAL(cli->outbuf,smb_nt_TotalDataCount, ldata);
    395         SIVAL(cli->outbuf,smb_nt_MaxParameterCount, mparam);
    396         SIVAL(cli->outbuf,smb_nt_MaxDataCount, mdata);
    397         SIVAL(cli->outbuf,smb_nt_ParameterCount, this_lparam);
    398         SIVAL(cli->outbuf,smb_nt_ParameterOffset, smb_offset(outparam,cli->outbuf));
    399         SIVAL(cli->outbuf,smb_nt_DataCount, this_ldata);
    400         SIVAL(cli->outbuf,smb_nt_DataOffset, smb_offset(outdata,cli->outbuf));
    401         SIVAL(cli->outbuf,smb_nt_SetupCount, lsetup);
    402         SIVAL(cli->outbuf,smb_nt_Function, function);
    403         for (i=0;i<lsetup;i++)          /* setup[] */
    404                 SSVAL(cli->outbuf,smb_nt_SetupStart+i*2,setup[i]);
    405 
    406         if (this_lparam)                        /* param[] */
    407                 memcpy(outparam,param,this_lparam);
    408         if (this_ldata)                 /* data[] */
    409                 memcpy(outdata,data,this_ldata);
    410 
    411         cli_setup_bcc(cli, outdata+this_ldata);
    412 
    413         show_msg(cli->outbuf);
    414         if (!cli_send_smb(cli)) {
    415                 return False;
    416         }
    417 
    418         cli_state_seqnum_persistent(cli, mid);
    419 
    420         if (this_ldata < ldata || this_lparam < lparam) {
    421                 /* receive interim response */
    422                 if (!cli_receive_smb(cli) || cli_is_error(cli)) {
    423                         cli_state_seqnum_remove(cli, mid);
    424                         return(False);
    425                 }
    426 
    427                 tot_data = this_ldata;
    428                 tot_param = this_lparam;
    429 
    430                 while (tot_data < ldata || tot_param < lparam)  {
    431                         this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
    432                         this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
    433 
    434                         cli_set_message(cli->outbuf,18,0,True);
    435                         SCVAL(cli->outbuf,smb_com,SMBnttranss);
    436 
    437                         /* XXX - these should probably be aligned */
    438                         outparam = smb_buf(cli->outbuf);
    439                         outdata = outparam+this_lparam;
    440 
    441                         /* secondary request */
    442                         SIVAL(cli->outbuf,smb_nts_TotalParameterCount,lparam);
    443                         SIVAL(cli->outbuf,smb_nts_TotalDataCount,ldata);
    444                         SIVAL(cli->outbuf,smb_nts_ParameterCount,this_lparam);
    445                         SIVAL(cli->outbuf,smb_nts_ParameterOffset,smb_offset(outparam,cli->outbuf));
    446                         SIVAL(cli->outbuf,smb_nts_ParameterDisplacement,tot_param);
    447                         SIVAL(cli->outbuf,smb_nts_DataCount,this_ldata);
    448                         SIVAL(cli->outbuf,smb_nts_DataOffset,smb_offset(outdata,cli->outbuf));
    449                         SIVAL(cli->outbuf,smb_nts_DataDisplacement,tot_data);
    450                         if (this_lparam)                        /* param[] */
    451                                 memcpy(outparam,param+tot_param,this_lparam);
    452                         if (this_ldata)                 /* data[] */
    453                                 memcpy(outdata,data+tot_data,this_ldata);
    454                         cli_setup_bcc(cli, outdata+this_ldata);
    455 
    456                         show_msg(cli->outbuf);
    457 
    458                         cli->mid = mid;
    459                         if (!cli_send_smb(cli)) {
    460                                 cli_state_seqnum_remove(cli, mid);
    461                                 return False;
    462                         }
    463 
    464                         tot_data += this_ldata;
    465                         tot_param += this_lparam;
    466                 }
    467         }
    468 
    469         return(True);
    470 }
    471 
    472 /****************************************************************************
    473  Receive a SMB nttrans response allocating the necessary memory.
    474 ****************************************************************************/
    475 
    476 bool cli_receive_nt_trans(struct cli_state *cli,
    477                           char **param, unsigned int *param_len,
    478                           char **data, unsigned int *data_len)
    479 {
    480         unsigned int total_data=0;
    481         unsigned int total_param=0;
    482         unsigned int this_data,this_param;
    483         uint8 eclass;
    484         uint32 ecode;
    485         bool ret = False;
    486         uint16_t mid;
    487 
    488         *data_len = *param_len = 0;
    489 
    490         mid = SVAL(cli->outbuf,smb_mid);
    491 
    492         if (!cli_receive_smb(cli)) {
    493                 cli_state_seqnum_remove(cli, mid);
    494                 return False;
    495         }
    496 
    497         show_msg(cli->inbuf);
    498 
    499         /* sanity check */
    500         if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
    501                 DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
    502                          CVAL(cli->inbuf,smb_com)));
    503                 cli_state_seqnum_remove(cli, mid);
    504                 return(False);
    505         }
    506 
    507         /*
    508          * An NT RPC pipe call can return ERRDOS, ERRmoredata
    509          * to a trans call. This is not an error and should not
    510          * be treated as such.
    511          */
    512         if (cli_is_dos_error(cli)) {
    513                 cli_dos_error(cli, &eclass, &ecode);
    514                 if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
    515                         goto out;
    516                 }
    517         }
    518 
    519         /*
    520          * Likewise for NT_STATUS_BUFFER_TOO_SMALL
    521          */
    522         if (cli_is_nt_error(cli)) {
    523                 if (!NT_STATUS_EQUAL(cli_nt_error(cli),
    524                                      NT_STATUS_BUFFER_TOO_SMALL)) {
    525                         goto out;
    526                 }
    527         }
    528 
    529         /* parse out the lengths */
    530         total_data = IVAL(cli->inbuf,smb_ntr_TotalDataCount);
    531         total_param = IVAL(cli->inbuf,smb_ntr_TotalParameterCount);
    532         /* Only allow 16 megs. */
    533         if (total_param > 16*1024*1024) {
    534                 DEBUG(0,("cli_receive_nt_trans: param buffer too large %d\n",
    535                                         total_param));
    536                 goto out;
    537         }
    538         if (total_data > 16*1024*1024) {
    539                 DEBUG(0,("cli_receive_nt_trans: data buffer too large %d\n",
    540                                         total_data));
    541                 goto out;
    542         }
    543 
    544         /* allocate it */
    545         if (total_data) {
    546                 /* We know adding 2 is safe as total_data is less
    547                  * than 16mb (above). */
    548                 *data = (char *)SMB_REALLOC(*data,total_data+2);
    549                 if (!(*data)) {
    550                         DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
    551                         goto out;
    552                 }
    553         }
    554 
    555         if (total_param) {
    556                 /* We know adding 2 is safe as total_param is less
    557                  * than 16mb (above). */
    558                 *param = (char *)SMB_REALLOC(*param,total_param+2);
    559                 if (!(*param)) {
    560                         DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
    561                         goto out;
    562                 }
    563         }
    564 
    565         while (1)  {
    566                 this_data = SVAL(cli->inbuf,smb_ntr_DataCount);
    567                 this_param = SVAL(cli->inbuf,smb_ntr_ParameterCount);
    568 
    569                 if (this_data + *data_len > total_data ||
    570                     this_param + *param_len > total_param) {
    571                         DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
    572                         goto out;
    573                 }
    574 
    575                 if (this_data + *data_len < this_data ||
    576                                 this_data + *data_len < *data_len ||
    577                                 this_param + *param_len < this_param ||
    578                                 this_param + *param_len < *param_len) {
    579                         DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
    580                         goto out;
    581                 }
    582 
    583                 if (this_data) {
    584                         unsigned int data_offset_out = SVAL(cli->inbuf,smb_ntr_DataDisplacement);
    585                         unsigned int data_offset_in = SVAL(cli->inbuf,smb_ntr_DataOffset);
    586 
    587                         if (data_offset_out > total_data ||
    588                                         data_offset_out + this_data > total_data ||
    589                                         data_offset_out + this_data < data_offset_out ||
    590                                         data_offset_out + this_data < this_data) {
    591                                 DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
    592                                 goto out;
    593                         }
    594                         if (data_offset_in > cli->bufsize ||
    595                                         data_offset_in + this_data >  cli->bufsize ||
    596                                         data_offset_in + this_data < data_offset_in ||
    597                                         data_offset_in + this_data < this_data) {
    598                                 DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
    599                                 goto out;
    600                         }
    601 
    602                         memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
    603                 }
    604 
    605                 if (this_param) {
    606                         unsigned int param_offset_out = SVAL(cli->inbuf,smb_ntr_ParameterDisplacement);
    607                         unsigned int param_offset_in = SVAL(cli->inbuf,smb_ntr_ParameterOffset);
    608 
    609                         if (param_offset_out > total_param ||
    610                                         param_offset_out + this_param > total_param ||
    611                                         param_offset_out + this_param < param_offset_out ||
    612                                         param_offset_out + this_param < this_param) {
    613                                 DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
    614                                 goto out;
    615                         }
    616                         if (param_offset_in > cli->bufsize ||
    617                                         param_offset_in + this_param >  cli->bufsize ||
    618                                         param_offset_in + this_param < param_offset_in ||
    619                                         param_offset_in + this_param < this_param) {
    620                                 DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
    621                                 goto out;
    622                         }
    623 
    624                         memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
    625                 }
    626 
    627                 *data_len += this_data;
    628                 *param_len += this_param;
    629 
    630                 if (total_data <= *data_len && total_param <= *param_len) {
    631                         ret = True;
    632                         break;
    633                 }
    634 
    635                 if (!cli_receive_smb(cli)) {
    636                         goto out;
    637                 }
    638 
    639                 show_msg(cli->inbuf);
    640 
    641                 /* sanity check */
    642                 if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
    643                         DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
    644                                  CVAL(cli->inbuf,smb_com)));
    645                         goto out;
    646                 }
    647                 if (cli_is_dos_error(cli)) {
    648                         cli_dos_error(cli, &eclass, &ecode);
    649                         if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
    650                                 goto out;
    651                         }
    652                 }
    653                 /*
    654                  * Likewise for NT_STATUS_BUFFER_TOO_SMALL
    655                  */
    656                 if (cli_is_nt_error(cli)) {
    657                         if (!NT_STATUS_EQUAL(cli_nt_error(cli),
    658                                              NT_STATUS_BUFFER_TOO_SMALL)) {
    659                                 goto out;
    660                         }
    661                 }
    662 
    663                 /* parse out the total lengths again - they can shrink! */
    664                 if (IVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data)
    665                         total_data = IVAL(cli->inbuf,smb_ntr_TotalDataCount);
    666                 if (IVAL(cli->inbuf,smb_ntr_TotalParameterCount) < total_param)
    667                         total_param = IVAL(cli->inbuf,smb_ntr_TotalParameterCount);
    668 
    669                 if (total_data <= *data_len && total_param <= *param_len) {
    670                         ret = True;
    671                         break;
    672                 }
    673         }
    674 
    675   out:
    676 
    677         cli_state_seqnum_remove(cli, mid);
    678 
    679         if (ret) {
    680                 /* Ensure the last 2 bytes of param and data are 2 null
    681                  * bytes. These are malloc'ed, but not included in any
    682                  * length counts. This allows cli_XX string reading functions
    683                  * to safely null terminate. */
    684                 if (total_data) {
    685                         SSVAL(*data,total_data,0);
    686                 }
    687                 if (total_param) {
    688                         SSVAL(*param,total_param,0);
    689                 }
    690         }
    691 
    692         return ret;
    693 }
     21#include "libsmb/libsmb.h"
     22#include "../lib/util/tevent_ntstatus.h"
     23#include "async_smb.h"
    69424
    69525struct trans_recvblob {
     
    70333        uint8_t cmd;
    70434        uint16_t mid;
    705         uint32_t seqnum;
    70635        const char *pipe_name;
    70736        uint8_t *pipe_name_conv;
     
    72150        struct trans_recvblob rparam;
    72251        struct trans_recvblob rdata;
    723 
    724         TALLOC_CTX *secondary_request_ctx;
    725 
    726         struct iovec iov[4];
     52        uint16_t recv_flags2;
     53
     54        struct iovec iov[6];
    72755        uint8_t pad[4];
     56        uint8_t zero_pad[4];
    72857        uint16_t vwv[32];
     58
     59        struct tevent_req *primary_subreq;
    72960};
     61
     62static void cli_trans_cleanup_primary(struct cli_trans_state *state)
     63{
     64        if (state->primary_subreq) {
     65                cli_smb_req_set_mid(state->primary_subreq, 0);
     66                cli_smb_req_unset_pending(state->primary_subreq);
     67                TALLOC_FREE(state->primary_subreq);
     68        }
     69}
     70
     71static int cli_trans_state_destructor(struct cli_trans_state *state)
     72{
     73        cli_trans_cleanup_primary(state);
     74        return 0;
     75}
    73076
    73177static NTSTATUS cli_pull_trans(uint8_t *inbuf,
     
    843189        uint8_t *pad = state->pad;
    844190        uint16_t *vwv = state->vwv;
    845         uint16_t param_offset;
    846         uint16_t this_param = 0;
    847         uint16_t this_data = 0;
     191        uint32_t param_offset;
     192        uint32_t this_param = 0;
     193        uint32_t param_pad;
     194        uint32_t data_offset;
     195        uint32_t this_data = 0;
     196        uint32_t data_pad;
    848197        uint32_t useable_space;
    849198        uint8_t cmd;
     
    893242        }
    894243
    895         useable_space = state->cli->max_xmit - smb_size - sizeof(uint16_t)*wct;
     244        param_offset += wct * sizeof(uint16_t);
     245        useable_space = state->cli->max_xmit - param_offset;
     246
     247        param_pad = param_offset % 4;
     248        if (param_pad > 0) {
     249                param_pad = MIN(param_pad, useable_space);
     250                iov[0].iov_base = (void *)state->zero_pad;
     251                iov[0].iov_len = param_pad;
     252                iov += 1;
     253                param_offset += param_pad;
     254        }
     255        useable_space = state->cli->max_xmit - param_offset;
    896256
    897257        if (state->param_sent < state->num_param) {
     
    903263        }
    904264
     265        data_offset = param_offset + this_param;
     266        useable_space = state->cli->max_xmit - data_offset;
     267
     268        data_pad = data_offset % 4;
     269        if (data_pad > 0) {
     270                data_pad = MIN(data_pad, useable_space);
     271                iov[0].iov_base = (void *)state->zero_pad;
     272                iov[0].iov_len = data_pad;
     273                iov += 1;
     274                data_offset += data_pad;
     275        }
     276        useable_space = state->cli->max_xmit - data_offset;
     277
    905278        if (state->data_sent < state->num_data) {
    906279                this_data = MIN(state->num_data - state->data_sent,
    907                                 useable_space - this_param);
     280                                useable_space);
    908281                iov[0].iov_base = (void *)(state->data + state->data_sent);
    909282                iov[0].iov_len = this_data;
     
    911284        }
    912285
    913         param_offset += wct * sizeof(uint16_t);
    914 
    915286        DEBUG(10, ("num_setup=%u, max_setup=%u, "
    916287                   "param_total=%u, this_param=%u, max_param=%u, "
    917288                   "data_total=%u, this_data=%u, max_data=%u, "
    918                    "param_offset=%u, param_disp=%u, data_disp=%u\n",
     289                   "param_offset=%u, param_pad=%u, param_disp=%u, "
     290                   "data_offset=%u, data_pad=%u, data_disp=%u\n",
    919291                   (unsigned)state->num_setup, (unsigned)state->max_setup,
    920292                   (unsigned)state->num_param, (unsigned)this_param,
     
    922294                   (unsigned)state->num_data, (unsigned)this_data,
    923295                   (unsigned)state->rdata.max,
    924                    (unsigned)param_offset,
    925                    (unsigned)state->param_sent, (unsigned)state->data_sent));
     296                   (unsigned)param_offset, (unsigned)param_pad,
     297                   (unsigned)state->param_sent,
     298                   (unsigned)data_offset, (unsigned)data_pad,
     299                   (unsigned)state->data_sent));
    926300
    927301        switch (cmd) {
     
    940314                SSVAL(vwv +10, 0, param_offset);
    941315                SSVAL(vwv +11, 0, this_data);
    942                 SSVAL(vwv +12, 0, param_offset + this_param);
     316                SSVAL(vwv +12, 0, data_offset);
    943317                SCVAL(vwv +13, 0, state->num_setup);
    944318                SCVAL(vwv +13, 1, 0);   /* reserved */
     
    954328                SSVAL(vwv + 4, 0, state->param_sent);
    955329                SSVAL(vwv + 5, 0, this_data);
    956                 SSVAL(vwv + 6, 0, param_offset + this_param);
     330                SSVAL(vwv + 6, 0, data_offset);
    957331                SSVAL(vwv + 7, 0, state->data_sent);
    958332                if (cmd == SMBtranss2) {
     
    961335                break;
    962336        case SMBnttrans:
    963                 SCVAL(vwv, 0, state->max_setup);
    964                 SSVAL(vwv, 1, 0); /* reserved */
    965                 SIVAL(vwv,  3, state->num_param);
    966                 SIVAL(vwv,  7, state->num_data);
    967                 SIVAL(vwv, 11, state->rparam.max);
    968                 SIVAL(vwv, 15, state->rdata.max);
    969                 SIVAL(vwv, 19, this_param);
    970                 SIVAL(vwv, 23, param_offset);
    971                 SIVAL(vwv, 27, this_data);
    972                 SIVAL(vwv, 31, param_offset + this_param);
    973                 SCVAL(vwv, 35, state->num_setup);
    974                 SSVAL(vwv, 36, state->function);
     337                SCVAL(vwv + 0, 0, state->max_setup);
     338                SSVAL(vwv + 0, 1, 0); /* reserved */
     339                SIVAL(vwv + 1, 1, state->num_param);
     340                SIVAL(vwv + 3, 1, state->num_data);
     341                SIVAL(vwv + 5, 1, state->rparam.max);
     342                SIVAL(vwv + 7, 1, state->rdata.max);
     343                SIVAL(vwv + 9, 1, this_param);
     344                SIVAL(vwv +11, 1, param_offset);
     345                SIVAL(vwv +13, 1, this_data);
     346                SIVAL(vwv +15, 1, data_offset);
     347                SCVAL(vwv +17, 1, state->num_setup);
     348                SSVAL(vwv +18, 0, state->function);
    975349                memcpy(vwv + 19, state->setup,
    976350                       sizeof(uint16_t) * state->num_setup);
    977351                break;
    978352        case SMBnttranss:
    979                 SSVAL(vwv, 0, 0); /* reserved */
    980                 SCVAL(vwv,  2, 0); /* reserved */
    981                 SIVAL(vwv,  3, state->num_param);
    982                 SIVAL(vwv,  7, state->num_data);
    983                 SIVAL(vwv, 11, this_param);
    984                 SIVAL(vwv, 15, param_offset);
    985                 SIVAL(vwv, 19, state->param_sent);
    986                 SIVAL(vwv, 23, this_data);
    987                 SIVAL(vwv, 27, param_offset + this_param);
    988                 SIVAL(vwv, 31, state->data_sent);
    989                 SCVAL(vwv, 35, 0); /* reserved */
     353                SSVAL(vwv + 0, 0, 0); /* reserved */
     354                SCVAL(vwv + 1, 0, 0); /* reserved */
     355                SIVAL(vwv + 1, 1, state->num_param);
     356                SIVAL(vwv + 3, 1, state->num_data);
     357                SIVAL(vwv + 5, 1, this_param);
     358                SIVAL(vwv + 7, 1, param_offset);
     359                SIVAL(vwv + 9, 1, state->param_sent);
     360                SIVAL(vwv +11, 1, this_data);
     361                SIVAL(vwv +13, 1, data_offset);
     362                SIVAL(vwv +15, 1, state->data_sent);
     363                SCVAL(vwv +17, 1, 0); /* reserved */
    990364                break;
    991365        }
     
    1084458                return tevent_req_post(req, ev);
    1085459        }
    1086         state->mid = cli_smb_req_mid(subreq);
    1087460        status = cli_smb_req_send(subreq);
    1088461        if (!NT_STATUS_IS_OK(status)) {
     
    1090463                return tevent_req_post(req, state->ev);
    1091464        }
    1092         cli_state_seqnum_persistent(cli, state->mid);
    1093465        tevent_req_set_callback(subreq, cli_trans_done, req);
     466
     467        /*
     468         * Now get the MID of the primary request
     469         * and mark it as persistent. This means
     470         * we will able to send and receive multiple
     471         * SMB pdus using this MID in both directions
     472         * (including correct SMB signing).
     473         */
     474        state->mid = cli_smb_req_mid(subreq);
     475        cli_smb_req_set_mid(subreq, state->mid);
     476        state->primary_subreq = subreq;
     477        talloc_set_destructor(state, cli_trans_state_destructor);
     478
    1094479        return req;
    1095480}
     481
     482static void cli_trans_done2(struct tevent_req *subreq);
    1096483
    1097484static void cli_trans_done(struct tevent_req *subreq)
     
    1107494        uint32_t num_bytes;
    1108495        uint8_t *bytes;
     496        uint8_t *inbuf;
    1109497        uint8_t num_setup       = 0;
    1110498        uint16_t *setup         = NULL;
     
    1118506        uint8_t *data           = NULL;
    1119507
    1120         status = cli_smb_recv(subreq, 0, &wct, &vwv, &num_bytes, &bytes);
     508        status = cli_smb_recv(subreq, state, &inbuf, 0, &wct, &vwv,
     509                              &num_bytes, &bytes);
     510        /*
     511         * Do not TALLOC_FREE(subreq) here, we might receive more than
     512         * one response for the same mid.
     513         */
    1121514
    1122515        /*
     
    1133526
    1134527        status = cli_pull_trans(
    1135                 cli_smb_inbuf(subreq), wct, vwv, num_bytes, bytes,
     528                inbuf, wct, vwv, num_bytes, bytes,
    1136529                state->cmd, !sent_all, &num_setup, &setup,
    1137530                &total_param, &num_param, &param_disp, &param,
     
    1144537        if (!sent_all) {
    1145538                int iov_count;
    1146 
    1147                 TALLOC_FREE(subreq);
     539                struct tevent_req *subreq2;
    1148540
    1149541                cli_trans_format(state, &wct, &iov_count);
    1150542
    1151                 subreq = cli_smb_req_create(state, state->ev, state->cli,
    1152                                             state->cmd + 1, 0, wct, state->vwv,
    1153                                             iov_count, state->iov);
    1154                 if (tevent_req_nomem(subreq, req)) {
     543                subreq2 = cli_smb_req_create(state, state->ev, state->cli,
     544                                             state->cmd + 1, 0, wct, state->vwv,
     545                                             iov_count, state->iov);
     546                if (tevent_req_nomem(subreq2, req)) {
    1155547                        return;
    1156548                }
    1157                 cli_smb_req_set_mid(subreq, state->mid);
    1158 
    1159                 status = cli_smb_req_send(subreq);
     549                cli_smb_req_set_mid(subreq2, state->mid);
     550
     551                status = cli_smb_req_send(subreq2);
    1160552
    1161553                if (!NT_STATUS_IS_OK(status)) {
    1162554                        goto fail;
    1163555                }
    1164                 tevent_req_set_callback(subreq, cli_trans_done, req);
     556                tevent_req_set_callback(subreq2, cli_trans_done2, req);
     557
    1165558                return;
    1166559        }
     
    1186579        if ((state->rparam.total == state->rparam.received)
    1187580            && (state->rdata.total == state->rdata.received)) {
    1188                 TALLOC_FREE(subreq);
    1189                 cli_state_seqnum_remove(state->cli, state->mid);
     581                state->recv_flags2 = SVAL(inbuf, smb_flg2);
     582                cli_trans_cleanup_primary(state);
    1190583                tevent_req_done(req);
    1191584                return;
    1192585        }
    1193586
    1194         if (!cli_smb_req_set_pending(subreq)) {
    1195                 status = NT_STATUS_NO_MEMORY;
    1196                 goto fail;
    1197         }
     587        TALLOC_FREE(inbuf);
     588
    1198589        return;
    1199590
    1200591 fail:
    1201         cli_state_seqnum_remove(state->cli, state->mid);
    1202         TALLOC_FREE(subreq);
     592        cli_trans_cleanup_primary(state);
    1203593        tevent_req_nterror(req, status);
    1204594}
    1205595
    1206 NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
    1207                         uint16_t **setup, uint8_t *num_setup,
    1208                         uint8_t **param, uint32_t *num_param,
    1209                         uint8_t **data, uint32_t *num_data)
    1210 {
     596static void cli_trans_done2(struct tevent_req *subreq2)
     597{
     598        struct tevent_req *req = tevent_req_callback_data(
     599                subreq2, struct tevent_req);
    1211600        struct cli_trans_state *state = tevent_req_data(
    1212601                req, struct cli_trans_state);
    1213602        NTSTATUS status;
     603        bool sent_all;
     604        uint8_t wct;
     605        uint32_t seqnum;
     606
     607        /*
     608         * First backup the seqnum of the secondary request
     609         * and attach it to the primary request.
     610         */
     611        seqnum = cli_smb_req_seqnum(subreq2);
     612        cli_smb_req_set_seqnum(state->primary_subreq, seqnum);
     613
     614        status = cli_smb_recv(subreq2, state, NULL, 0, &wct, NULL,
     615                              NULL, NULL);
     616        TALLOC_FREE(subreq2);
     617
     618        if (!NT_STATUS_IS_OK(status)) {
     619                goto fail;
     620        }
     621
     622        if (wct != 0) {
     623                status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     624                goto fail;
     625        }
     626
     627        sent_all = ((state->param_sent == state->num_param)
     628                    && (state->data_sent == state->num_data));
     629
     630        if (!sent_all) {
     631                int iov_count;
     632
     633                cli_trans_format(state, &wct, &iov_count);
     634
     635                subreq2 = cli_smb_req_create(state, state->ev, state->cli,
     636                                             state->cmd + 1, 0, wct, state->vwv,
     637                                             iov_count, state->iov);
     638                if (tevent_req_nomem(subreq2, req)) {
     639                        return;
     640                }
     641                cli_smb_req_set_mid(subreq2, state->mid);
     642
     643                status = cli_smb_req_send(subreq2);
     644
     645                if (!NT_STATUS_IS_OK(status)) {
     646                        goto fail;
     647                }
     648                tevent_req_set_callback(subreq2, cli_trans_done2, req);
     649                return;
     650        }
     651
     652        return;
     653
     654 fail:
     655        cli_trans_cleanup_primary(state);
     656        tevent_req_nterror(req, status);
     657}
     658
     659NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     660                        uint16_t *recv_flags2,
     661                        uint16_t **setup, uint8_t min_setup,
     662                        uint8_t *num_setup,
     663                        uint8_t **param, uint32_t min_param,
     664                        uint32_t *num_param,
     665                        uint8_t **data, uint32_t min_data,
     666                        uint32_t *num_data)
     667{
     668        struct cli_trans_state *state = tevent_req_data(
     669                req, struct cli_trans_state);
     670        NTSTATUS status;
     671
     672        cli_trans_cleanup_primary(state);
    1214673
    1215674        if (tevent_req_is_nterror(req, &status)) {
    1216675                return status;
     676        }
     677
     678        if ((state->num_rsetup < min_setup)
     679            || (state->rparam.total < min_param)
     680            || (state->rdata.total < min_data)) {
     681                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     682        }
     683
     684        if (recv_flags2 != NULL) {
     685                *recv_flags2 = state->recv_flags2;
    1217686        }
    1218687
     
    1248717                   uint8_t *param, uint32_t num_param, uint32_t max_param,
    1249718                   uint8_t *data, uint32_t num_data, uint32_t max_data,
    1250                    uint16_t **rsetup, uint8_t *num_rsetup,
    1251                    uint8_t **rparam, uint32_t *num_rparam,
    1252                    uint8_t **rdata, uint32_t *num_rdata)
     719                   uint16_t *recv_flags2,
     720                   uint16_t **rsetup, uint8_t min_rsetup, uint8_t *num_rsetup,
     721                   uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam,
     722                   uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata)
    1253723{
    1254724        TALLOC_CTX *frame = talloc_stackframe();
     
    1286756        }
    1287757
    1288         status = cli_trans_recv(req, mem_ctx, rsetup, num_rsetup,
    1289                                 rparam, num_rparam, rdata, num_rdata);
     758        status = cli_trans_recv(req, mem_ctx, recv_flags2,
     759                                rsetup, min_rsetup, num_rsetup,
     760                                rparam, min_rparam, num_rparam,
     761                                rdata, min_rdata, num_rdata);
    1290762 fail:
    1291763        TALLOC_FREE(frame);
  • vendor/current/source3/libsmb/conncache.c

    r414 r740  
    9898static NTSTATUS negative_conn_cache_valuedecode(const char *value)
    9999{
    100         unsigned int v = NT_STATUS_V(NT_STATUS_INTERNAL_ERROR);;
     100        unsigned int v = NT_STATUS_V(NT_STATUS_INTERNAL_ERROR);
    101101
    102102        if (value != NULL) {
  • vendor/current/source3/libsmb/dsgetdcname.c

    r414 r740  
    2222
    2323#include "includes.h"
    24 
    25 #define DSGETDCNAME_FMT "DSGETDCNAME/DOMAIN/%s"
     24#include "libads/sitename_cache.h"
     25#include "../librpc/gen_ndr/ndr_netlogon.h"
     26#include "libads/cldap.h"
     27#include "libads/dns.h"
     28#include "libsmb/clidgram.h"
     29
    2630/* 15 minutes */
    2731#define DSGETDCNAME_CACHE_TTL   60*15
     
    123127        }
    124128
    125         return talloc_asprintf_strupper_m(mem_ctx, DSGETDCNAME_FMT, domain);
     129        return talloc_asprintf_strupper_m(mem_ctx, "DSGETDCNAME/DOMAIN/%s",
     130                                          domain);
    126131}
    127132
     
    190195        r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
    191196
    192         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r,
     197        ndr_err = ndr_push_struct_blob(&blob, mem_ctx, r,
    193198                       (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX);
    194199        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    196201        }
    197202
    198         if (r->domain) {
    199                 status = dsgetdcname_cache_store(mem_ctx, r->domain, &blob);
     203        if (r->domain_name) {
     204                status = dsgetdcname_cache_store(mem_ctx, r->domain_name, &blob);
    200205                if (!NT_STATUS_IS_OK(status)) {
    201206                        goto done;
    202207                }
    203208                if (r->client_site) {
    204                         sitename_store(r->domain, r->client_site);
     209                        sitename_store(r->domain_name, r->client_site);
    205210                }
    206211        }
     
    341346        }
    342347
    343         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r,
     348        ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
    344349                      (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX);
    345350
     
    497502        dclist = TALLOC_ZERO_ARRAY(mem_ctx, struct ip_service_name, count);
    498503        if (!dclist) {
     504                SAFE_FREE(iplist);
    499505                return NT_STATUS_NO_MEMORY;
    500506        }
     
    512518                r->hostname = talloc_strdup(mem_ctx, addr);
    513519                if (!r->hostname) {
     520                        SAFE_FREE(iplist);
    514521                        return NT_STATUS_NO_MEMORY;
    515522                }
     
    519526        *returned_dclist = dclist;
    520527        *returned_count = count;
     528        SAFE_FREE(iplist);
    521529
    522530        return NT_STATUS_OK;
     
    622630                 * anything about the DC's   -- jerry */
    623631
    624                 if (!is_zero_addr((struct sockaddr *)(void *)&r->ss)) {
     632                if (!is_zero_addr(&r->ss)) {
    625633                        count++;
    626634                        continue;
     
    687695                info->forest_name = talloc_strdup(mem_ctx, forest_name);
    688696                NT_STATUS_HAVE_NO_MEMORY(info->forest_name);
    689                 flags |= DS_DNS_FOREST;
     697                flags |= DS_DNS_FOREST_ROOT;
    690698        }
    691699
     
    783791        map_dc_and_domain_names(flags,
    784792                                r->pdc_name,
    785                                 r->domain,
     793                                r->domain_name,
    786794                                r->pdc_dns_name,
    787795                                r->dns_domain,
     
    892900/****************************************************************
    893901****************************************************************/
    894 
    895 static struct event_context *ev_context(void)
    896 {
    897         static struct event_context *ctx;
    898 
    899         if (!ctx && !(ctx = event_context_init(NULL))) {
    900                 smb_panic("Could not init event context");
    901         }
    902         return ctx;
    903 }
    904 
    905 /****************************************************************
    906 ****************************************************************/
    907 
    908 static struct messaging_context *msg_context(TALLOC_CTX *mem_ctx)
    909 {
    910         static struct messaging_context *ctx;
    911 
    912         if (!ctx && !(ctx = messaging_init(mem_ctx, server_id_self(),
    913                                            ev_context()))) {
    914                 smb_panic("Could not init messaging context");
    915         }
    916         return ctx;
    917 }
    918902
    919903/****************************************************************
     
    941925                              NETLOGON_NT_VERSION_5EX_WITH_IP;
    942926
    943         if (!msg_ctx) {
    944                 msg_ctx = msg_context(mem_ctx);
     927        if (msg_ctx == NULL) {
     928                return NT_STATUS_INVALID_PARAMETER;
    945929        }
    946930
     
    954938
    955939        for (i=0; i<num_dcs; i++) {
     940                uint16_t val;
     941                int dgm_id;
     942
     943                generate_random_buffer((uint8_t *)&val, 2);
     944                dgm_id = val;
    956945
    957946                ip_list.ss = dclist[i].ss;
     
    962951                }
    963952
    964                 if (send_getdc_request(mem_ctx, msg_ctx,
    965                                        &dclist[i].ss, domain_name,
    966                                        NULL, nt_version))
    967                 {
    968                         int k;
    969                         smb_msleep(300);
    970                         for (k=0; k<5; k++) {
    971                                 if (receive_getdc_response(mem_ctx,
    972                                                            &dclist[i].ss,
    973                                                            domain_name,
    974                                                            &nt_version,
    975                                                            &dc_name,
    976                                                            &r)) {
    977                                         store_cache = true;
    978                                         namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
    979                                         goto make_reply;
    980                                 }
    981                                 smb_msleep(1500);
    982                         }
     953                status = nbt_getdc(msg_ctx, &dclist[i].ss, domain_name,
     954                                   NULL, nt_version,
     955                                   mem_ctx, &nt_version, &dc_name, &r);
     956                if (NT_STATUS_IS_OK(status)) {
     957                        store_cache = true;
     958                        namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
     959                        goto make_reply;
    983960                }
    984961
     
    999976
    1000977                        logon1.nt_version = nt_version;
    1001                         logon1.server = tmp_dc_name;
    1002                         logon1.domain = talloc_strdup_upper(mem_ctx, domain_name);
    1003                         NT_STATUS_HAVE_NO_MEMORY(logon1.domain);
     978                        logon1.pdc_name = tmp_dc_name;
     979                        logon1.domain_name = talloc_strdup_upper(mem_ctx, domain_name);
     980                        NT_STATUS_HAVE_NO_MEMORY(logon1.domain_name);
    1004981
    1005982                        r->data.nt4 = logon1;
  • vendor/current/source3/libsmb/errormap.c

    r414 r740  
    2121
    2222#include "includes.h"
    23 #include "nsswitch/libwbclient/wbclient.h"
     23
     24#if HAVE_GSSAPI_GSSAPI_H
     25#include <gssapi/gssapi.h>
     26#elif HAVE_GSSAPI_GSSAPI_GENERIC_H
     27#include <gssapi/gssapi_generic.h>
     28#elif HAVE_GSSAPI_H
     29#include <gssapi.h>
     30#endif
    2431
    2532/* This map was extracted by the ERRMAPEXTRACT smbtorture command.
     
    183190*/
    184191        {ERRSRV,        ERRbadpw,       NT_STATUS_WRONG_PASSWORD},
     192        {ERRSRV,        ERRbaduid,      NT_STATUS_USER_SESSION_DELETED},
    185193        {ERRHRD,        ERRgeneral,     NT_STATUS_ILL_FORMED_PASSWORD},
    186194        {ERRHRD,        ERRgeneral,     NT_STATUS_PASSWORD_RESTRICTION},
     
    737745        {ERRDOS,        1022,   NT_STATUS(0x0000010c)},
    738746        {ERRSRV,        ERRbadpw,       NT_STATUS_WRONG_PASSWORD},
     747        {ERRSRV,        ERRbaduid,      NT_STATUS_USER_SESSION_DELETED},
    739748        {ERRSRV,        ERRbadtype,     NT_STATUS_BAD_DEVICE_TYPE},
    740749        {ERRSRV,        ERRaccess,      NT_STATUS_NETWORK_ACCESS_DENIED},
     
    14261435{
    14271436        int i;
    1428         if (eclass == 0 && ecode == 0) return NT_STATUS_OK;
     1437        if (eclass == 0) return NT_STATUS_OK;
    14291438        for (i=0; NT_STATUS_V(dos_to_ntstatus_map[i].ntstatus); i++) {
    14301439                if (eclass == dos_to_ntstatus_map[i].dos_class &&
     
    15051514}
    15061515
    1507 /*******************************************************************************
    1508  Map between wbcErr and NT status.
    1509 *******************************************************************************/
    1510 
    1511 static const struct {
    1512         wbcErr wbc_err;
    1513         NTSTATUS nt_status;
    1514 } wbcErr_ntstatus_map[] = {
    1515         { WBC_ERR_SUCCESS,               NT_STATUS_OK },
    1516         { WBC_ERR_NOT_IMPLEMENTED,       NT_STATUS_NOT_IMPLEMENTED },
    1517         { WBC_ERR_UNKNOWN_FAILURE,       NT_STATUS_UNSUCCESSFUL },
    1518         { WBC_ERR_NO_MEMORY,             NT_STATUS_NO_MEMORY },
    1519         { WBC_ERR_INVALID_SID,           NT_STATUS_INVALID_SID },
    1520         { WBC_ERR_INVALID_PARAM,         NT_STATUS_INVALID_PARAMETER },
    1521         { WBC_ERR_WINBIND_NOT_AVAILABLE, NT_STATUS_SERVER_DISABLED },
    1522         { WBC_ERR_DOMAIN_NOT_FOUND,      NT_STATUS_NO_SUCH_DOMAIN },
    1523         { WBC_ERR_INVALID_RESPONSE,      NT_STATUS_INVALID_NETWORK_RESPONSE },
    1524         { WBC_ERR_NSS_ERROR,             NT_STATUS_INTERNAL_ERROR },
    1525         { WBC_ERR_AUTH_ERROR,            NT_STATUS_LOGON_FAILURE },
    1526         { WBC_ERR_UNKNOWN_USER,          NT_STATUS_NO_SUCH_USER },
    1527         { WBC_ERR_UNKNOWN_GROUP,         NT_STATUS_NO_SUCH_GROUP },
    1528         { WBC_ERR_PWD_CHANGE_FAILED,     NT_STATUS_PASSWORD_RESTRICTION }
    1529 };
    1530 
    1531 NTSTATUS map_nt_error_from_wbcErr(wbcErr wbc_err)
    1532 {
    1533         int i;
    1534 
    1535         /* Look through list */
    1536         for (i=0;i<ARRAY_SIZE(wbcErr_ntstatus_map);i++) {
    1537                 if (wbcErr_ntstatus_map[i].wbc_err == wbc_err) {
    1538                         return wbcErr_ntstatus_map[i].nt_status;
    1539                 }
    1540         }
    1541 
    1542         /* Default return */
    1543         return NT_STATUS_UNSUCCESSFUL;
    1544 }
    1545 
    15461516
    15471517#if defined(HAVE_GSSAPI)
  • vendor/current/source3/libsmb/libsmb_cache.c

    r414 r740  
    66   Copyright (C) John Terpstra 2000
    77   Copyright (C) Tom Jansen (Ninja ISD) 2002
    8    
     8
    99   This program is free software; you can redistribute it and/or modify
    1010   it under the terms of the GNU General Public License as published by
    1111   the Free Software Foundation; either version 3 of the License, or
    1212   (at your option) any later version.
    13    
     13
    1414   This program is distributed in the hope that it will be useful,
    1515   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1616   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1717   GNU General Public License for more details.
    18    
     18
    1919   You should have received a copy of the GNU General Public License
    2020   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2222
    2323#include "includes.h"
     24#include "libsmb/libsmb.h"
    2425#include "libsmbclient.h"
    2526#include "libsmb_internal.h"
     
    3536        char *username;
    3637        SMBCSRV *server;
    37        
     38
    3839        struct smbc_server_cache *next, *prev;
    3940};
     
    5455{
    5556        struct smbc_server_cache * srvcache = NULL;
    56        
     57
    5758        if (!(srvcache = SMB_MALLOC_P(struct smbc_server_cache))) {
    5859                errno = ENOMEM;
     
    6061                return 1;
    6162        }
    62        
     63
    6364        ZERO_STRUCTP(srvcache);
    64        
     65
    6566        srvcache->server = newsrv;
    66        
     67
    6768        srvcache->server_name = SMB_STRDUP(server);
    6869        if (!srvcache->server_name) {
     
    7071                goto failed;
    7172        }
    72        
     73
    7374        srvcache->share_name = SMB_STRDUP(share);
    7475        if (!srvcache->share_name) {
     
    7677                goto failed;
    7778        }
    78        
     79
    7980        srvcache->workgroup = SMB_STRDUP(workgroup);
    8081        if (!srvcache->workgroup) {
     
    8283                goto failed;
    8384        }
    84        
     85
    8586        srvcache->username = SMB_STRDUP(username);
    8687        if (!srvcache->username) {
     
    8889                goto failed;
    8990        }
    90        
     91
    9192        DLIST_ADD(context->internal->server_cache, srvcache);
    9293        return 0;
    93        
     94
    9495failed:
    9596        SAFE_FREE(srvcache->server_name);
     
    9899        SAFE_FREE(srvcache->username);
    99100        SAFE_FREE(srvcache);
    100        
     101
    101102        return 1;
    102103}
     
    117118{
    118119        struct smbc_server_cache * srv = NULL;
    119        
     120
    120121        /* Search the cache lines */
    121122        for (srv = context->internal->server_cache; srv; srv = srv->next) {
    122                
     123
    123124                if (strcmp(server,srv->server_name)  == 0 &&
    124125                    strcmp(workgroup,srv->workgroup) == 0 &&
    125126                    strcmp(user, srv->username)  == 0) {
    126                        
     127
    127128                        /* If the share name matches, we're cool */
    128129                        if (strcmp(share, srv->share_name) == 0) {
    129130                                return srv->server;
    130131                        }
    131                        
     132
    132133                        /*
    133134                         * We only return an empty share name or the attribute
     
    137138                        if (*share == '\0' || strcmp(share, "*IPC$") == 0)
    138139                                continue;
    139                        
     140
    140141                        /*
    141142                         * Never return an empty share name or the attribute
     
    145146                            strcmp(srv->share_name, "*IPC$") == 0)
    146147                                continue;
    147                        
     148
    148149                        /*
    149150                         * If we're only allowing one share per server, then
     
    152153                         */
    153154                        if (smbc_getOptionOneSharePerServer(context)) {
     155                                NTSTATUS status;
    154156                                /*
    155157                                 * The currently connected share name
     
    157159                                 * disconnect from the current share.
    158160                                 */
    159                                 if (! cli_tdis(srv->server->cli)) {
     161                                status = cli_tdis(srv->server->cli);
     162                                if (!NT_STATUS_IS_OK(status)) {
    160163                                        /* Sigh. Couldn't disconnect. */
    161164                                        cli_shutdown(srv->server->cli);
     
    164167                                        continue;
    165168                                }
    166                                
     169
    167170                                /*
    168171                                 * Save the new share name.  We've
     
    179182                                        continue;
    180183                                }
    181                                
    182                                
     184
    183185                                return srv->server;
    184186                        }
    185187                }
    186188        }
    187        
     189
    188190        return NULL;
    189191}
     
    200202{
    201203        struct smbc_server_cache * srv = NULL;
    202        
     204
    203205        for (srv = context->internal->server_cache; srv; srv = srv->next) {
    204206                if (server == srv->server) {
    205                        
     207
    206208                        /* remove this sucker */
    207209                        DLIST_REMOVE(context->internal->server_cache, srv);
     
    229231        struct smbc_server_cache * next;
    230232        int could_not_purge_all = 0;
    231        
     233
    232234        for (srv = context->internal->server_cache,
    233235                     next = (srv ? srv->next :NULL);
     
    235237             srv = next,
    236238                     next = (srv ? srv->next : NULL)) {
    237                
     239
    238240                if (SMBC_remove_unused_server(context, srv->server)) {
    239241                        /* could not be removed */
  • vendor/current/source3/libsmb/libsmb_compat.c

    r414 r740  
    77   Copyright (C) Tom Jansen (Ninja ISD) 2002
    88   Copyright (C) Derrell Lipman 2003, 2008
    9    
     9
    1010   This program is free software; you can redistribute it and/or modify
    1111   it under the terms of the GNU General Public License as published by
    1212   the Free Software Foundation; either version 3 of the License, or
    1313   (at your option) any later version.
    14    
     14
    1515   This program is distributed in the hope that it will be useful,
    1616   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1717   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1818   GNU General Public License for more details.
    19    
     19
    2020   You should have received a copy of the GNU General Public License
    2121   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    5656{
    5757        struct smbc_compat_fdlist * f = smbc_compat_fd_avail;
    58        
     58
    5959        if (f) {
    6060                /* We found one that's available */
    6161                DLIST_REMOVE(smbc_compat_fd_avail, f);
    62                
    6362        } else {
    6463                /*
     
    7372                        return -1;
    7473                }
    75                
     74
    7675                f = SMB_MALLOC_P(struct smbc_compat_fdlist);
    7776                if (!f) {
     
    7978                        return -1;
    8079                }
    81                
     80
    8281                f->fd = SMBC_BASE_FD + smbc_compat_nextfd++;
    8382        }
    84        
     83
    8584        f->file = file;
    8685        DLIST_ADD(smbc_compat_fd_in_use, f);
    87        
     86
    8887        return f->fd;
    8988}
     
    9695{
    9796        struct smbc_compat_fdlist * f = smbc_compat_fd_in_use;
    98        
     97
    9998        while (f) {
    10099                if (f->fd == fd)
     
    102101                f = f->next;
    103102        }
    104        
     103
    105104        if (f) {
    106105                /* found */
     
    123122                if (!statcont)
    124123                        return -1;
    125                
     124
    126125                smbc_setDebug(statcont, debug);
    127126                smbc_setFunctionAuthData(statcont, fn);
    128                
     127
    129128                if (!smbc_init_context(statcont)) {
    130129                        smbc_free_context(statcont, False);
    131130                        return -1;
    132131                }
    133                
     132
    134133                smbc_compat_initialized = 1;
    135                
     134
    136135                return 0;
    137136        }
     
    144143{
    145144        SMBCCTX *old_context = statcont;
    146        
     145
    147146        if (context) {
    148147                /* Save provided context.  It must have been initialized! */
    149148                statcont = context;
    150                
     149
    151150                /* You'd better know what you're doing.  We won't help you. */
    152151                smbc_compat_initialized = 1;
    153152        }
    154        
     153
    155154        return old_context;
    156155}
     
    164163        SMBCFILE * file;
    165164        int fd;
    166        
     165
    167166        file = smbc_getFunctionOpen(statcont)(statcont, furl, flags, mode);
    168167        if (!file)
    169168                return -1;
    170        
     169
    171170        fd = add_fd(file);
    172171        if (fd == -1)
     
    182181        SMBCFILE * file;
    183182        int fd;
    184        
     183
    185184        file = smbc_getFunctionCreat(statcont)(statcont, furl, mode);
    186185        if (!file)
    187186                return -1;
    188        
     187
    189188        fd = add_fd(file);
    190189        if (fd == -1) {
     
    251250        SMBCFILE * file;
    252251        int fd;
    253        
     252
    254253        file = smbc_getFunctionOpendir(statcont)(statcont, durl);
    255254        if (!file)
    256255                return -1;
    257        
     256
    258257        fd = add_fd(file);
    259258        if (fd == -1)
    260259                smbc_getFunctionClosedir(statcont)(statcont, file);
    261        
     260
    262261        return fd;
    263262}
     
    373372{
    374373        struct timeval tv[2];
    375        
     374
    376375        if (utbuf == NULL)
    377376                return smbc_getFunctionUtimes(statcont)(statcont, fname, NULL);
    378        
     377
    379378        tv[0].tv_sec = utbuf->actime;
    380379        tv[1].tv_sec = utbuf->modtime;
    381380        tv[0].tv_usec = tv[1].tv_usec = 0;
    382        
     381
    383382        return smbc_getFunctionUtimes(statcont)(statcont, fname, tv);
    384383}
     
    535534{
    536535        SMBCFILE * file;
    537        
     536
    538537        file = smbc_getFunctionOpenPrintJob(statcont)(statcont, fname);
    539538        if (!file) return -1;
  • vendor/current/source3/libsmb/libsmb_context.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424
    2525#include "includes.h"
     26#include "libsmb/libsmb.h"
    2627#include "libsmbclient.h"
    2728#include "libsmb_internal.h"
     29#include "secrets.h"
    2830
    2931
     
    4446    char *home = NULL;
    4547    TALLOC_CTX *frame = talloc_stackframe();
    46                
    47     load_case_tables();
    48                
    49     setup_logging("libsmbclient", True);
     48
     49    load_case_tables_library();
     50
     51    setup_logging("libsmbclient", DEBUG_STDOUT);
    5052
    5153    /* Here we would open the smb.conf file if needed ... */
    52                
     54
    5355    lp_set_in_client(True);
    54                
     56
    5557    home = getenv("HOME");
    5658    if (home) {
     
    6668        }
    6769    }
    68                
     70
    6971    if (!conf_loaded) {
    7072        /*
     
    7476         * defaults ...
    7577         */
    76                        
     78
    7779        if (!lp_load(get_dyn_CONFIGFILE(), True, False, False, False)) {
    7880            DEBUG(5, ("Could not load config file: %s\n",
     
    98100        }
    99101    }
    100                
     102
    101103    load_interfaces();  /* Load the list of interfaces ... */
    102                
     104
    103105    reopen_logs();  /* Get logging working ... */
    104                
     106
    105107    /*
    106108     * Block SIGPIPE (from lib/util_sock.c: write())
     
    108110     */
    109111    BlockSignals(True, SIGPIPE);
    110                
     112
    111113    /* Create the mutex we'll use to protect initialized_ctx_count */
    112114    if (SMB_THREAD_CREATE_MUTEX("initialized_ctx_count_mutex",
     
    137139{
    138140        SMBCCTX *context;
    139        
     141
    140142        /* The first call to this function should initialize the module */
    141143        SMB_THREAD_ONCE(&SMBC_initialized, SMBC_module_init, NULL);
     
    150152                return NULL;
    151153        }
    152        
     154
    153155        ZERO_STRUCTP(context);
    154        
     156
    155157        context->internal = SMB_MALLOC_P(struct SMBC_internal_data);
    156158        if (!context->internal) {
     
    159161                return NULL;
    160162        }
    161        
     163
    162164        /* Initialize the context and establish reasonable defaults */
    163165        ZERO_STRUCTP(context->internal);
    164        
     166
    165167        smbc_setDebug(context, 0);
    166168        smbc_setTimeout(context, 20000);
    167        
     169
    168170        smbc_setOptionFullTimeNames(context, False);
    169171        smbc_setOptionOpenShareMode(context, SMBC_SHAREMODE_DENY_NONE);
     
    177179                smbc_setOptionUseCCache(context, true);
    178180        }
    179        
     181
    180182        smbc_setFunctionAuthData(context, SMBC_get_auth_data);
    181183        smbc_setFunctionCheckServer(context, SMBC_check_server);
    182184        smbc_setFunctionRemoveUnusedServer(context, SMBC_remove_unused_server);
    183        
     185
    184186        smbc_setOptionUserData(context, NULL);
    185187        smbc_setFunctionAddCachedServer(context, SMBC_add_cached_server);
     
    187189        smbc_setFunctionRemoveCachedServer(context, SMBC_remove_cached_server);
    188190        smbc_setFunctionPurgeCachedServers(context, SMBC_purge_cached_servers);
    189        
     191
    190192        smbc_setFunctionOpen(context, SMBC_open_ctx);
    191193        smbc_setFunctionCreat(context, SMBC_creat_ctx);
     
    216218        smbc_setFunctionRemovexattr(context, SMBC_removexattr_ctx);
    217219        smbc_setFunctionListxattr(context, SMBC_listxattr_ctx);
    218        
     220
    219221        smbc_setFunctionOpenPrintJob(context, SMBC_open_print_job_ctx);
    220222        smbc_setFunctionPrintFile(context, SMBC_print_file_ctx);
    221223        smbc_setFunctionListPrintJobs(context, SMBC_list_print_jobs_ctx);
    222224        smbc_setFunctionUnlinkPrintJob(context, SMBC_unlink_print_job_ctx);
    223        
     225
    224226        return context;
    225227}
     
    240242                return 1;
    241243        }
    242        
     244
    243245        if (shutdown_ctx) {
    244246                SMBCFILE * f;
    245247                DEBUG(1,("Performing aggressive shutdown.\n"));
    246                
     248
    247249                f = context->internal->files;
    248250                while (f) {
     
    251253                }
    252254                context->internal->files = NULL;
    253                
     255
    254256                /* First try to remove the servers the nice way. */
    255257                if (smbc_getFunctionPurgeCachedServers(context)(context)) {
     
    294296                }
    295297        }
    296        
     298
    297299        /* Things we have to clean up */
    298300        smbc_setWorkgroup(context, NULL);
    299301        smbc_setNetbiosName(context, NULL);
    300302        smbc_setUser(context, NULL);
    301        
     303
    302304        DEBUG(3, ("Context %p successfully freed\n", context));
    303305
     
    325327                smb_panic("error unlocking 'initialized_ctx_count'");
    326328        }
    327        
     329
    328330        return 0;
    329331}
     
    347349                const char *s;
    348350        } option_value;
    349        
     351
    350352        va_start(ap, option_name);
    351        
     353
    352354        if (strcmp(option_name, "debug_to_stderr") == 0) {
    353355                option_value.b = (bool) va_arg(ap, int);
    354356                smbc_setOptionDebugToStderr(context, option_value.b);
    355                
     357
    356358        } else if (strcmp(option_name, "full_time_names") == 0) {
    357359                option_value.b = (bool) va_arg(ap, int);
    358360                smbc_setOptionFullTimeNames(context, option_value.b);
    359                
     361
    360362        } else if (strcmp(option_name, "open_share_mode") == 0) {
    361363                option_value.i = va_arg(ap, int);
    362364                smbc_setOptionOpenShareMode(context, option_value.i);
    363                
     365
    364366        } else if (strcmp(option_name, "auth_function") == 0) {
    365367                option_value.auth_fn =
    366368                        va_arg(ap, smbc_get_auth_data_with_context_fn);
    367369                smbc_setFunctionAuthDataWithContext(context, option_value.auth_fn);
    368                
     370
    369371        } else if (strcmp(option_name, "user_data") == 0) {
    370372                option_value.v = va_arg(ap, void *);
    371373                smbc_setOptionUserData(context, option_value.v);
    372                
     374
    373375        } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
    374376                option_value.s = va_arg(ap, const char *);
     
    383385                                                         SMBC_ENCRYPTLEVEL_REQUIRE);
    384386                }
    385                
     387
    386388        } else if (strcmp(option_name, "browse_max_lmb_count") == 0) {
    387389                option_value.i = va_arg(ap, int);
    388390                smbc_setOptionBrowseMaxLmbCount(context, option_value.i);
    389                
     391
    390392        } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) {
    391393                option_value.b = (bool) va_arg(ap, int);
    392394                smbc_setOptionUrlEncodeReaddirEntries(context, option_value.b);
    393                
     395
    394396        } else if (strcmp(option_name, "one_share_per_server") == 0) {
    395397                option_value.b = (bool) va_arg(ap, int);
    396398                smbc_setOptionOneSharePerServer(context, option_value.b);
    397                
     399
    398400        } else if (strcmp(option_name, "use_kerberos") == 0) {
    399401                option_value.b = (bool) va_arg(ap, int);
    400402                smbc_setOptionUseKerberos(context, option_value.b);
    401                
     403
    402404        } else if (strcmp(option_name, "fallback_after_kerberos") == 0) {
    403405                option_value.b = (bool) va_arg(ap, int);
    404406                smbc_setOptionFallbackAfterKerberos(context, option_value.b);
    405                
     407
    406408        } else if (strcmp(option_name, "use_ccache") == 0) {
    407409                option_value.b = (bool) va_arg(ap, int);
     
    412414                smbc_setOptionNoAutoAnonymousLogin(context, option_value.b);
    413415        }
    414        
     416
    415417        va_end(ap);
    416418}
     
    431433                return (void *) smbc_getOptionDebugToStderr(context);
    432434#endif
    433                
     435
    434436        } else if (strcmp(option_name, "full_time_names") == 0) {
    435437#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    438440                return (void *) smbc_getOptionFullTimeNames(context);
    439441#endif
    440                
     442
    441443        } else if (strcmp(option_name, "open_share_mode") == 0) {
    442444#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    445447                return (void *) smbc_getOptionOpenShareMode(context);
    446448#endif
    447                
     449
    448450        } else if (strcmp(option_name, "auth_function") == 0) {
    449451                return (void *) smbc_getFunctionAuthDataWithContext(context);
    450                
     452
    451453        } else if (strcmp(option_name, "user_data") == 0) {
    452454                return smbc_getOptionUserData(context);
    453                
     455
    454456        } else if (strcmp(option_name, "smb_encrypt_level") == 0) {
    455457                switch(smbc_getOptionSmbEncryptionLevel(context))
     
    462464                        return (void *) "require";
    463465                }
    464                
     466
    465467        } else if (strcmp(option_name, "smb_encrypt_on") == 0) {
    466468                SMBCSRV *s;
    467469                unsigned int num_servers = 0;
    468                
     470
    469471                for (s = context->internal->servers; s; s = s->next) {
    470472                        num_servers++;
     
    478480                return (void *) (bool) (num_servers > 0);
    479481#endif
    480                
     482
    481483        } else if (strcmp(option_name, "browse_max_lmb_count") == 0) {
    482484#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    485487                return (void *) smbc_getOptionBrowseMaxLmbCount(context);
    486488#endif
    487                
     489
    488490        } else if (strcmp(option_name, "urlencode_readdir_entries") == 0) {
    489491#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    492494                return (void *) (bool) smbc_getOptionUrlEncodeReaddirEntries(context);
    493495#endif
    494                
     496
    495497        } else if (strcmp(option_name, "one_share_per_server") == 0) {
    496498#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    499501                return (void *) (bool) smbc_getOptionOneSharePerServer(context);
    500502#endif
    501                
     503
    502504        } else if (strcmp(option_name, "use_kerberos") == 0) {
    503505#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    506508                return (void *) (bool) smbc_getOptionUseKerberos(context);
    507509#endif
    508                
     510
    509511        } else if (strcmp(option_name, "fallback_after_kerberos") == 0) {
    510512#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    513515                return (void *) (bool) smbc_getOptionFallbackAfterKerberos(context);
    514516#endif
    515                
     517
    516518        } else if (strcmp(option_name, "use_ccache") == 0) {
    517519#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
     
    528530#endif
    529531        }
    530        
     532
    531533        return NULL;
    532534}
     
    544546{
    545547        int pid;
    546        
     548
    547549        if (!context) {
    548550                errno = EBADF;
    549551                return NULL;
    550552        }
    551        
     553
    552554        /* Do not initialise the same client twice */
    553555        if (context->internal->initialized) {
    554556                return NULL;
    555557        }
    556        
    557         if (context->internal->debug_stderr) {
    558             /*
    559              * Hmmm... Do we want a unique dbf per-thread? For now, we'll just
    560              * leave it up to the user. If any one context spefies debug to
    561              * stderr then all will be.
    562              */
    563             dbf = x_stderr;
    564             x_setbuf(x_stderr, NULL);
    565         }
    566                
     558
    567559        if ((!smbc_getFunctionAuthData(context) &&
    568560             !smbc_getFunctionAuthDataWithContext(context)) ||
    569561            smbc_getDebug(context) < 0 ||
    570562            smbc_getDebug(context) > 100) {
    571                
     563
    572564                errno = EINVAL;
    573565                return NULL;
    574                
    575         }
    576        
     566
     567        }
     568
    577569        if (!smbc_getUser(context)) {
    578570                /*
    579571                 * FIXME: Is this the best way to get the user info?
    580572                 */
    581                 char *user = getenv("USER");
     573                char *user = getenv("USER");
    582574                /* walk around as "guest" if no username can be found */
    583575                if (!user) {
     
    595587                SAFE_FREE(user);
    596588
    597                 if (!smbc_getUser(context)) {
     589                if (!smbc_getUser(context)) {
    598590                        errno = ENOMEM;
    599591                        return NULL;
    600592                }
    601593        }
    602        
     594
    603595        if (!smbc_getNetbiosName(context)) {
    604596                /*
     
    629621                        return NULL;
    630622                }
    631                
     623
    632624                smbc_setNetbiosName(context, netbios_name);
    633625                SAFE_FREE(netbios_name);
     
    638630                }
    639631        }
    640        
     632
    641633        DEBUG(1, ("Using netbios name %s.\n", smbc_getNetbiosName(context)));
    642        
     634
    643635        if (!smbc_getWorkgroup(context)) {
    644636                char *workgroup;
     
    665657                }
    666658        }
    667        
     659
    668660        DEBUG(1, ("Using workgroup %s.\n", smbc_getWorkgroup(context)));
    669        
     661
    670662        /* shortest timeout is 1 second */
    671663        if (smbc_getTimeout(context) > 0 && smbc_getTimeout(context) < 1000)
    672664                smbc_setTimeout(context, 1000);
    673        
     665
    674666        context->internal->initialized = True;
    675667
     
    685677                smb_panic("error unlocking 'initialized_ctx_count'");
    686678        }
    687        
     679
    688680        return context;
    689681}
  • vendor/current/source3/libsmb/libsmb_dir.c

    r414 r740  
    2424
    2525#include "includes.h"
     26#include "libsmb/libsmb.h"
     27#include "popt_common.h"
    2628#include "libsmbclient.h"
    2729#include "libsmb_internal.h"
    28 #include "../librpc/gen_ndr/cli_srvsvc.h"
     30#include "rpc_client/cli_pipe.h"
     31#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
     32#include "libsmb/nmblib.h"
    2933
    3034/*
     
    147151
    148152        if (add_dirent(dir, name, comment, dirent_type) < 0) {
    149 
    150153                /* An error occurred, what do we do? */
    151154                /* FIXME: Add some code here */
     155                /* Change cli_NetServerEnum to take a fn
     156                   returning NTSTATUS... JRA. */
    152157        }
    153158
     
    227232
    228233        if (add_dirent(dir, name, comment, dirent_type) < 0) {
    229 
    230234                /* An error occurred, what do we do? */
    231235                /* FIXME: Add some code here */
    232 
    233         }
    234 }
    235 
    236 static void
     236                /* Change cli_NetServerEnum to take a fn
     237                   returning NTSTATUS... JRA. */
     238        }
     239}
     240
     241static NTSTATUS
    237242dir_list_fn(const char *mnt,
    238             file_info *finfo,
     243            struct file_info *finfo,
    239244            const char *mask,
    240245            void *state)
     
    242247
    243248        if (add_dirent((SMBCFILE *)state, finfo->name, "",
    244                        (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) {
    245 
    246                 /* Handle an error ... */
    247 
    248                 /* FIXME: Add some code ... */
    249 
    250         }
    251 
     249                       (finfo->mode&FILE_ATTRIBUTE_DIRECTORY?SMBC_DIR:SMBC_FILE)) < 0) {
     250                SMBCFILE *dir = (SMBCFILE *)state;
     251                return map_nt_error_from_unix(dir->dir_error);
     252        }
     253        return NT_STATUS_OK;
    252254}
    253255
     
    272274        uint32_t resume_handle = 0;
    273275        uint32_t total_entries = 0;
     276        struct dcerpc_binding_handle *b;
    274277
    275278        /* Open the server service pipe */
     
    287290        info_ctr.ctr.ctr1 = &ctr1;
    288291
     292        b = pipe_hnd->binding_handle;
     293
    289294        /* Issue the NetShareEnum RPC call and retrieve the response */
    290         nt_status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, talloc_tos(),
     295        nt_status = dcerpc_srvsvc_NetShareEnumAll(b, talloc_tos(),
    291296                                                  pipe_hnd->desthost,
    292297                                                  &info_ctr,
     
    297302
    298303        /* Was it successful? */
    299         if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result) ||
    300             total_entries == 0) {
     304        if (!NT_STATUS_IS_OK(nt_status)) {
     305                /*  Nope.  Go clean up. */
     306                result = ntstatus_to_werror(nt_status);
     307                goto done;
     308        }
     309
     310        if (!W_ERROR_IS_OK(result)) {
    301311                /*  Nope.  Go clean up. */
    302312                goto done;
    303313        }
     314
     315        if (total_entries == 0) {
     316                /*  Nope.  Go clean up. */
     317                result = WERR_GENERAL_FAILURE;
     318                goto done;
     319        }
    304320
    305321        /* For each returned entry... */
     
    370386        if (!context || !context->internal->initialized) {
    371387                DEBUG(4, ("no valid context\n"));
     388                TALLOC_FREE(frame);
    372389                errno = EINVAL + 8192;
    373                 TALLOC_FREE(frame);
    374390                return NULL;
    375391
     
    378394        if (!fname) {
    379395                DEBUG(4, ("no valid fname\n"));
     396                TALLOC_FREE(frame);
    380397                errno = EINVAL + 8193;
    381                 TALLOC_FREE(frame);
    382398                return NULL;
    383399        }
     
    394410                            &options)) {
    395411                DEBUG(4, ("no valid path\n"));
     412                TALLOC_FREE(frame);
    396413                errno = EINVAL + 8194;
    397                 TALLOC_FREE(frame);
    398414                return NULL;
    399415        }
     
    406422        if (SMBC_check_options(server, share, path, options)) {
    407423                DEBUG(4, ("unacceptable options (%s)\n", options));
     424                TALLOC_FREE(frame);
    408425                errno = EINVAL + 8195;
    409                 TALLOC_FREE(frame);
    410426                return NULL;
    411427        }
     
    414430                user = talloc_strdup(frame, smbc_getUser(context));
    415431                if (!user) {
     432                        TALLOC_FREE(frame);
    416433                        errno = ENOMEM;
    417                         TALLOC_FREE(frame);
    418434                        return NULL;
    419435                }
     
    423439
    424440        if (!dir) {
     441                TALLOC_FREE(frame);
    425442                errno = ENOMEM;
    426                 TALLOC_FREE(frame);
    427443                return NULL;
    428444        }
     
    442458                int count;
    443459                int max_lmb_count;
    444                 struct ip_service *ip_list;
    445                 struct ip_service server_addr;
     460                struct sockaddr_storage *ip_list;
     461                struct sockaddr_storage server_addr;
    446462                struct user_auth_info u_info;
     463                NTSTATUS status;
    447464
    448465                if (share[0] != (char)0 || path[0] != (char)0) {
    449466
    450                         errno = EINVAL + 8196;
    451467                        if (dir) {
    452468                                SAFE_FREE(dir->fname);
     
    454470                        }
    455471                        TALLOC_FREE(frame);
     472                        errno = EINVAL + 8196;
    456473                        return NULL;
    457474                }
     
    484501
    485502                ip_list = NULL;
    486                 if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
    487                                                         &count)))
     503                status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
     504                                            &ip_list, &count);
     505                if (!NT_STATUS_IS_OK(status))
    488506                {
    489507
    490                         SAFE_FREE(ip_list);
    491 
    492                         if (!find_master_ip(workgroup, &server_addr.ss)) {
     508                        TALLOC_FREE(ip_list);
     509
     510                        if (!find_master_ip(workgroup, &server_addr)) {
    493511
    494512                                if (dir) {
     
    496514                                        SAFE_FREE(dir);
    497515                                }
     516                                TALLOC_FREE(frame);
    498517                                errno = ENOENT;
    499                                 TALLOC_FREE(frame);
    500518                                return NULL;
    501519                        }
    502520
    503                         ip_list = (struct ip_service *)memdup(
    504                                 &server_addr, sizeof(server_addr));
     521                        ip_list = (struct sockaddr_storage *)talloc_memdup(
     522                                talloc_tos(), &server_addr,
     523                                sizeof(server_addr));
    505524                        if (ip_list == NULL) {
     525                                if (dir) {
     526                                        SAFE_FREE(dir->fname);
     527                                        SAFE_FREE(dir);
     528                                }
     529                                TALLOC_FREE(frame);
    506530                                errno = ENOMEM;
    507                                 TALLOC_FREE(frame);
    508531                                return NULL;
    509532                        }
     
    516539                        struct cli_state *cli = NULL;
    517540
    518                         print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
     541                        print_sockaddr(addr, sizeof(addr), &ip_list[i]);
    519542                        DEBUG(99, ("Found master browser %d of %d: %s\n",
    520543                                   i+1, MAX(count, max_lmb_count),
     
    537560
    538561                        if (!workgroup || !server) {
     562                                if (dir) {
     563                                        SAFE_FREE(dir->fname);
     564                                        SAFE_FREE(dir);
     565                                }
     566                                TALLOC_FREE(frame);
    539567                                errno = ENOMEM;
    540                                 TALLOC_FREE(frame);
    541568                                return NULL;
    542569                        }
     
    572599                }
    573600
    574                 SAFE_FREE(ip_list);
     601                TALLOC_FREE(ip_list);
    575602        } else {
    576603                /*
     
    582609
    583610                                /* Should not have empty share with path */
    584                                 errno = EINVAL + 8197;
    585611                                if (dir) {
    586612                                        SAFE_FREE(dir->fname);
     
    588614                                }
    589615                                TALLOC_FREE(frame);
     616                                errno = EINVAL + 8197;
    590617                                return NULL;
    591618
     
    645672                                                SAFE_FREE(dir);
    646673                                        }
     674                                        TALLOC_FREE(frame);
    647675                                        errno = EPERM;
    648                                         TALLOC_FREE(frame);
    649676                                        return NULL;
    650677
     
    749776                        char *targetpath;
    750777                        struct cli_state *targetcli;
     778                        NTSTATUS status;
    751779
    752780                        /* We connect to the server and list the directory */
     
    792820                        }
    793821
    794                         if (cli_list(targetcli, targetpath,
    795                                      aDIR | aSYSTEM | aHIDDEN,
    796                                      dir_list_fn, (void *)dir) < 0) {
    797 
     822                        status = cli_list(targetcli, targetpath,
     823                                          FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
     824                                          dir_list_fn, (void *)dir);
     825                        if (!NT_STATUS_IS_OK(status)) {
    798826                                if (dir) {
    799827                                        SAFE_FREE(dir->fname);
     
    845873                                }
    846874
     875                                TALLOC_FREE(frame);
    847876                                errno = saved_errno;
    848                                 TALLOC_FREE(frame);
    849877                                return NULL;
    850878                        }
     
    10491077        while ((dirlist = dir->dir_next)) {
    10501078                struct smbc_dirent *dirent;
     1079                struct smbc_dirent *currentEntry = (struct smbc_dirent *)ndir;
    10511080
    10521081                if (!dirlist->dirent) {
     
    10851114                }
    10861115
    1087                 memcpy(ndir, dirent, reqd); /* Copy the data in ... */
    1088 
    1089                 ((struct smbc_dirent *)ndir)->comment =
    1090                         (char *)(&((struct smbc_dirent *)ndir)->name +
    1091                                  dirent->namelen +
    1092                                  1);
     1116                memcpy(currentEntry, dirent, reqd); /* Copy the data in ... */
     1117
     1118                currentEntry->comment = &currentEntry->name[0] +
     1119                                                dirent->namelen + 1;
    10931120
    10941121                ndir += reqd;
    1095 
    10961122                rem -= reqd;
     1123
     1124                /* Try and align the struct for the next entry
     1125                   on a valid pointer boundary by appending zeros */
     1126                while((rem > 0) && ((unsigned long long)ndir & (sizeof(void*) - 1))) {
     1127                        *ndir = '\0';
     1128                        rem--;
     1129                        ndir++;
     1130                        currentEntry->dirlen++;
     1131                }
    10971132
    10981133                dir->dir_next = dirlist = dirlist -> next;
     
    12031238 */
    12041239
    1205 static void
     1240static NTSTATUS
    12061241rmdir_list_fn(const char *mnt,
    1207               file_info *finfo,
     1242              struct file_info *finfo,
    12081243              const char *mask,
    12091244              void *state)
     
    12141249                *smbc_rmdir_dirempty = false;
    12151250        }
     1251        return NT_STATUS_OK;
    12161252}
    12171253
     
    13031339                        char *lpath;
    13041340                        bool smbc_rmdir_dirempty = true;
     1341                        NTSTATUS status;
    13051342
    13061343                        lpath = talloc_asprintf(frame, "%s\\*",
     
    13121349                        }
    13131350
    1314                         if (cli_list(targetcli, lpath,
    1315                                      aDIR | aSYSTEM | aHIDDEN,
    1316                                      rmdir_list_fn,
    1317                                      &smbc_rmdir_dirempty) < 0) {
    1318 
     1351                        status = cli_list(targetcli, lpath,
     1352                                          FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
     1353                                          rmdir_list_fn,
     1354                                          &smbc_rmdir_dirempty);
     1355
     1356                        if (!NT_STATUS_IS_OK(status)) {
    13191357                                /* Fix errno to ignore latest error ... */
    13201358                                DEBUG(5, ("smbc_rmdir: "
     
    15781616        mode = 0;
    15791617
    1580         if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY;
    1581         if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH;
    1582         if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM;
    1583         if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN;
     1618        if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= FILE_ATTRIBUTE_READONLY;
     1619        if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= FILE_ATTRIBUTE_ARCHIVE;
     1620        if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= FILE_ATTRIBUTE_SYSTEM;
     1621        if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= FILE_ATTRIBUTE_HIDDEN;
    15841622
    15851623        if (!NT_STATUS_IS_OK(cli_setatr(targetcli, targetpath, mode, 0))) {
     
    17701808        /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/
    17711809
    1772         if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetpath, aSYSTEM | aHIDDEN))) {
     1810        if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetpath, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) {
    17731811
    17741812                errno = SMBC_errno(context, targetcli);
     
    19762014
    19772015                if (eno != EEXIST ||
    1978                     !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, aSYSTEM | aHIDDEN)) ||
     2016                    !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) ||
    19792017                    !NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1, targetpath2))) {
    19802018
  • vendor/current/source3/libsmb/libsmb_file.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424
    2525#include "includes.h"
     26#include "libsmb/libsmb.h"
    2627#include "libsmbclient.h"
    2728#include "libsmb_internal.h"
     
    5152        NTSTATUS status = NT_STATUS_OBJECT_PATH_INVALID;
    5253        TALLOC_CTX *frame = talloc_stackframe();
    53        
     54
    5455        if (!context || !context->internal->initialized) {
    55                
    5656                errno = EINVAL;  /* Best I can think of ... */
    5757                TALLOC_FREE(frame);
    5858                return NULL;
    59                
    60         }
    61        
     59        }
     60
    6261        if (!fname) {
    63                
    6462                errno = EINVAL;
    6563                TALLOC_FREE(frame);
    6664                return NULL;
    67                
    68         }
    69        
     65        }
     66
    7067        if (SMBC_parse_path(frame,
    7168                            context,
     
    8279                return NULL;
    8380        }
    84        
     81
    8582        if (!user || user[0] == (char)0) {
    8683                user = talloc_strdup(frame, smbc_getUser(context));
     
    9188                }
    9289        }
    93        
     90
    9491        srv = SMBC_server(frame, context, True,
    9592                          server, share, &workgroup, &user, &password);
    96        
    9793        if (!srv) {
    9894                if (errno == EPERM) errno = EACCES;
     
    10096                return NULL;  /* SMBC_server sets errno */
    10197        }
    102        
     98
    10399        /* Hmmm, the test for a directory is suspect here ... FIXME */
    104        
     100
    105101        if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') {
    106102                status = NT_STATUS_OBJECT_PATH_INVALID;
    107103        } else {
    108104                file = SMB_MALLOC_P(SMBCFILE);
    109                
    110105                if (!file) {
    111106                        errno = ENOMEM;
     
    113108                        return NULL;
    114109                }
    115                
     110
    116111                ZERO_STRUCTP(file);
    117                
     112
    118113                /*d_printf(">>>open: resolving %s\n", path);*/
    119114                if (!cli_resolve_path(frame, "", context->internal->auth_info,
     
    127122                }
    128123                /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
    129                
     124
    130125                status = cli_open(targetcli, targetpath, flags,
    131126                                   context->internal->share_mode, &fd);
    132127                if (!NT_STATUS_IS_OK(status)) {
    133                        
     128
    134129                        /* Handle the error ... */
    135                        
     130
    136131                        SAFE_FREE(file);
    137132                        errno = SMBC_errno(context, targetcli);
    138133                        TALLOC_FREE(frame);
    139134                        return NULL;
    140                        
    141135                }
    142                
     136
    143137                /* Fill in file struct */
    144                
     138
    145139                file->cli_fd  = fd;
    146140                file->fname   = SMB_STRDUP(fname);
     
    148142                file->offset  = 0;
    149143                file->file    = True;
    150                
     144
    151145                DLIST_ADD(context->internal->files, file);
    152                
     146
    153147                /*
    154148                 * If the file was opened in O_APPEND mode, all write
     
    181175                        }
    182176                }
    183                
     177
    184178                TALLOC_FREE(frame);
    185179                return file;
    186                
    187         }
    188        
     180        }
     181
    189182        /* Check if opendir needed ... */
    190        
     183
    191184        if (!NT_STATUS_IS_OK(status)) {
    192185                int eno = 0;
    193                
     186
    194187                eno = SMBC_errno(context, srv->cli);
    195188                file = smbc_getFunctionOpendir(context)(context, fname);
     
    197190                TALLOC_FREE(frame);
    198191                return file;
    199                
    200         }
    201        
     192        }
     193
    202194        errno = EINVAL; /* FIXME, correct errno ? */
    203195        TALLOC_FREE(frame);
    204196        return NULL;
    205        
    206197}
    207198
     
    215206               mode_t mode)
    216207{
    217        
    218208        if (!context || !context->internal->initialized) {
    219                
    220209                errno = EINVAL;
    221210                return NULL;
    222                
    223         }
    224        
     211        }
     212
    225213        return SMBC_open_ctx(context, path,
    226214                             O_WRONLY | O_CREAT | O_TRUNC, mode);
     
    243231        struct cli_state *targetcli = NULL;
    244232        TALLOC_CTX *frame = talloc_stackframe();
    245        
     233
    246234        /*
    247235         * offset:
     
    254242         */
    255243        off_t offset;
    256        
     244
    257245        if (!context || !context->internal->initialized) {
    258                
    259                 errno = EINVAL;
    260                 TALLOC_FREE(frame);
    261                 return -1;
    262                
    263         }
    264        
     246                errno = EINVAL;
     247                TALLOC_FREE(frame);
     248                return -1;
     249        }
     250
    265251        DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count));
    266        
     252
    267253        if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
    268254                errno = EBADF;
    269255                TALLOC_FREE(frame);
    270256                return -1;
    271                
    272         }
    273        
     257        }
     258
    274259        offset = file->offset;
    275        
     260
    276261        /* Check that the buffer exists ... */
    277        
     262
    278263        if (buf == NULL) {
    279264                errno = EINVAL;
    280265                TALLOC_FREE(frame);
    281266                return -1;
    282                
    283         }
    284        
     267        }
     268
    285269        /*d_printf(">>>read: parsing %s\n", file->fname);*/
    286270        if (SMBC_parse_path(frame,
     
    298282                return -1;
    299283        }
    300        
     284
    301285        /*d_printf(">>>read: resolving %s\n", path);*/
    302286        if (!cli_resolve_path(frame, "", context->internal->auth_info,
     
    309293        }
    310294        /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
    311        
     295
    312296        ret = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count);
    313        
     297
    314298        if (ret < 0) {
    315                
    316299                errno = SMBC_errno(context, targetcli);
    317300                TALLOC_FREE(frame);
    318301                return -1;
    319                
    320         }
    321        
     302        }
     303
    322304        file->offset += ret;
    323        
     305
    324306        DEBUG(4, ("  --> %d\n", ret));
    325        
     307
    326308        TALLOC_FREE(frame);
    327309        return ret;  /* Success, ret bytes of data ... */
    328        
    329310}
    330311
     
    339320               size_t count)
    340321{
    341         int ret;
    342322        off_t offset;
    343323        char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
     
    346326        struct cli_state *targetcli = NULL;
    347327        TALLOC_CTX *frame = talloc_stackframe();
    348        
     328        NTSTATUS status;
     329
    349330        /* First check all pointers before dereferencing them */
    350        
     331
    351332        if (!context || !context->internal->initialized) {
    352                
    353                 errno = EINVAL;
    354                 TALLOC_FREE(frame);
    355                 return -1;
    356                
    357         }
    358        
     333                errno = EINVAL;
     334                TALLOC_FREE(frame);
     335                return -1;
     336        }
     337
    359338        if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
    360339                errno = EBADF;
     
    362341                return -1;
    363342        }
    364        
     343
    365344        /* Check that the buffer exists ... */
    366        
     345
    367346        if (buf == NULL) {
    368347                errno = EINVAL;
    369348                TALLOC_FREE(frame);
    370349                return -1;
    371                
    372         }
    373        
     350        }
     351
    374352        offset = file->offset; /* See "offset" comment in SMBC_read_ctx() */
    375        
     353
    376354        /*d_printf(">>>write: parsing %s\n", file->fname);*/
    377355        if (SMBC_parse_path(frame,
     
    400378        }
    401379        /*d_printf(">>>write: resolved path as %s\n", targetpath);*/
    402        
    403         ret = cli_write(targetcli, file->cli_fd,
    404                         0, (char *)buf, offset, count);
    405        
    406         if (ret <= 0) {
    407                 errno = SMBC_errno(context, targetcli);
    408                 TALLOC_FREE(frame);
    409                 return -1;
    410                
    411         }
    412        
    413         file->offset += ret;
    414        
     380
     381        status = cli_writeall(targetcli, file->cli_fd,
     382                              0, (uint8_t *)buf, offset, count, NULL);
     383        if (!NT_STATUS_IS_OK(status)) {
     384                errno = map_errno_from_nt_status(status);
     385                TALLOC_FREE(frame);
     386                return -1;
     387        }
     388
     389        file->offset += count;
     390
    415391        TALLOC_FREE(frame);
    416         return ret;  /* Success, 0 bytes of data ... */
     392        return count;  /* Success, 0 bytes of data ... */
    417393}
    418394
     
    431407        struct cli_state *targetcli = NULL;
    432408        TALLOC_CTX *frame = talloc_stackframe();
    433        
     409
    434410        if (!context || !context->internal->initialized) {
    435                
    436                 errno = EINVAL;
    437                 TALLOC_FREE(frame);
    438                 return -1;
    439         }
    440        
     411                errno = EINVAL;
     412                TALLOC_FREE(frame);
     413                return -1;
     414        }
     415
    441416        if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
    442417                errno = EBADF;
     
    444419                return -1;
    445420        }
    446        
     421
    447422        /* IS a dir ... */
    448423        if (!file->file) {
     
    450425                return smbc_getFunctionClosedir(context)(context, file);
    451426        }
    452        
     427
    453428        /*d_printf(">>>close: parsing %s\n", file->fname);*/
    454429        if (SMBC_parse_path(frame,
     
    466441                return -1;
    467442        }
    468        
     443
    469444        /*d_printf(">>>close: resolving %s\n", path);*/
    470445        if (!cli_resolve_path(frame, "", context->internal->auth_info,
     
    477452        }
    478453        /*d_printf(">>>close: resolved path as %s\n", targetpath);*/
    479        
     454
    480455        if (!NT_STATUS_IS_OK(cli_close(targetcli, file->cli_fd))) {
    481                
    482456                DEBUG(3, ("cli_close failed on %s. purging server.\n",
    483457                          file->fname));
     
    492466                TALLOC_FREE(frame);
    493467                return -1;
    494                
    495         }
    496        
     468        }
     469
    497470        DLIST_REMOVE(context->internal->files, file);
    498471        SAFE_FREE(file->fname);
    499472        SAFE_FREE(file);
    500473        TALLOC_FREE(frame);
    501        
    502474        return 0;
    503475}
     
    524496        time_t write_time;
    525497        TALLOC_CTX *frame = talloc_stackframe();
    526        
     498
    527499        if (!context || !context->internal->initialized) {
    528                
    529500                errno = EINVAL;
    530501                TALLOC_FREE(frame);
    531502                return False;
    532503        }
    533        
     504
    534505        /* path fixup for . and .. */
    535506        if (strequal(path, ".") || strequal(path, "..")) {
     
    551522        }
    552523        DEBUG(4,("SMBC_getatr: sending qpathinfo\n"));
    553        
     524
    554525        if (!cli_resolve_path(frame, "", context->internal->auth_info,
    555526                        srv->cli, fixedpath,
     
    560531                return False;
    561532        }
    562        
     533
    563534        if (!srv->no_pathinfo2 &&
    564             cli_qpathinfo2(targetcli, targetpath,
     535            NT_STATUS_IS_OK(cli_qpathinfo2(targetcli, targetpath,
    565536                           create_time_ts,
    566537                           access_time_ts,
    567538                           write_time_ts,
    568539                           change_time_ts,
    569                            size, mode, ino)) {
     540                           size, mode, ino))) {
    570541                TALLOC_FREE(frame);
    571542                return True;
    572543        }
    573        
     544
    574545        /* if this is NT then don't bother with the getatr */
    575546        if (targetcli->capabilities & CAP_NT_SMBS) {
     
    578549                return False;
    579550        }
    580        
     551
    581552        if (NT_STATUS_IS_OK(cli_getatr(targetcli, targetpath, mode, size, &write_time))) {
    582                
    583553                struct timespec w_time_ts;
    584                
     554
    585555                w_time_ts = convert_time_t_to_timespec(write_time);
    586                
    587556                if (write_time_ts != NULL) {
    588557                        *write_time_ts = w_time_ts;
    589558                }
    590                
    591559                if (create_time_ts != NULL) {
    592560                        *create_time_ts = w_time_ts;
    593561                }
    594                
    595562                if (access_time_ts != NULL) {
    596563                        *access_time_ts = w_time_ts;
    597564                }
    598                
    599565                if (change_time_ts != NULL) {
    600566                        *change_time_ts = w_time_ts;
    601567                }
    602                
    603568                srv->no_pathinfo2 = True;
    604569                TALLOC_FREE(frame);
    605570                return True;
    606571        }
    607        
     572
    608573        errno = EPERM;
    609574        TALLOC_FREE(frame);
    610575        return False;
    611        
    612576}
    613577
     
    633597        int ret;
    634598        TALLOC_CTX *frame = talloc_stackframe();
    635        
     599
    636600        /*
    637601         * First, try setpathinfo (if qpathinfo succeeded), for it is the
     
    641605         */
    642606        if (srv->no_pathinfo ||
    643             ! cli_setpathinfo(srv->cli, path,
    644                               create_time,
    645                               access_time,
    646                               write_time,
    647                               change_time,
    648                               mode)) {
    649                
     607            !NT_STATUS_IS_OK(cli_setpathinfo_basic(srv->cli, path,
     608                                                   create_time,
     609                                                   access_time,
     610                                                   write_time,
     611                                                   change_time,
     612                                                   mode))) {
     613
    650614                /*
    651615                 * setpathinfo is not supported; go to plan B.
     
    657621                 * supports both times.
    658622                 */
    659                
     623
    660624                /* Don't try {q,set}pathinfo() again, with this server */
    661625                srv->no_pathinfo = True;
    662                
     626
    663627                /* Open the file */
    664628                if (!NT_STATUS_IS_OK(cli_open(srv->cli, path, O_RDWR, DENY_NONE, &fd))) {
    665                        
    666629                        errno = SMBC_errno(context, srv->cli);
    667630                        TALLOC_FREE(frame);
    668631                        return -1;
    669632                }
    670                
     633
    671634                /* Set the new attributes */
    672635                ret = NT_STATUS_IS_OK(cli_setattrE(srv->cli, fd,
     
    674637                                   access_time,
    675638                                   write_time));
    676                
     639
    677640                /* Close the file */
    678641                cli_close(srv->cli, fd);
    679                
     642
    680643                /*
    681644                 * Unfortunately, setattrE() doesn't have a provision for
     
    687650                        ret = NT_STATUS_IS_OK(cli_setatr(srv->cli, path, mode, 0));
    688651                }
    689                
     652
    690653                if (! ret) {
    691654                        errno = SMBC_errno(context, srv->cli);
     
    694657                }
    695658        }
    696        
     659
    697660        TALLOC_FREE(frame);
    698661        return True;
     
    715678        struct cli_state *targetcli = NULL;
    716679        TALLOC_CTX *frame = talloc_stackframe();
    717        
     680
    718681        if (!context || !context->internal->initialized) {
    719                
    720                 errno = EINVAL;
    721                 TALLOC_FREE(frame);
    722                 return -1;
    723         }
    724        
     682                errno = EINVAL;
     683                TALLOC_FREE(frame);
     684                return -1;
     685        }
     686
    725687        if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
    726                
    727688                errno = EBADF;
    728689                TALLOC_FREE(frame);
    729690                return -1;
    730                
    731         }
    732        
     691        }
     692
    733693        if (!file->file) {
    734                
    735694                errno = EINVAL;
    736695                TALLOC_FREE(frame);
    737696                return -1;      /* Can't lseek a dir ... */
    738                
    739         }
    740        
     697        }
     698
    741699        switch (whence) {
    742700        case SEEK_SET:
    743701                file->offset = offset;
    744702                break;
    745                
    746703        case SEEK_CUR:
    747704                file->offset += offset;
    748705                break;
    749                
    750706        case SEEK_END:
    751707                /*d_printf(">>>lseek: parsing %s\n", file->fname);*/
     
    764720                        return -1;
    765721                }
    766                
     722
    767723                /*d_printf(">>>lseek: resolving %s\n", path);*/
    768724                if (!cli_resolve_path(frame, "", context->internal->auth_info,
     
    774730                        return -1;
    775731                }
     732
    776733                /*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/
    777                
    778                 if (!cli_qfileinfo(targetcli, file->cli_fd, NULL,
    779                                    &size, NULL, NULL, NULL, NULL, NULL))
    780                 {
     734                if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
     735                                             targetcli, file->cli_fd, NULL,
     736                                             &size, NULL, NULL, NULL, NULL,
     737                                             NULL))) {
    781738                        SMB_OFF_T b_size = size;
    782739                        if (!NT_STATUS_IS_OK(cli_getattrE(targetcli, file->cli_fd,
     
    790747                file->offset = size + offset;
    791748                break;
    792                
    793749        default:
    794750                errno = EINVAL;
    795751                break;
    796                
    797         }
    798        
     752        }
     753
    799754        TALLOC_FREE(frame);
    800755        return file->offset;
    801        
    802756}
    803757
     
    821775        struct cli_state *targetcli = NULL;
    822776        TALLOC_CTX *frame = talloc_stackframe();
    823        
     777
    824778        if (!context || !context->internal->initialized) {
    825                
    826                 errno = EINVAL;
    827                 TALLOC_FREE(frame);
    828                 return -1;
    829         }
    830        
     779                errno = EINVAL;
     780                TALLOC_FREE(frame);
     781                return -1;
     782        }
     783
    831784        if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
    832785                errno = EBADF;
     
    834787                return -1;
    835788        }
    836        
     789
    837790        if (!file->file) {
    838791                errno = EINVAL;
     
    840793                return -1;
    841794        }
    842        
     795
    843796        /*d_printf(">>>fstat: parsing %s\n", file->fname);*/
    844797        if (SMBC_parse_path(frame,
     
    856809                return -1;
    857810        }
    858        
     811
    859812        /*d_printf(">>>fstat: resolving %s\n", path);*/
    860813        if (!cli_resolve_path(frame, "", context->internal->auth_info,
     
    867820        }
    868821        /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
    869        
     822
    870823        if (!NT_STATUS_IS_OK(cli_ftruncate(targetcli, file->cli_fd, (uint64_t)size))) {
    871824                errno = EINVAL;
     
    873826                return -1;
    874827        }
    875        
     828
    876829        TALLOC_FREE(frame);
    877830        return 0;
    878        
    879831}
  • vendor/current/source3/libsmb/libsmb_misc.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424
    2525#include "includes.h"
     26#include "libsmb/libsmb.h"
    2627#include "libsmbclient.h"
    2728#include "libsmb_internal.h"
     
    5152{
    5253        int ret = cli_errno(c);
    53        
     54
    5455        if (cli_is_dos_error(c)) {
    5556                uint8 eclass;
    5657                uint32 ecode;
    57                
     58
    5859                cli_dos_error(c, &eclass, &ecode);
    59                
     60
    6061                DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n",
    6162                         (int)eclass, (int)ecode, (int)ecode, ret));
    6263        } else {
    6364                NTSTATUS status;
    64                
     65
    6566                status = cli_nt_error(c);
    66                
     67
    6768                DEBUG(3,("smbc errno %s -> %d\n",
    6869                         nt_errstr(status), ret));
    6970        }
    70        
     71
    7172        return ret;
    7273}
  • vendor/current/source3/libsmb/libsmb_path.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    6161        size_t newlen = 1;
    6262        char *p, *dest;
    63        
     63
    6464        if (old_length == 0) {
    6565                return 0;
    6666        }
    67        
     67
    6868        *pp_dest = NULL;
    6969        for (i = 0; i < old_length; ) {
    7070                unsigned char character = src[i++];
    71                
     71
    7272                if (character == '%') {
    7373                        int a = i+1 < old_length ? hex2int(src[i]) : -1;
    7474                        int b = i+1 < old_length ? hex2int(src[i+1]) : -1;
    75                        
     75
    7676                        /* Replace valid sequence */
    7777                        if (a != -1 && b != -1) {
     
    8888                newlen++;
    8989        }
    90        
     90
    9191        dest = TALLOC_ARRAY(ctx, char, newlen);
    9292        if (!dest) {
    9393                return err_count;
    9494        }
    95        
     95
    9696        err_count = 0;
    9797        for (p = dest, i = 0; i < old_length; ) {
    9898                unsigned char character = src[i++];
    99                
     99
    100100                if (character == '%') {
    101101                        int a = i+1 < old_length ? hex2int(src[i]) : -1;
    102102                        int b = i+1 < old_length ? hex2int(src[i+1]) : -1;
    103                        
     103
    104104                        /* Replace valid sequence */
    105105                        if (a != -1 && b != -1) {
     
    116116                *p++ = character;
    117117        }
    118        
     118
    119119        *p = '\0';
    120120        *pp_dest = dest;
     
    130130        char *pdest;
    131131        int ret = urldecode_talloc(frame, &pdest, src);
    132        
     132
    133133        if (pdest) {
    134134                strlcpy(dest, pdest, max_dest_len);
     
    152152{
    153153        char hex[] = "0123456789ABCDEF";
    154        
     154
    155155        for (; *src != '\0' && max_dest_len >= 3; src++) {
    156                
     156
    157157                if ((*src < '0' &&
    158158                     *src != '-' &&
     
    173173                }
    174174        }
    175        
     175
    176176        *dest++ = '\0';
    177177        max_dest_len--;
    178        
     178
    179179        return max_dest_len;
    180180}
     
    236236        char *workgroup = NULL;
    237237        int len;
    238        
     238
    239239        /* Ensure these returns are at least valid pointers. */
    240240        *pp_server = talloc_strdup(ctx, "");
     
    243243        *pp_user = talloc_strdup(ctx, "");
    244244        *pp_password = talloc_strdup(ctx, "");
    245        
     245
    246246        if (!*pp_server || !*pp_share || !*pp_path ||
    247247            !*pp_user || !*pp_password) {
    248248                return -1;
    249249        }
    250        
     250
    251251        /*
    252252         * Assume we wont find an authentication domain to parse, so default
     
    257257                        talloc_strdup(ctx, smbc_getWorkgroup(context));
    258258        }
    259        
     259
    260260        if (pp_options) {
    261261                *pp_options = talloc_strdup(ctx, "");
    262262        }
    263263        s = talloc_strdup(ctx, fname);
    264        
     264
    265265        /* see if it has the right prefix */
    266266        len = strlen(SMBC_PREFIX);
     
    268268                return -1; /* What about no smb: ? */
    269269        }
    270        
     270
    271271        p = s + len;
    272        
     272
    273273        /* Watch the test below, we are testing to see if we should exit */
    274        
     274
    275275        if (strncmp(p, "//", 2) && strncmp(p, "\\\\", 2)) {
    276276                DEBUG(1, ("Invalid path (does not begin with smb://"));
    277277                return -1;
    278278        }
    279        
     279
    280280        p += 2;  /* Skip the double slash */
    281        
     281
    282282        /* See if any options were specified */
    283283        if ((q = strrchr(p, '?')) != NULL ) {
    284284                /* There are options.  Null terminate here and point to them */
    285285                *q++ = '\0';
    286                
     286
    287287                DEBUG(4, ("Found options '%s'", q));
    288                
     288
    289289                /* Copy the options */
    290290                if (pp_options && *pp_options != NULL) {
     
    293293                }
    294294        }
    295        
     295
    296296        if (*p == '\0') {
    297297                goto decoding;
    298298        }
    299        
     299
    300300        if (*p == '/') {
    301301                int wl = strlen(smbc_getWorkgroup(context));
    302                
     302
    303303                if (wl > 16) {
    304304                        wl = 16;
    305305                }
    306                
     306
    307307                *pp_server = talloc_strdup(ctx, smbc_getWorkgroup(context));
    308308                if (!*pp_server) {
     
    312312                return 0;
    313313        }
    314        
     314
    315315        /*
    316316         * ok, its for us. Now parse out the server, share etc.
     
    319319         * exists ...
    320320         */
    321        
     321
    322322        /* check that '@' occurs before '/', if '/' exists at all */
    323323        q = strchr_m(p, '@');
     
    326326                char *userinfo = NULL;
    327327                const char *u;
    328                
     328
    329329                next_token_no_ltrim_talloc(ctx, &p, &userinfo, "@");
    330330                if (!userinfo) {
     
    332332                }
    333333                u = userinfo;
    334                
     334
    335335                if (strchr_m(u, ';')) {
    336336                        next_token_no_ltrim_talloc(ctx, &u, &workgroup, ";");
     
    342342                        }
    343343                }
    344                
     344
    345345                if (strchr_m(u, ':')) {
    346346                        next_token_no_ltrim_talloc(ctx, &u, pp_user, ":");
     
    359359                }
    360360        }
    361        
     361
    362362        if (!next_token_talloc(ctx, &p, pp_server, "/")) {
    363363                return -1;
    364364        }
    365        
     365
    366366        if (*p == (char)0) {
    367367                goto decoding;  /* That's it ... */
    368368        }
    369        
     369
    370370        if (!next_token_talloc(ctx, &p, pp_share, "/")) {
    371371                return -1;
    372372        }
    373        
     373
    374374        /*
    375375         * Prepend a leading slash if there's a file path, as required by
     
    387387        }
    388388        string_replace(*pp_path, '/', '\\');
    389        
     389
    390390decoding:
    391        
    392391        (void) urldecode_talloc(ctx, pp_path, *pp_path);
    393392        (void) urldecode_talloc(ctx, pp_server, *pp_server);
     
    408407                                           *pp_user,
    409408                                           *pp_password);
    410        
    411409        return 0;
    412410}
  • vendor/current/source3/libsmb/libsmb_printjob.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424
    2525#include "includes.h"
     26#include "libsmb/libsmb.h"
    2627#include "libsmbclient.h"
    2728#include "libsmb_internal.h"
     
    4243        char *path = NULL;
    4344        TALLOC_CTX *frame = talloc_stackframe();
    44        
     45
    4546        if (!context || !context->internal->initialized) {
    46                
    4747                errno = EINVAL;
    4848                TALLOC_FREE(frame);
    4949                return NULL;
    5050        }
    51        
     51
    5252        if (!fname) {
    5353                errno = EINVAL;
     
    5555                return NULL;
    5656        }
    57        
     57
    5858        DEBUG(4, ("SMBC_open_print_job_ctx(%s)\n", fname));
    59        
     59
    6060        if (SMBC_parse_path(frame,
    6161                            context,
     
    7272                return NULL;
    7373        }
    74        
     74
    7575        /* What if the path is empty, or the file exists? */
    76        
     76
    7777        TALLOC_FREE(frame);
    7878        return smbc_getFunctionOpen(context)(context, fname, O_WRONLY, 666);
     
    9999        char buf[4096];
    100100        TALLOC_CTX *frame = talloc_stackframe();
    101        
     101
    102102        if (!c_file || !c_file->internal->initialized ||
    103103            !c_print || !c_print->internal->initialized) {
    104                
    105                 errno = EINVAL;
    106                 TALLOC_FREE(frame);
    107                 return -1;
    108                
    109         }
    110        
     104                errno = EINVAL;
     105                TALLOC_FREE(frame);
     106                return -1;
     107        }
     108
    111109        if (!fname && !printq) {
    112                
    113                 errno = EINVAL;
    114                 TALLOC_FREE(frame);
    115                 return -1;
    116                
    117         }
    118        
     110                errno = EINVAL;
     111                TALLOC_FREE(frame);
     112                return -1;
     113        }
     114
    119115        /* Try to open the file for reading ... */
    120        
     116
    121117        if ((long)(fid1 = smbc_getFunctionOpen(c_file)(c_file, fname,
    122118                                                       O_RDONLY, 0666)) < 0) {
     
    125121                return -1;  /* smbc_open sets errno */
    126122        }
    127        
     123
    128124        /* Now, try to open the printer file for writing */
    129        
     125
    130126        if ((long)(fid2 = smbc_getFunctionOpenPrintJob(c_print)(c_print,
    131127                                                                printq)) < 0) {
    132                
    133128                saverr = errno;  /* Save errno */
    134129                smbc_getFunctionClose(c_file)(c_file, fid1);
     
    136131                TALLOC_FREE(frame);
    137132                return -1;
    138                
    139         }
    140        
     133        }
     134
    141135        while ((bytes = smbc_getFunctionRead(c_file)(c_file, fid1,
    142136                                                     buf, sizeof(buf))) > 0) {
    143                
    144137                tot_bytes += bytes;
    145                
     138
    146139                if ((smbc_getFunctionWrite(c_print)(c_print, fid2,
    147140                                                    buf, bytes)) < 0) {
    148                        
    149141                        saverr = errno;
    150142                        smbc_getFunctionClose(c_file)(c_file, fid1);
    151143                        smbc_getFunctionClose(c_print)(c_print, fid2);
    152144                        errno = saverr;
    153                        
    154145                }
    155                
    156         }
    157        
     146        }
     147
    158148        saverr = errno;
    159        
     149
    160150        smbc_getFunctionClose(c_file)(c_file, fid1);
    161151        smbc_getFunctionClose(c_print)(c_print, fid2);
    162        
     152
    163153        if (bytes < 0) {
    164                
    165154                errno = saverr;
    166155                TALLOC_FREE(frame);
    167156                return -1;
    168                
    169         }
    170        
     157        }
     158
    171159        TALLOC_FREE(frame);
    172160        return tot_bytes;
    173        
    174161}
    175162
     
    191178        char *path = NULL;
    192179        TALLOC_CTX *frame = talloc_stackframe();
    193        
     180
    194181        if (!context || !context->internal->initialized) {
    195                
    196                 errno = EINVAL;
    197                 TALLOC_FREE(frame);
    198                 return -1;
    199         }
    200        
     182                errno = EINVAL;
     183                TALLOC_FREE(frame);
     184                return -1;
     185        }
     186
    201187        if (!fname) {
    202188                errno = EINVAL;
     
    204190                return -1;
    205191        }
    206        
     192
    207193        DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname));
    208        
     194
    209195        if (SMBC_parse_path(frame,
    210196                            context,
     
    221207                return -1;
    222208        }
    223        
     209
    224210        if (!user || user[0] == (char)0) {
    225211                user = talloc_strdup(frame, smbc_getUser(context));
     
    230216                }
    231217        }
    232        
     218
    233219        srv = SMBC_server(frame, context, True,
    234220                          server, share, &workgroup, &user, &password);
    235        
     221
    236222        if (!srv) {
    237223                TALLOC_FREE(frame);
    238224                return -1;  /* errno set by SMBC_server */
    239225        }
    240        
     226
    241227        if (cli_print_queue(srv->cli,
    242228                            (void (*)(struct print_job_info *))fn) < 0) {
     
    245231                return -1;
    246232        }
    247        
     233
    248234        TALLOC_FREE(frame);
    249235        return 0;
    250        
    251236}
    252237
     
    269254        int err;
    270255        TALLOC_CTX *frame = talloc_stackframe();
    271        
     256
    272257        if (!context || !context->internal->initialized) {
    273                
    274                 errno = EINVAL;
    275                 TALLOC_FREE(frame);
    276                 return -1;
    277         }
    278        
     258                errno = EINVAL;
     259                TALLOC_FREE(frame);
     260                return -1;
     261        }
     262
    279263        if (!fname) {
    280264                errno = EINVAL;
     
    282266                return -1;
    283267        }
    284        
     268
    285269        DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname));
    286        
     270
    287271        if (SMBC_parse_path(frame,
    288272                            context,
     
    299283                return -1;
    300284        }
    301        
     285
    302286        if (!user || user[0] == (char)0) {
    303287                user = talloc_strdup(frame, smbc_getUser(context));
     
    308292                }
    309293        }
    310        
     294
    311295        srv = SMBC_server(frame, context, True,
    312296                          server, share, &workgroup, &user, &password);
    313        
     297
    314298        if (!srv) {
    315                
    316299                TALLOC_FREE(frame);
    317300                return -1;  /* errno set by SMBC_server */
    318                
    319         }
    320        
     301        }
     302
    321303        if ((err = cli_printjob_del(srv->cli, id)) != 0) {
    322                
    323304                if (err < 0)
    324305                        errno = SMBC_errno(context, srv->cli);
     
    327308                TALLOC_FREE(frame);
    328309                return -1;
    329                
    330         }
    331        
     310        }
     311
    332312        TALLOC_FREE(frame);
    333313        return 0;
    334        
    335314}
    336315
  • vendor/current/source3/libsmb/libsmb_server.c

    r414 r740  
    2525
    2626#include "includes.h"
     27#include "libsmb/libsmb.h"
    2728#include "libsmbclient.h"
    2829#include "libsmb_internal.h"
    29 
     30#include "../librpc/gen_ndr/ndr_lsa.h"
     31#include "rpc_client/cli_pipe.h"
     32#include "rpc_client/cli_lsarpc.h"
     33#include "libcli/security/security.h"
     34#include "libsmb/nmblib.h"
    3035
    3136/*
     
    331336                                DEBUG(4,
    332337                                      ("IPC$ so ignore case sensitivity\n"));
    333                         } else if (!cli_get_fs_attr_info(c, &fs_attrs)) {
     338                        } else if (!NT_STATUS_IS_OK(cli_get_fs_attr_info(c, &fs_attrs))) {
    334339                                DEBUG(4, ("Could not retrieve "
    335340                                          "case sensitivity flag: %s.\n",
     
    568573        if (is_ipc) {
    569574                DEBUG(4, ("IPC$ so ignore case sensitivity\n"));
    570         } else if (!cli_get_fs_attr_info(c, &fs_attrs)) {
     575        } else if (!NT_STATUS_IS_OK(cli_get_fs_attr_info(c, &fs_attrs))) {
    571576                DEBUG(4, ("Could not retrieve case sensitivity flag: %s.\n",
    572577                          cli_errstr(c)));
     
    776781                                                *pp_password,
    777782                                                flags,
    778                                                 Undefined, NULL);
     783                                                Undefined);
    779784                if (! NT_STATUS_IS_OK(nt_status)) {
    780785                        DEBUG(1,("cli_full_connection failed! (%s)\n",
  • vendor/current/source3/libsmb/libsmb_setget.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    9191smbc_setDebug(SMBCCTX *c, int debug)
    9292{
     93        char buf[32];
     94        snprintf(buf, sizeof(buf), "%d", debug);
    9395        c->debug = debug;
    94         DEBUGLEVEL = debug;
     96        lp_set_cmdline("log level", buf);
    9597}
    9698
     
    119121smbc_getOptionDebugToStderr(SMBCCTX *c)
    120122{
    121         return c->internal->debug_stderr;
    122 }
    123 
    124 /** Set whether to log to standard error instead of standard output */
     123        /* Because this is a global concept, it is better to check
     124         * what is really set, rather than what we wanted set
     125         * (particularly as you cannot go back to stdout). */
     126        return debug_get_output_is_stderr();
     127}
     128
     129/** Set whether to log to standard error instead of standard output.
     130 * This option is 'sticky' - once set to true, it cannot be set to
     131 * false again, as it is global to the process, as once we have been
     132 * told that it is not safe to safe to write to stdout, we shouldn't
     133 * go back as we don't know it was this context that set it that way.
     134 */
    125135void
    126136smbc_setOptionDebugToStderr(SMBCCTX *c, smbc_bool b)
    127137{
    128         c->internal->debug_stderr = b;
     138        if (b) {
     139                /*
     140                 * We do not have a unique per-thread debug state? For
     141                 * now, we'll just leave it up to the user. If any one
     142                 * context spefies debug to stderr then all will be (and
     143                 * will stay that way, as it is unsafe to flip back if
     144                 * stdout is in use for other things)
     145                 */
     146                setup_logging("libsmbclient", DEBUG_STDERR);
     147        }
    129148}
    130149
  • vendor/current/source3/libsmb/libsmb_stat.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424
    2525#include "includes.h"
     26#include "libsmb/libsmb.h"
    2627#include "libsmbclient.h"
    2728#include "libsmb_internal.h"
     
    3738{
    3839        if (!context || !context->internal->initialized) {
    39                
    4040                errno = EINVAL;
    4141                return -1;
    42                
    43         }
    44        
     42        }
     43
    4544        if (!*name) return 2; /* FIXME, why 2 ??? */
    4645        return (ino_t)str_checksum(name);
    47        
    4846}
    4947
     
    6159{
    6260        TALLOC_CTX *frame = talloc_stackframe();
    63        
     61
    6462        st->st_mode = 0;
    65        
     63
    6664        if (IS_DOS_DIR(mode)) {
    6765                st->st_mode = SMBC_DIR_MODE;
     
    6967                st->st_mode = SMBC_FILE_MODE;
    7068        }
    71        
     69
    7270        if (IS_DOS_ARCHIVE(mode)) st->st_mode |= S_IXUSR;
    7371        if (IS_DOS_SYSTEM(mode)) st->st_mode |= S_IXGRP;
    7472        if (IS_DOS_HIDDEN(mode)) st->st_mode |= S_IXOTH;
    7573        if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR;
    76        
     74
    7775        st->st_size = size;
    7876#ifdef HAVE_STAT_ST_BLKSIZE
     
    8785        st->st_uid = getuid();
    8886        st->st_gid = getgid();
    89        
     87
    9088        if (IS_DOS_DIR(mode)) {
    9189                st->st_nlink = 2;
     
    9391                st->st_nlink = 1;
    9492        }
    95        
     93
    9694        if (st->st_ino == 0) {
    9795                st->st_ino = generate_inode(context, fname);
    9896        }
    99        
     97
    10098        TALLOC_FREE(frame);
    10199        return True;  /* FIXME: Is this needed ? */
    102        
    103100}
    104101
     
    126123        SMB_INO_T ino = 0;
    127124        TALLOC_CTX *frame = talloc_stackframe();
    128        
     125
    129126        if (!context || !context->internal->initialized) {
    130                
    131127                errno = EINVAL;  /* Best I can think of ... */
    132128                TALLOC_FREE(frame);
    133129                return -1;
    134130        }
    135        
     131
    136132        if (!fname) {
    137133                errno = EINVAL;
     
    139135                return -1;
    140136        }
    141        
     137
    142138        DEBUG(4, ("smbc_stat(%s)\n", fname));
    143        
     139
    144140        if (SMBC_parse_path(frame,
    145141                            context,
     
    165161                }
    166162        }
    167        
     163
    168164        srv = SMBC_server(frame, context, True,
    169165                          server, share, &workgroup, &user, &password);
    170        
    171166        if (!srv) {
    172167                TALLOC_FREE(frame);
    173168                return -1;  /* errno set by SMBC_server */
    174169        }
    175        
     170
    176171        if (!SMBC_getatr(context, srv, path, &mode, &size,
    177172                         NULL,
     
    184179                return -1;
    185180        }
    186        
     181
    187182        st->st_ino = ino;
    188        
     183
    189184        setup_stat(context, st, (char *) fname, size, mode);
    190        
     185
    191186        st->st_atime = convert_timespec_to_time_t(access_time_ts);
    192187        st->st_ctime = convert_timespec_to_time_t(change_time_ts);
    193188        st->st_mtime = convert_timespec_to_time_t(write_time_ts);
    194189        st->st_dev   = srv->dev;
    195        
     190
    196191        TALLOC_FREE(frame);
    197192        return 0;
    198        
    199193}
    200194
     
    222216        SMB_INO_T ino = 0;
    223217        TALLOC_CTX *frame = talloc_stackframe();
    224        
     218
    225219        if (!context || !context->internal->initialized) {
    226                
    227220                errno = EINVAL;
    228221                TALLOC_FREE(frame);
    229222                return -1;
    230223        }
    231        
     224
    232225        if (!file || !SMBC_dlist_contains(context->internal->files, file)) {
    233226                errno = EBADF;
     
    235228                return -1;
    236229        }
    237        
     230
    238231        if (!file->file) {
    239232                TALLOC_FREE(frame);
    240233                return smbc_getFunctionFstatdir(context)(context, file, st);
    241234        }
    242        
     235
    243236        /*d_printf(">>>fstat: parsing %s\n", file->fname);*/
    244237        if (SMBC_parse_path(frame,
     
    256249                return -1;
    257250        }
    258        
     251
    259252        /*d_printf(">>>fstat: resolving %s\n", path);*/
    260253        if (!cli_resolve_path(frame, "", context->internal->auth_info,
    261                         file->srv->cli, path,
    262                         &targetcli, &targetpath)) {
     254                              file->srv->cli, path,
     255                              &targetcli, &targetpath)) {
    263256                d_printf("Could not resolve %s\n", path);
    264257                errno = ENOENT;
     
    267260        }
    268261        /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
    269        
    270         if (!cli_qfileinfo(targetcli, file->cli_fd, &mode, &size,
    271                            NULL,
    272                            &access_time_ts,
    273                            &write_time_ts,
    274                            &change_time_ts,
    275                            &ino)) {
    276                
     262
     263        if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
     264                                     targetcli, file->cli_fd, &mode, &size,
     265                                     NULL,
     266                                     &access_time_ts,
     267                                     &write_time_ts,
     268                                     &change_time_ts,
     269                                     &ino))) {
    277270                time_t change_time, access_time, write_time;
    278                
     271
    279272                if (!NT_STATUS_IS_OK(cli_getattrE(targetcli, file->cli_fd, &mode, &size,
    280273                                  &change_time, &access_time, &write_time))) {
    281                        
    282274                        errno = EINVAL;
    283275                        TALLOC_FREE(frame);
    284276                        return -1;
    285277                }
    286                
    287278                change_time_ts = convert_time_t_to_timespec(change_time);
    288279                access_time_ts = convert_time_t_to_timespec(access_time);
    289280                write_time_ts = convert_time_t_to_timespec(write_time);
    290281        }
    291        
     282
    292283        st->st_ino = ino;
    293        
     284
    294285        setup_stat(context, st, file->fname, size, mode);
    295        
     286
    296287        st->st_atime = convert_timespec_to_time_t(access_time_ts);
    297288        st->st_ctime = convert_timespec_to_time_t(change_time_ts);
    298289        st->st_mtime = convert_timespec_to_time_t(write_time_ts);
    299290        st->st_dev = file->srv->dev;
    300        
     291
    301292        TALLOC_FREE(frame);
    302293        return 0;
    303        
    304294}
    305295
     
    369359        uint32 fs_attrs = 0;
    370360        struct cli_state *cli = file->srv->cli;
    371                
    372361
    373362        /* Initialize all fields (at least until we actually use them) */
     
    390379                uint64_t sectors_per_allocation_unit;
    391380                uint64_t bytes_per_sector;
    392                
     381                NTSTATUS status;
     382
    393383                /* Nope. If size data is available... */
    394                 if (cli_get_fs_full_size_info(cli,
    395                                               &total_allocation_units,
    396                                               &caller_allocation_units,
    397                                               &actual_allocation_units,
    398                                               &sectors_per_allocation_unit,
    399                                               &bytes_per_sector)) {
     384                status = cli_get_fs_full_size_info(cli,
     385                                                   &total_allocation_units,
     386                                                   &caller_allocation_units,
     387                                                   &actual_allocation_units,
     388                                                   &sectors_per_allocation_unit,
     389                                                   &bytes_per_sector);
     390                if (NT_STATUS_IS_OK(status)) {
    400391
    401392                        /* ... then provide it */
     
    422413                uint64_t free_file_nodes;
    423414                uint64_t fs_identifier;
     415                NTSTATUS status;
    424416
    425417                /* Has UNIXCIFS. If POSIX filesystem info is available... */
    426                 if (cli_get_posix_fs_info(cli,
    427                                           &optimal_transfer_size,
    428                                           &block_size,
    429                                           &total_blocks,
    430                                           &blocks_available,
    431                                           &user_blocks_available,
    432                                           &total_file_nodes,
    433                                           &free_file_nodes,
    434                                           &fs_identifier)) {
     418                status = cli_get_posix_fs_info(cli,
     419                                               &optimal_transfer_size,
     420                                               &block_size,
     421                                               &total_blocks,
     422                                               &blocks_available,
     423                                               &user_blocks_available,
     424                                               &total_file_nodes,
     425                                               &free_file_nodes,
     426                                               &fs_identifier);
     427                if (NT_STATUS_IS_OK(status)) {
    435428
    436429                        /* ... then what's provided here takes precedence. */
     
    455448
    456449        /* See if the share is case sensitive */
    457         if (!cli_get_fs_attr_info(cli, &fs_attrs)) {
     450        if (!NT_STATUS_IS_OK(cli_get_fs_attr_info(cli, &fs_attrs))) {
    458451                /*
    459452                 * We can't determine the case sensitivity of
  • vendor/current/source3/libsmb/libsmb_xattr.c

    r414 r740  
    88   Copyright (C) Derrell Lipman 2003-2008
    99   Copyright (C) Jeremy Allison 2007, 2008
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424
    2525#include "includes.h"
     26#include "libsmb/libsmb.h"
    2627#include "libsmbclient.h"
    2728#include "libsmb_internal.h"
    28 
     29#include "../librpc/gen_ndr/ndr_lsa.h"
     30#include "rpc_client/rpc_client.h"
     31#include "rpc_client/cli_lsarpc.h"
     32#include "../libcli/security/security.h"
    2933
    3034/*
     
    3539{
    3640        struct rpc_pipe_client *pipe_hnd;
    37        
     41
    3842        for (pipe_hnd = ipc_cli->pipe_list;
    3943             pipe_hnd;
    4044             pipe_hnd = pipe_hnd->next) {
    41                
    4245                if (ndr_syntax_id_equal(&pipe_hnd->abstract_syntax,
    4346                                        &ndr_table_lsarpc.syntax_id)) {
     
    4548                }
    4649        }
    47        
    4850        return NULL;
    4951}
     
    5658
    5759static int
    58 ace_compare(SEC_ACE *ace1,
    59             SEC_ACE *ace2)
     60ace_compare(struct security_ace *ace1,
     61            struct security_ace *ace2)
    6062{
    6163        bool b1;
    6264        bool b2;
    63        
     65
    6466        /* If the ACEs are equal, we have nothing more to do. */
    6567        if (sec_ace_equal(ace1, ace2)) {
    6668                return 0;
    6769        }
    68        
     70
    6971        /* Inherited follow non-inherited */
    7072        b1 = ((ace1->flags & SEC_ACE_FLAG_INHERITED_ACE) != 0);
     
    7375                return (b1 ? 1 : -1);
    7476        }
    75        
     77
    7678        /*
    7779         * What shall we do with AUDITs and ALARMs?  It's undefined.  We'll
     
    8991                return (b1 ? 1 : -1);
    9092        }
    91        
     93
    9294        /* Allowed ACEs follow denied ACEs */
    9395        b1 = (ace1->type == SEC_ACE_TYPE_ACCESS_ALLOWED ||
     
    98100                return (b1 ? 1 : -1);
    99101        }
    100        
     102
    101103        /*
    102104         * ACEs applying to an entity's object follow those applying to the
     
    110112                return (b1 ? 1 : -1);
    111113        }
    112        
     114
    113115        /*
    114116         * If we get this far, the ACEs are similar as far as the
     
    117119         * just seems reasonable.
    118120         */
    119        
     121
    120122        if (ace1->type != ace2->type) {
    121123                return ace2->type - ace1->type;
    122124        }
    123        
    124         if (sid_compare(&ace1->trustee, &ace2->trustee)) {
    125                 return sid_compare(&ace1->trustee, &ace2->trustee);
    126         }
    127        
     125
     126        if (dom_sid_compare(&ace1->trustee, &ace2->trustee)) {
     127                return dom_sid_compare(&ace1->trustee, &ace2->trustee);
     128        }
     129
    128130        if (ace1->flags != ace2->flags) {
    129131                return ace1->flags - ace2->flags;
    130132        }
    131        
     133
    132134        if (ace1->access_mask != ace2->access_mask) {
    133135                return ace1->access_mask - ace2->access_mask;
    134136        }
    135        
     137
    136138        if (ace1->size != ace2->size) {
    137139                return ace1->size - ace2->size;
    138140        }
    139        
    140         return memcmp(ace1, ace2, sizeof(SEC_ACE));
     141
     142        return memcmp(ace1, ace2, sizeof(struct security_ace));
    141143}
    142144
    143145
    144146static void
    145 sort_acl(SEC_ACL *the_acl)
     147sort_acl(struct security_acl *the_acl)
    146148{
    147149        uint32 i;
    148150        if (!the_acl) return;
    149        
    150         qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]),
    151               QSORT_CAST ace_compare);
    152        
     151
     152        TYPESAFE_QSORT(the_acl->aces, the_acl->num_aces, ace_compare);
     153
    153154        for (i=1;i<the_acl->num_aces;) {
    154155                if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
     
    170171                      fstring str,
    171172                      bool numeric,
    172                       DOM_SID *sid)
     173                      struct dom_sid *sid)
    173174{
    174175        char **domains = NULL;
     
    177178        struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
    178179        TALLOC_CTX *ctx;
    179        
     180
    180181        sid_to_fstring(str, sid);
    181        
     182
    182183        if (numeric) {
    183184                return;     /* no lookup desired */
    184185        }
    185        
     186
    186187        if (!pipe_hnd) {
    187188                return;
    188189        }
    189        
     190
    190191        /* Ask LSA to convert the sid to a name */
    191        
     192
    192193        ctx = talloc_stackframe();
    193        
     194
    194195        if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ctx,
    195196                                                    pol, 1, sid, &domains,
     
    199200                return;
    200201        }
    201        
     202
    202203        /* Converted OK */
    203        
     204
    204205        slprintf(str, sizeof(fstring) - 1, "%s%s%s",
    205206                 domains[0], lp_winbind_separator(),
     
    214215                      struct policy_handle *pol,
    215216                      bool numeric,
    216                       DOM_SID *sid,
     217                      struct dom_sid *sid,
    217218                      const char *str)
    218219{
    219220        enum lsa_SidType *types = NULL;
    220         DOM_SID *sids = NULL;
     221        struct dom_sid *sids = NULL;
    221222        bool result = True;
    222223        TALLOC_CTX *ctx = NULL;
    223224        struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
    224        
     225
    225226        if (!pipe_hnd) {
    226227                return False;
    227228        }
    228        
     229
    229230        if (numeric) {
    230231                if (strncmp(str, "S-", 2) == 0) {
    231232                        return string_to_sid(sid, str);
    232233                }
    233                
     234
    234235                result = False;
    235236                goto done;
    236237        }
    237        
     238
    238239        ctx = talloc_stackframe();
    239240        if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ctx,
     
    244245                goto done;
    245246        }
    246        
     247
    247248        sid_copy(sid, &sids[0]);
    248249done:
    249        
    250250        TALLOC_FREE(ctx);
    251251        return result;
     
    253253
    254254
    255 /* parse an ACE in the same format as print_ace() */
     255/* parse an struct security_ace in the same format as print_ace() */
    256256static bool
    257257parse_ace(struct cli_state *ipc_cli,
    258258          struct policy_handle *pol,
    259           SEC_ACE *ace,
     259          struct security_ace *ace,
    260260          bool numeric,
    261261          char *str)
     
    267267        unsigned int aflags;
    268268        unsigned int amask;
    269         DOM_SID sid;
     269        struct dom_sid sid;
    270270        uint32_t mask;
    271271        const struct perm_value *v;
     
    275275        };
    276276        TALLOC_CTX *frame = talloc_stackframe();
    277        
     277
    278278        /* These values discovered by inspection */
    279279        static const struct perm_value special_values[] = {
     
    286286                { "", 0 },
    287287        };
    288        
     288
    289289        static const struct perm_value standard_values[] = {
    290290                { "READ",   0x001200a9 },
     
    293293                { "", 0 },
    294294        };
    295        
    296        
     295
    297296        ZERO_STRUCTP(ace);
    298297        p = strchr_m(str,':');
     
    304303        p++;
    305304        /* Try to parse numeric form */
    306        
     305
    307306        if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
    308307            convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) {
    309308                goto done;
    310309        }
    311        
     310
    312311        /* Try to parse text form */
    313        
     312
    314313        if (!convert_string_to_sid(ipc_cli, pol, numeric, &sid, str)) {
    315314                TALLOC_FREE(frame);
    316315                return false;
    317316        }
    318        
     317
    319318        cp = p;
    320319        if (!next_token_talloc(frame, &cp, &tok, "/")) {
     
    322321                return false;
    323322        }
    324        
     323
    325324        if (StrnCaseCmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
    326325                atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
     
    331330                return false;
    332331        }
    333        
     332
    334333        /* Only numeric form accepted for flags at present */
    335        
     334
    336335        if (!(next_token_talloc(frame, &cp, &tok, "/") &&
    337336              sscanf(tok, "%i", &aflags))) {
     
    339338                return false;
    340339        }
    341        
     340
    342341        if (!next_token_talloc(frame, &cp, &tok, "/")) {
    343342                TALLOC_FREE(frame);
    344343                return false;
    345344        }
    346        
     345
    347346        if (strncmp(tok, "0x", 2) == 0) {
    348347                if (sscanf(tok, "%i", &amask) != 1) {
     
    352351                goto done;
    353352        }
    354        
     353
    355354        for (v = standard_values; v->perm; v++) {
    356355                if (strcmp(tok, v->perm) == 0) {
     
    359358                }
    360359        }
    361        
     360
    362361        p = tok;
    363        
     362
    364363        while(*p) {
    365364                bool found = False;
    366                
     365
    367366                for (v = special_values; v->perm; v++) {
    368367                        if (v->perm[0] == *p) {
     
    371370                        }
    372371                }
    373                
     372
    374373                if (!found) {
    375374                        TALLOC_FREE(frame);
     
    378377                p++;
    379378        }
    380        
     379
    381380        if (*p) {
    382381                TALLOC_FREE(frame);
    383382                return false;
    384383        }
    385        
     384
    386385done:
    387386        mask = amask;
     
    391390}
    392391
    393 /* add an ACE to a list of ACEs in a SEC_ACL */
     392/* add an struct security_ace to a list of struct security_aces in a struct security_acl */
    394393static bool
    395 add_ace(SEC_ACL **the_acl,
    396         SEC_ACE *ace,
     394add_ace(struct security_acl **the_acl,
     395        struct security_ace *ace,
    397396        TALLOC_CTX *ctx)
    398397{
    399         SEC_ACL *newacl;
    400         SEC_ACE *aces;
    401        
     398        struct security_acl *newacl;
     399        struct security_ace *aces;
     400
    402401        if (! *the_acl) {
    403402                (*the_acl) = make_sec_acl(ctx, 3, 1, ace);
    404403                return True;
    405404        }
    406        
    407         if ((aces = SMB_CALLOC_ARRAY(SEC_ACE,
     405
     406        if ((aces = SMB_CALLOC_ARRAY(struct security_ace,
    408407                                     1+(*the_acl)->num_aces)) == NULL) {
    409408                return False;
    410409        }
    411         memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
    412         memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
     410        memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(struct security_ace));
     411        memcpy(aces+(*the_acl)->num_aces, ace, sizeof(struct security_ace));
    413412        newacl = make_sec_acl(ctx, (*the_acl)->revision,
    414413                              1+(*the_acl)->num_aces, aces);
     
    420419
    421420/* parse a ascii version of a security descriptor */
    422 static SEC_DESC *
     421static struct security_descriptor *
    423422sec_desc_parse(TALLOC_CTX *ctx,
    424423               struct cli_state *ipc_cli,
     
    429428        const char *p = str;
    430429        char *tok;
    431         SEC_DESC *ret = NULL;
     430        struct security_descriptor *ret = NULL;
    432431        size_t sd_size;
    433         DOM_SID *group_sid=NULL;
    434         DOM_SID *owner_sid=NULL;
    435         SEC_ACL *dacl=NULL;
     432        struct dom_sid *group_sid=NULL;
     433        struct dom_sid *owner_sid=NULL;
     434        struct security_acl *dacl=NULL;
    436435        int revision=1;
    437        
     436
    438437        while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) {
    439                
     438
    440439                if (StrnCaseCmp(tok,"REVISION:", 9) == 0) {
    441440                        revision = strtol(tok+9, NULL, 16);
    442441                        continue;
    443442                }
    444                
     443
    445444                if (StrnCaseCmp(tok,"OWNER:", 6) == 0) {
    446445                        if (owner_sid) {
     
    448447                                goto done;
    449448                        }
    450                         owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
     449                        owner_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
    451450                        if (!owner_sid ||
    452451                            !convert_string_to_sid(ipc_cli, pol,
     
    458457                        continue;
    459458                }
    460                
     459
    461460                if (StrnCaseCmp(tok,"OWNER+:", 7) == 0) {
    462461                        if (owner_sid) {
     
    464463                                goto done;
    465464                        }
    466                         owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
     465                        owner_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
    467466                        if (!owner_sid ||
    468467                            !convert_string_to_sid(ipc_cli, pol,
     
    474473                        continue;
    475474                }
    476                
     475
    477476                if (StrnCaseCmp(tok,"GROUP:", 6) == 0) {
    478477                        if (group_sid) {
     
    480479                                goto done;
    481480                        }
    482                         group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
     481                        group_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
    483482                        if (!group_sid ||
    484483                            !convert_string_to_sid(ipc_cli, pol,
     
    490489                        continue;
    491490                }
    492                
     491
    493492                if (StrnCaseCmp(tok,"GROUP+:", 7) == 0) {
    494493                        if (group_sid) {
     
    496495                                goto done;
    497496                        }
    498                         group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
     497                        group_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
    499498                        if (!group_sid ||
    500499                            !convert_string_to_sid(ipc_cli, pol,
     
    506505                        continue;
    507506                }
    508                
     507
    509508                if (StrnCaseCmp(tok,"ACL:", 4) == 0) {
    510                         SEC_ACE ace;
     509                        struct security_ace ace;
    511510                        if (!parse_ace(ipc_cli, pol, &ace, numeric, tok+4)) {
    512511                                DEBUG(5, ("Failed to parse ACL %s\n", tok));
     
    519518                        continue;
    520519                }
    521                
     520
    522521                if (StrnCaseCmp(tok,"ACL+:", 5) == 0) {
    523                         SEC_ACE ace;
     522                        struct security_ace ace;
    524523                        if (!parse_ace(ipc_cli, pol, &ace, False, tok+5)) {
    525524                                DEBUG(5, ("Failed to parse ACL %s\n", tok));
     
    532531                        continue;
    533532                }
    534                
     533
    535534                DEBUG(5, ("Failed to parse security descriptor\n"));
    536535                goto done;
    537536        }
    538        
     537
    539538        ret = make_sec_desc(ctx, revision, SEC_DESC_SELF_RELATIVE,
    540539                            owner_sid, group_sid, NULL, dacl, &sd_size);
    541        
     540
    542541done:
    543542        SAFE_FREE(group_sid);
    544543        SAFE_FREE(owner_sid);
    545        
    546544        return ret;
    547545}
     
    563561        SMB_INO_T inode = 0;
    564562        DOS_ATTR_DESC *ret;
    565        
     563
    566564        ret = TALLOC_P(ctx, DOS_ATTR_DESC);
    567565        if (!ret) {
     
    569567                return NULL;
    570568        }
    571        
     569
    572570        /* Obtain the DOS attributes */
    573571        if (!SMBC_getatr(context, srv, CONST_DISCARD(char *, filename),
     
    582580                return NULL;
    583581        }
    584        
     582
    585583        ret->mode = mode;
    586584        ret->size = size;
     
    590588        ret->change_time = convert_timespec_to_time_t(change_time_ts);
    591589        ret->inode = inode;
    592        
     590
    593591        return ret;
    594592}
     
    612610                const char * change_time_attr;
    613611        } attr_strings;
    614        
     612
    615613        /* Determine whether to use old-style or new-style attribute names */
    616614        if (context->internal->full_time_names) {
     
    627625                attr_strings.change_time_attr = "C_TIME";
    628626        }
    629        
     627
    630628        /* if this is to set the entire ACL... */
    631629        if (*str == '*') {
     
    637635                }
    638636        }
    639        
     637
    640638        frame = talloc_stackframe();
    641639        while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) {
     
    652650                        continue;
    653651                }
    654                
     652
    655653                if (StrnCaseCmp(tok, "SIZE:", 5) == 0) {
    656654                        dad->size = (SMB_OFF_T)atof(tok+5);
    657655                        continue;
    658656                }
    659                
     657
    660658                n = strlen(attr_strings.access_time_attr);
    661659                if (StrnCaseCmp(tok, attr_strings.access_time_attr, n) == 0) {
     
    663661                        continue;
    664662                }
    665                
     663
    666664                n = strlen(attr_strings.change_time_attr);
    667665                if (StrnCaseCmp(tok, attr_strings.change_time_attr, n) == 0) {
     
    669667                        continue;
    670668                }
    671                
     669
    672670                n = strlen(attr_strings.write_time_attr);
    673671                if (StrnCaseCmp(tok, attr_strings.write_time_attr, n) == 0) {
     
    675673                        continue;
    676674                }
    677                
     675
    678676                if (attr_strings.create_time_attr != NULL) {
    679677                        n = strlen(attr_strings.create_time_attr);
     
    685683                        }
    686684                }
    687                
     685
    688686                if (StrnCaseCmp(tok, "INODE:", 6) == 0) {
    689687                        dad->inode = (SMB_INO_T)atof(tok+6);
     
    732730        bool determine_size = (bufsize == 0);
    733731        uint16_t fnum;
    734         SEC_DESC *sd;
     732        struct security_descriptor *sd;
    735733        fstring sidstr;
    736734        fstring name_sandbox;
     
    762760                const char * change_time_attr;
    763761        } excl_attr_strings;
    764        
     762
    765763        /* Determine whether to use old-style or new-style attribute names */
    766764        if (context->internal->full_time_names) {
     
    770768                attr_strings.write_time_attr = "WRITE_TIME";
    771769                attr_strings.change_time_attr = "CHANGE_TIME";
    772                
     770
    773771                excl_attr_strings.create_time_attr = "CREATE_TIME";
    774772                excl_attr_strings.access_time_attr = "ACCESS_TIME";
     
    781779                attr_strings.write_time_attr = "M_TIME";
    782780                attr_strings.change_time_attr = "C_TIME";
    783                
     781
    784782                excl_attr_strings.create_time_attr = NULL;
    785783                excl_attr_strings.access_time_attr = "dos_attr.A_TIME";
     
    787785                excl_attr_strings.change_time_attr = "dos_attr.C_TIME";
    788786        }
    789        
     787
    790788        /* Copy name so we can strip off exclusions (if any are specified) */
    791789        strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1);
    792        
     790
    793791        /* Ensure name is null terminated */
    794792        name_sandbox[sizeof(name_sandbox) - 1] = '\0';
    795        
     793
    796794        /* Play in the sandbox */
    797795        name = name_sandbox;
    798        
     796
    799797        /* If there are any exclusions, point to them and mask them from name */
    800798        if ((pExclude = strchr(name, '!')) != NULL)
     
    802800                *pExclude++ = '\0';
    803801        }
    804        
     802
    805803        all = (StrnCaseCmp(name, "system.*", 8) == 0);
    806804        all_nt = (StrnCaseCmp(name, "system.nt_sec_desc.*", 20) == 0);
     
    810808        some_dos = (StrnCaseCmp(name, "system.dos_attr.", 16) == 0);
    811809        numeric = (* (name + strlen(name) - 1) != '+');
    812        
     810
    813811        /* Look for exclusions from "all" requests */
    814812        if (all || all_nt || all_dos) {
    815                
    816813                /* Exclusions are delimited by '!' */
    817814                for (;
    818815                     pExclude != NULL;
    819816                     pExclude = (p == NULL ? NULL : p + 1)) {
    820                        
     817
    821818                        /* Find end of this exclusion name */
    822819                        if ((p = strchr(pExclude, '!')) != NULL)
     
    824821                                *p = '\0';
    825822                        }
    826                        
     823
    827824                        /* Which exclusion name is this? */
    828825                        if (StrCaseCmp(pExclude,
     
    878875                }
    879876        }
    880        
     877
    881878        n_used = 0;
    882        
     879
    883880        /*
    884881         * If we are (possibly) talking to an NT or new system and some NT
     
    951948                                }
    952949                        }
    953                        
     950
    954951                        if (!determine_size && n > bufsize) {
    955952                                errno = ERANGE;
     
    961958                        n = 0;
    962959                }
    963                
     960
    964961                if (! exclude_nt_owner) {
    965962                        /* Get owner and group sid */
     
    972969                                fstrcpy(sidstr, "");
    973970                        }
    974                        
     971
    975972                        if (all || all_nt) {
    976973                                if (determine_size) {
     
    999996                                }
    1000997                        }
    1001                        
     998
    1002999                        if (!determine_size && n > bufsize) {
    10031000                                errno = ERANGE;
     
    10091006                        n = 0;
    10101007                }
    1011                
     1008
    10121009                if (! exclude_nt_group) {
    10131010                        if (sd->group_sid) {
     
    10181015                                fstrcpy(sidstr, "");
    10191016                        }
    1020                        
     1017
    10211018                        if (all || all_nt) {
    10221019                                if (determine_size) {
     
    10451042                                }
    10461043                        }
    1047                        
     1044
    10481045                        if (!determine_size && n > bufsize) {
    10491046                                errno = ERANGE;
     
    10551052                        n = 0;
    10561053                }
    1057                
     1054
    10581055                if (! exclude_nt_acl) {
    10591056                        /* Add aces to value buffer  */
    10601057                        for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
    1061                                
    1062                                 SEC_ACE *ace = &sd->dacl->aces[i];
     1058
     1059                                struct security_ace *ace = &sd->dacl->aces[i];
    10631060                                convert_sid_to_string(ipc_cli, pol,
    10641061                                                      sidstr, numeric,
    10651062                                                      &ace->trustee);
    1066                                
     1063
    10671064                                if (all || all_nt) {
    10681065                                        if (determine_size) {
     
    11471144                        }
    11481145                }
    1149                
     1146
    11501147                /* Restore name pointer to its original value */
    11511148                name -= 19;
    11521149        }
    1153        
     1150
    11541151        if (all || some_dos) {
    11551152                /* Point to the portion after "system.dos_attr." */
    11561153                name += 16;     /* if (all) this will be invalid but unused */
    1157                
     1154
    11581155                /* Obtain the DOS attributes */
    11591156                if (!SMBC_getatr(context, srv, filename, &mode, &size,
     
    11631160                                 &change_time_ts,
    11641161                                 &ino)) {
    1165                        
     1162
    11661163                        errno = SMBC_errno(context, srv->cli);
    11671164                        return -1;
    1168                        
    1169                 }
    1170                
     1165                }
     1166
    11711167                create_time = convert_timespec_to_time_t(create_time_ts);
    11721168                access_time = convert_timespec_to_time_t(access_time_ts);
    11731169                write_time = convert_timespec_to_time_t(write_time_ts);
    11741170                change_time = convert_timespec_to_time_t(change_time_ts);
    1175                
     1171
    11761172                if (! exclude_dos_mode) {
    11771173                        if (all || all_dos) {
     
    12111207                                }
    12121208                        }
    1213                        
     1209
    12141210                        if (!determine_size && n > bufsize) {
    12151211                                errno = ERANGE;
     
    12211217                        n = 0;
    12221218                }
    1223                
     1219
    12241220                if (! exclude_dos_size) {
    12251221                        if (all || all_dos) {
     
    12561252                                }
    12571253                        }
    1258                        
     1254
    12591255                        if (!determine_size && n > bufsize) {
    12601256                                errno = ERANGE;
     
    12661262                        n = 0;
    12671263                }
    1268                
     1264
    12691265                if (! exclude_dos_create_time &&
    12701266                    attr_strings.create_time_attr != NULL) {
     
    12991295                                }
    13001296                        }
    1301                        
     1297
    13021298                        if (!determine_size && n > bufsize) {
    13031299                                errno = ERANGE;
     
    13091305                        n = 0;
    13101306                }
    1311                
     1307
    13121308                if (! exclude_dos_access_time) {
    13131309                        if (all || all_dos) {
     
    13411337                                }
    13421338                        }
    1343                        
     1339
    13441340                        if (!determine_size && n > bufsize) {
    13451341                                errno = ERANGE;
     
    13511347                        n = 0;
    13521348                }
    1353                
     1349
    13541350                if (! exclude_dos_write_time) {
    13551351                        if (all || all_dos) {
     
    13831379                                }
    13841380                        }
    1385                        
     1381
    13861382                        if (!determine_size && n > bufsize) {
    13871383                                errno = ERANGE;
     
    13931389                        n = 0;
    13941390                }
    1395                
     1391
    13961392                if (! exclude_dos_change_time) {
    13971393                        if (all || all_dos) {
     
    14251421                                }
    14261422                        }
    1427                        
     1423
    14281424                        if (!determine_size && n > bufsize) {
    14291425                                errno = ERANGE;
     
    14351431                        n = 0;
    14361432                }
    1437                
     1433
    14381434                if (! exclude_dos_inode) {
    14391435                        if (all || all_dos) {
     
    14701466                                }
    14711467                        }
    1472                        
     1468
    14731469                        if (!determine_size && n > bufsize) {
    14741470                                errno = ERANGE;
     
    14801476                        n = 0;
    14811477                }
    1482                
     1478
    14831479                /* Restore name pointer to its original value */
    14841480                name -= 16;
    14851481        }
    1486        
     1482
    14871483        if (n_used == 0) {
    14881484                errno = ENOATTR;
    14891485                return -1;
    14901486        }
    1491        
     1487
    14921488        return n_used;
    14931489}
     
    15091505        uint16_t fnum = (uint16_t)-1;
    15101506        int err = 0;
    1511         SEC_DESC *sd = NULL, *old;
    1512         SEC_ACL *dacl = NULL;
    1513         DOM_SID *owner_sid = NULL;
    1514         DOM_SID *group_sid = NULL;
     1507        struct security_descriptor *sd = NULL, *old;
     1508        struct security_acl *dacl = NULL;
     1509        struct dom_sid *owner_sid = NULL;
     1510        struct dom_sid *group_sid = NULL;
    15151511        uint32 i, j;
    15161512        size_t sd_size;
     
    15201516        char *targetpath = NULL;
    15211517        struct cli_state *targetcli = NULL;
     1518        NTSTATUS status;
    15221519
    15231520        /* the_acl will be null for REMOVE_ALL operations */
     
    15261523                           p > the_acl &&
    15271524                           p[-1] != '+');
    1528                
     1525
    15291526                /* if this is to set the entire ACL... */
    15301527                if (*the_acl == '*') {
     
    15321529                        the_acl = p + 1;
    15331530                }
    1534                
     1531
    15351532                sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, the_acl);
    1536                
    15371533                if (!sd) {
    15381534                        errno = EINVAL;
     
    15401536                }
    15411537        }
    1542        
     1538
    15431539        /* SMBC_XATTR_MODE_REMOVE_ALL is the only caller
    15441540           that doesn't deref sd */
    1545        
     1541
    15461542        if (!sd && (mode != SMBC_XATTR_MODE_REMOVE_ALL)) {
    15471543                errno = EINVAL;
     
    16021598                                }
    16031599                        }
    1604                        
     1600
    16051601                        if (!found) {
    16061602                                err = ENOATTR;
     
    16101606                }
    16111607                break;
    1612                
     1608
    16131609        case SMBC_XATTR_MODE_ADD:
    16141610                for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
    16151611                        bool found = False;
    1616                        
     1612
    16171613                        for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
    1618                                 if (sid_equal(&sd->dacl->aces[i].trustee,
     1614                                if (dom_sid_equal(&sd->dacl->aces[i].trustee,
    16191615                                              &old->dacl->aces[j].trustee)) {
    16201616                                        if (!(flags & SMBC_XATTR_FLAG_CREATE)) {
     
    16281624                                }
    16291625                        }
    1630                        
     1626
    16311627                        if (!found && (flags & SMBC_XATTR_FLAG_REPLACE)) {
    16321628                                err = ENOATTR;
     
    16341630                                goto failed;
    16351631                        }
    1636                        
     1632
    16371633                        for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
    16381634                                add_ace(&old->dacl, &sd->dacl->aces[i], ctx);
     
    16411637                dacl = old->dacl;
    16421638                break;
    1643                
     1639
    16441640        case SMBC_XATTR_MODE_SET:
    16451641                old = sd;
     
    16481644                dacl = old->dacl;
    16491645                break;
    1650                
     1646
    16511647        case SMBC_XATTR_MODE_CHOWN:
    16521648                owner_sid = sd->owner_sid;
    16531649                break;
    1654                
     1650
    16551651        case SMBC_XATTR_MODE_CHGRP:
    16561652                group_sid = sd->group_sid;
    16571653                break;
    16581654        }
    1659        
     1655
    16601656        /* Denied ACE entries must come before allowed ones */
    16611657        sort_acl(old->dacl);
    1662        
     1658
    16631659        /* Create new security descriptor and set it */
    16641660        sd = make_sec_desc(ctx, old->revision, SEC_DESC_SELF_RELATIVE,
    16651661                           owner_sid, group_sid, NULL, dacl, &sd_size);
    1666        
     1662
    16671663        if (!NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetpath, 0,
    16681664                             WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
     
    16731669                return -1;
    16741670        }
    1675        
    1676         if (!cli_set_secdesc(targetcli, fnum, sd)) {
     1671
     1672        status = cli_set_secdesc(targetcli, fnum, sd);
     1673        if (!NT_STATUS_IS_OK(status)) {
    16771674                DEBUG(5, ("ERROR: secdesc set failed: %s\n",
    1678                         cli_errstr(targetcli)));
     1675                          nt_errstr(status)));
    16791676                ret = -1;
    16801677        }
    1681        
     1678
    16821679        /* Clean up */
    1683        
     1680
    16841681failed:
    16851682        cli_close(targetcli, fnum);
    1686        
     1683
    16871684        if (err != 0) {
    16881685                errno = err;
    16891686        }
    1690        
     1687
    16911688        return ret;
    16921689}
     
    17191716        } attr_strings;
    17201717        TALLOC_CTX *frame = talloc_stackframe();
    1721        
     1718
    17221719        if (!context || !context->internal->initialized) {
    1723                
    17241720                errno = EINVAL;  /* Best I can think of ... */
    17251721                TALLOC_FREE(frame);
    17261722                return -1;
    17271723        }
    1728        
     1724
    17291725        if (!fname) {
    17301726                errno = EINVAL;
     
    17321728                return -1;
    17331729        }
    1734        
     1730
    17351731        DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n",
    17361732                  fname, name, (int) size, (const char*)value));
    1737        
     1733
    17381734        if (SMBC_parse_path(frame,
    17391735                            context,
     
    17501746                return -1;
    17511747        }
    1752        
     1748
    17531749        if (!user || user[0] == (char)0) {
    17541750                user = talloc_strdup(frame, smbc_getUser(context));
     
    17591755                }
    17601756        }
    1761        
     1757
    17621758        srv = SMBC_server(frame, context, True,
    17631759                          server, share, &workgroup, &user, &password);
     
    17661762                return -1;  /* errno set by SMBC_server */
    17671763        }
    1768        
     1764
    17691765        if (! srv->no_nt_session) {
    17701766                ipc_srv = SMBC_attr_server(frame, context, server, share,
     
    17761772                ipc_srv = NULL;
    17771773        }
    1778        
     1774
    17791775        /*
    17801776         * Are they asking to set the entire set of known attributes?
     
    17921788                        return -1;
    17931789                }
    1794                
     1790
    17951791                if (ipc_srv) {
    17961792                        ret = cacl_set(context, talloc_tos(), srv->cli,
     
    18041800                        ret = 0;
    18051801                }
    1806                
     1802
    18071803                /* get a DOS Attribute Descriptor with current attributes */
    18081804                dad = dos_attr_query(context, talloc_tos(), path, srv);
     
    18101806                        /* Overwrite old with new, using what was provided */
    18111807                        dos_attr_parse(context, dad, srv, namevalue);
    1812                        
     1808
    18131809                        /* Set the new DOS attributes */
    18141810                        if (! SMBC_setatr(context, srv, path,
     
    18181814                                          dad->change_time,
    18191815                                          dad->mode)) {
    1820                                
     1816
    18211817                                /* cause failure if NT failed too */
    18221818                                dad = NULL;
    18231819                        }
    18241820                }
    1825                
     1821
    18261822                /* we only fail if both NT and DOS sets failed */
    18271823                if (ret < 0 && ! dad) {
     
    18311827                        ret = 0;
    18321828                }
    1833                
     1829
    18341830                TALLOC_FREE(frame);
    18351831                return ret;
    18361832        }
    1837        
     1833
    18381834        /*
    18391835         * Are they asking to set an access control element or to set
     
    18451841            StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 ||
    18461842            StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) {
    1847                
     1843
    18481844                /* Yup. */
    18491845                char *namevalue =
    18501846                        talloc_asprintf(talloc_tos(), "%s:%s",
    18511847                                        name+19, (const char *) value);
    1852                
     1848
    18531849                if (! ipc_srv) {
    18541850                        ret = -1; /* errno set by SMBC_server() */
     
    18691865                return ret;
    18701866        }
    1871        
     1867
    18721868        /*
    18731869         * Are they asking to set the owner?
     
    18751871        if (StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 ||
    18761872            StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0) {
    1877                
     1873
    18781874                /* Yup. */
    18791875                char *namevalue =
    18801876                        talloc_asprintf(talloc_tos(), "%s:%s",
    18811877                                        name+19, (const char *) value);
    1882                
     1878
    18831879                if (! ipc_srv) {
    18841880                        ret = -1; /* errno set by SMBC_server() */
     
    18951891                return ret;
    18961892        }
    1897        
     1893
    18981894        /*
    18991895         * Are they asking to set the group?
     
    19011897        if (StrCaseCmp(name, "system.nt_sec_desc.group") == 0 ||
    19021898            StrCaseCmp(name, "system.nt_sec_desc.group+") == 0) {
    1903                
     1899
    19041900                /* Yup. */
    19051901                char *namevalue =
    19061902                        talloc_asprintf(talloc_tos(), "%s:%s",
    19071903                                        name+19, (const char *) value);
    1908                
     1904
    19091905                if (! ipc_srv) {
    19101906                        /* errno set by SMBC_server() */
     
    19221918                return ret;
    19231919        }
    1924        
     1920
    19251921        /* Determine whether to use old-style or new-style attribute names */
    19261922        if (context->internal->full_time_names) {
     
    19371933                attr_strings.change_time_attr = "system.dos_attr.C_TIME";
    19381934        }
    1939        
     1935
    19401936        /*
    19411937         * Are they asking to set a DOS attribute?
     
    19481944            StrCaseCmp(name, attr_strings.write_time_attr) == 0 ||
    19491945            StrCaseCmp(name, attr_strings.change_time_attr) == 0) {
    1950                
     1946
    19511947                /* get a DOS Attribute Descriptor with current attributes */
    19521948                dad = dos_attr_query(context, talloc_tos(), path, srv);
     
    19611957                                /* Overwrite old with provided new params */
    19621958                                dos_attr_parse(context, dad, srv, namevalue);
    1963                                
     1959
    19641960                                /* Set the new DOS attributes */
    19651961                                ret2 = SMBC_setatr(context, srv, path,
     
    19691965                                                   dad->change_time,
    19701966                                                   dad->mode);
    1971                                
     1967
    19721968                                /* ret2 has True (success) / False (failure) */
    19731969                                if (ret2) {
     
    19801976                        ret = -1;
    19811977                }
    1982                
     1978
    19831979                TALLOC_FREE(frame);
    19841980                return ret;
    19851981        }
    1986        
     1982
    19871983        /* Unsupported attribute name */
    19881984        errno = EINVAL;
     
    20142010        } attr_strings;
    20152011        TALLOC_CTX *frame = talloc_stackframe();
    2016        
     2012
    20172013        if (!context || !context->internal->initialized) {
    2018                
    20192014                errno = EINVAL;  /* Best I can think of ... */
    20202015                TALLOC_FREE(frame);
    20212016                return -1;
    20222017        }
    2023        
     2018
    20242019        if (!fname) {
    20252020                errno = EINVAL;
     
    20272022                return -1;
    20282023        }
    2029        
     2024
    20302025        DEBUG(4, ("smbc_getxattr(%s, %s)\n", fname, name));
    2031        
     2026
    20322027        if (SMBC_parse_path(frame,
    20332028                            context,
     
    20442039                return -1;
    20452040        }
    2046        
     2041
    20472042        if (!user || user[0] == (char)0) {
    20482043                user = talloc_strdup(frame, smbc_getUser(context));
     
    20532048                }
    20542049        }
    2055        
     2050
    20562051        srv = SMBC_server(frame, context, True,
    20572052                          server, share, &workgroup, &user, &password);
     
    20602055                return -1;  /* errno set by SMBC_server */
    20612056        }
    2062        
     2057
    20632058        if (! srv->no_nt_session) {
    20642059                ipc_srv = SMBC_attr_server(frame, context, server, share,
     
    20702065                ipc_srv = NULL;
    20712066        }
    2072        
     2067
    20732068        /* Determine whether to use old-style or new-style attribute names */
    20742069        if (context->internal->full_time_names) {
     
    20852080                attr_strings.change_time_attr = "system.dos_attr.C_TIME";
    20862081        }
    2087        
     2082
    20882083        /* Are they requesting a supported attribute? */
    20892084        if (StrCaseCmp(name, "system.*") == 0 ||
     
    21122107            StrCaseCmp(name, attr_strings.change_time_attr) == 0 ||
    21132108            StrCaseCmp(name, "system.dos_attr.inode") == 0) {
    2114                
     2109
    21152110                /* Yup. */
    21162111                char *filename = (char *) name;
     
    21272122                return ret;
    21282123        }
    2129        
     2124
    21302125        /* Unsupported attribute name */
    21312126        errno = EINVAL;
     
    21502145        char *path = NULL;
    21512146        TALLOC_CTX *frame = talloc_stackframe();
    2152        
     2147
    21532148        if (!context || !context->internal->initialized) {
    2154                
    21552149                errno = EINVAL;  /* Best I can think of ... */
    21562150                TALLOC_FREE(frame);
    21572151                return -1;
    21582152        }
    2159        
     2153
    21602154        if (!fname) {
    21612155                errno = EINVAL;
     
    21632157                return -1;
    21642158        }
    2165        
     2159
    21662160        DEBUG(4, ("smbc_removexattr(%s, %s)\n", fname, name));
    2167        
     2161
    21682162        if (SMBC_parse_path(frame,
    21692163                            context,
     
    21802174                return -1;
    21812175        }
    2182        
     2176
    21832177        if (!user || user[0] == (char)0) {
    21842178                user = talloc_strdup(frame, smbc_getUser(context));
     
    21892183                }
    21902184        }
    2191        
     2185
    21922186        srv = SMBC_server(frame, context, True,
    21932187                          server, share, &workgroup, &user, &password);
     
    21962190                return -1;  /* errno set by SMBC_server */
    21972191        }
    2198        
     2192
    21992193        if (! srv->no_nt_session) {
    22002194                ipc_srv = SMBC_attr_server(frame, context, server, share,
     
    22062200                ipc_srv = NULL;
    22072201        }
    2208        
     2202
    22092203        if (! ipc_srv) {
    22102204                TALLOC_FREE(frame);
    22112205                return -1; /* errno set by SMBC_attr_server */
    22122206        }
    2213        
     2207
    22142208        /* Are they asking to set the entire ACL? */
    22152209        if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 ||
    22162210            StrCaseCmp(name, "system.nt_sec_desc.*+") == 0) {
    2217                
     2211
    22182212                /* Yup. */
    22192213                ret = cacl_set(context, talloc_tos(), srv->cli,
     
    22232217                return ret;
    22242218        }
    2225        
     2219
    22262220        /*
    22272221         * Are they asking to remove one or more spceific security descriptor
     
    22352229            StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 ||
    22362230            StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) {
    2237                
     2231
    22382232                /* Yup. */
    22392233                ret = cacl_set(context, talloc_tos(), srv->cli,
     
    22442238                return ret;
    22452239        }
    2246        
     2240
    22472241        /* Unsupported attribute name */
    22482242        errno = EINVAL;
     
    23032297                ;
    23042298        const char * supported;
    2305        
     2299
    23062300        if (context->internal->full_time_names) {
    23072301                supported = supported_new;
     
    23112305                retsize = sizeof(supported_old);
    23122306        }
    2313        
     2307
    23142308        if (size == 0) {
    23152309                return retsize;
    23162310        }
    2317        
     2311
    23182312        if (retsize > size) {
    23192313                errno = ERANGE;
    23202314                return -1;
    23212315        }
    2322        
     2316
    23232317        /* this can't be strcpy() because there are embedded null characters */
    23242318        memcpy(list, supported, retsize);
  • vendor/current/source3/libsmb/namecache.c

    r414 r740  
    2525
    2626#define NBTKEY_FMT  "NBT/%s#%02X"
    27 
    28 /**
    29  * Initialise namecache system. Function calls gencache
    30  * initialisation function to perform necessary actions
    31  *
    32  * @return true upon successful initialisation of the cache or
    33  *         false on failure
    34  **/
    35 
    36 bool namecache_enable(void)
    37 {
    38         /*
    39          * Check if name caching disabled by setting the name cache
    40          * timeout to zero.
    41          */
    42 
    43         if (lp_name_cache_timeout() == 0) {
    44                 DEBUG(5, ("namecache_enable: disabling netbios name cache\n"));
    45                 return False;
    46         }
    47 
    48         /* I leave it for now, though I don't think we really
    49          * need this (mimir, 27.09.2002) */
    50         DEBUG(5, ("namecache_enable: enabling netbios namecache, timeout %d "
    51                   "seconds\n", lp_name_cache_timeout()));
    52 
    53         return True;
    54 }
    5527
    5628/**
     
    189161                SAFE_FREE(key);
    190162                return False;
    191         } else {
    192                 DEBUG(5, ("name %s#%02X found.\n", name, name_type));
    193         }
     163        }
     164
     165        DEBUG(5, ("name %s#%02X found.\n", name, name_type));
    194166
    195167        /*
  • vendor/current/source3/libsmb/namequery.c

    r414 r740  
    2020
    2121#include "includes.h"
     22#include "../lib/util/tevent_ntstatus.h"
     23#include "libads/sitename_cache.h"
     24#include "libads/dns.h"
     25#include "../libcli/netlogon/netlogon.h"
     26#include "lib/async_req/async_sock.h"
     27#include "libsmb/nmblib.h"
    2228
    2329/* nmbd.c sets this to True. */
     
    209215****************************************************************************/
    210216
    211 static NODE_STATUS_STRUCT *parse_node_status(char *p,
     217static struct node_status *parse_node_status(TALLOC_CTX *mem_ctx, char *p,
    212218                                int *num_names,
    213219                                struct node_status_extra *extra)
    214220{
    215         NODE_STATUS_STRUCT *ret;
     221        struct node_status *ret;
    216222        int i;
    217223
     
    221227                return NULL;
    222228
    223         ret = SMB_MALLOC_ARRAY(NODE_STATUS_STRUCT,*num_names);
     229        ret = TALLOC_ARRAY(mem_ctx, struct node_status,*num_names);
    224230        if (!ret)
    225231                return NULL;
     
    244250}
    245251
     252struct sock_packet_read_state {
     253        struct tevent_context *ev;
     254        enum packet_type type;
     255        int trn_id;
     256
     257        struct nb_packet_reader *reader;
     258        struct tevent_req *reader_req;
     259
     260        int sock;
     261        struct tevent_req *socket_req;
     262        uint8_t buf[1024];
     263        struct sockaddr_storage addr;
     264        socklen_t addr_len;
     265
     266        bool (*validator)(struct packet_struct *p,
     267                          void *private_data);
     268        void *private_data;
     269
     270        struct packet_struct *packet;
     271};
     272
     273static int sock_packet_read_state_destructor(struct sock_packet_read_state *s);
     274static void sock_packet_read_got_packet(struct tevent_req *subreq);
     275static void sock_packet_read_got_socket(struct tevent_req *subreq);
     276
     277static struct tevent_req *sock_packet_read_send(
     278        TALLOC_CTX *mem_ctx,
     279        struct tevent_context *ev,
     280        int sock, /* dgram socket */
     281        struct nb_packet_reader *reader,
     282        enum packet_type type,
     283        int trn_id,
     284        bool (*validator)(struct packet_struct *p, void *private_data),
     285        void *private_data)
     286{
     287        struct tevent_req *req;
     288        struct sock_packet_read_state *state;
     289
     290        req = tevent_req_create(mem_ctx, &state,
     291                                struct sock_packet_read_state);
     292        if (req == NULL) {
     293                return NULL;
     294        }
     295        talloc_set_destructor(state, sock_packet_read_state_destructor);
     296        state->ev = ev;
     297        state->reader = reader;
     298        state->sock = sock;
     299        state->type = type;
     300        state->trn_id = trn_id;
     301        state->validator = validator;
     302        state->private_data = private_data;
     303
     304        if (reader != NULL) {
     305                state->reader_req = nb_packet_read_send(state, ev, reader);
     306                if (tevent_req_nomem(state->reader_req, req)) {
     307                        return tevent_req_post(req, ev);
     308                }
     309                tevent_req_set_callback(
     310                        state->reader_req, sock_packet_read_got_packet, req);
     311        }
     312
     313        state->addr_len = sizeof(state->addr);
     314        state->socket_req = recvfrom_send(state, ev, sock,
     315                                          state->buf, sizeof(state->buf), 0,
     316                                          &state->addr, &state->addr_len);
     317        if (tevent_req_nomem(state->socket_req, req)) {
     318                return tevent_req_post(req, ev);
     319        }
     320        tevent_req_set_callback(state->socket_req, sock_packet_read_got_socket,
     321                                req);
     322
     323        return req;
     324}
     325
     326static int sock_packet_read_state_destructor(struct sock_packet_read_state *s)
     327{
     328        if (s->packet != NULL) {
     329                free_packet(s->packet);
     330                s->packet = NULL;
     331        }
     332        return 0;
     333}
     334
     335static void sock_packet_read_got_packet(struct tevent_req *subreq)
     336{
     337        struct tevent_req *req = tevent_req_callback_data(
     338                subreq, struct tevent_req);
     339        struct sock_packet_read_state *state = tevent_req_data(
     340                req, struct sock_packet_read_state);
     341        NTSTATUS status;
     342
     343        status = nb_packet_read_recv(subreq, &state->packet);
     344
     345        TALLOC_FREE(state->reader_req);
     346
     347        if (!NT_STATUS_IS_OK(status)) {
     348                if (state->socket_req != NULL) {
     349                        /*
     350                         * Still waiting for socket
     351                         */
     352                        return;
     353                }
     354                /*
     355                 * Both socket and packet reader failed
     356                 */
     357                tevent_req_nterror(req, status);
     358                return;
     359        }
     360
     361        if ((state->validator != NULL) &&
     362            !state->validator(state->packet, state->private_data)) {
     363                DEBUG(10, ("validator failed\n"));
     364
     365                free_packet(state->packet);
     366                state->packet = NULL;
     367
     368                state->reader_req = nb_packet_read_send(state, state->ev,
     369                                                        state->reader);
     370                if (tevent_req_nomem(state->reader_req, req)) {
     371                        return;
     372                }
     373                tevent_req_set_callback(
     374                        state->reader_req, sock_packet_read_got_packet, req);
     375                return;
     376        }
     377
     378        TALLOC_FREE(state->socket_req);
     379        tevent_req_done(req);
     380}
     381
     382static void sock_packet_read_got_socket(struct tevent_req *subreq)
     383{
     384        struct tevent_req *req = tevent_req_callback_data(
     385                subreq, struct tevent_req);
     386        struct sock_packet_read_state *state = tevent_req_data(
     387                req, struct sock_packet_read_state);
     388        struct sockaddr_in *in_addr;
     389        ssize_t received;
     390        int err;
     391
     392        received = recvfrom_recv(subreq, &err);
     393
     394        TALLOC_FREE(state->socket_req);
     395
     396        if (received == -1) {
     397                if (state->reader_req != NULL) {
     398                        /*
     399                         * Still waiting for reader
     400                         */
     401                        return;
     402                }
     403                /*
     404                 * Both socket and reader failed
     405                 */
     406                tevent_req_nterror(req, map_nt_error_from_unix(err));
     407                return;
     408        }
     409        if (state->addr.ss_family != AF_INET) {
     410                goto retry;
     411        }
     412        in_addr = (struct sockaddr_in *)(void *)&state->addr;
     413
     414        state->packet = parse_packet((char *)state->buf, received, state->type,
     415                                     in_addr->sin_addr, in_addr->sin_port);
     416        if (state->packet == NULL) {
     417                DEBUG(10, ("parse_packet failed\n"));
     418                goto retry;
     419        }
     420        if ((state->trn_id != -1) &&
     421            (state->trn_id != packet_trn_id(state->packet))) {
     422                DEBUG(10, ("Expected transaction id %d, got %d\n",
     423                           state->trn_id, packet_trn_id(state->packet)));
     424                goto retry;
     425        }
     426
     427        if ((state->validator != NULL) &&
     428            !state->validator(state->packet, state->private_data)) {
     429                DEBUG(10, ("validator failed\n"));
     430                goto retry;
     431        }
     432
     433        tevent_req_done(req);
     434        return;
     435
     436retry:
     437        if (state->packet != NULL) {
     438                free_packet(state->packet);
     439                state->packet = NULL;
     440        }
     441        state->socket_req = recvfrom_send(state, state->ev, state->sock,
     442                                          state->buf, sizeof(state->buf), 0,
     443                                          &state->addr, &state->addr_len);
     444        if (tevent_req_nomem(state->socket_req, req)) {
     445                return;
     446        }
     447        tevent_req_set_callback(state->socket_req, sock_packet_read_got_socket,
     448                                req);
     449}
     450
     451static NTSTATUS sock_packet_read_recv(struct tevent_req *req,
     452                                      struct packet_struct **ppacket)
     453{
     454        struct sock_packet_read_state *state = tevent_req_data(
     455                req, struct sock_packet_read_state);
     456        NTSTATUS status;
     457
     458        if (tevent_req_is_nterror(req, &status)) {
     459                return status;
     460        }
     461        *ppacket = state->packet;
     462        state->packet = NULL;
     463        return NT_STATUS_OK;
     464}
     465
     466struct nb_trans_state {
     467        struct tevent_context *ev;
     468        int sock;
     469        struct nb_packet_reader *reader;
     470
     471        const struct sockaddr_storage *dst_addr;
     472        uint8_t *buf;
     473        size_t buflen;
     474        enum packet_type type;
     475        int trn_id;
     476
     477        bool (*validator)(struct packet_struct *p,
     478                          void *private_data);
     479        void *private_data;
     480
     481        struct packet_struct *packet;
     482};
     483
     484static int nb_trans_state_destructor(struct nb_trans_state *s);
     485static void nb_trans_got_reader(struct tevent_req *subreq);
     486static void nb_trans_done(struct tevent_req *subreq);
     487static void nb_trans_sent(struct tevent_req *subreq);
     488static void nb_trans_send_next(struct tevent_req *subreq);
     489
     490static struct tevent_req *nb_trans_send(
     491        TALLOC_CTX *mem_ctx,
     492        struct tevent_context *ev,
     493        const struct sockaddr_storage *my_addr,
     494        const struct sockaddr_storage *dst_addr,
     495        bool bcast,
     496        uint8_t *buf, size_t buflen,
     497        enum packet_type type, int trn_id,
     498        bool (*validator)(struct packet_struct *p,
     499                          void *private_data),
     500        void *private_data)
     501{
     502        struct tevent_req *req, *subreq;
     503        struct nb_trans_state *state;
     504
     505        req = tevent_req_create(mem_ctx, &state, struct nb_trans_state);
     506        if (req == NULL) {
     507                return NULL;
     508        }
     509        talloc_set_destructor(state, nb_trans_state_destructor);
     510        state->ev = ev;
     511        state->dst_addr = dst_addr;
     512        state->buf = buf;
     513        state->buflen = buflen;
     514        state->type = type;
     515        state->trn_id = trn_id;
     516        state->validator = validator;
     517        state->private_data = private_data;
     518
     519        state->sock = open_socket_in(SOCK_DGRAM, 0, 3, my_addr, True);
     520        if (state->sock == -1) {
     521                tevent_req_nterror(req, map_nt_error_from_unix(errno));
     522                DEBUG(10, ("open_socket_in failed: %s\n", strerror(errno)));
     523                return tevent_req_post(req, ev);
     524        }
     525
     526        if (bcast) {
     527                set_socket_options(state->sock,"SO_BROADCAST");
     528        }
     529
     530        subreq = nb_packet_reader_send(state, ev, type, state->trn_id, NULL);
     531        if (tevent_req_nomem(subreq, req)) {
     532                return tevent_req_post(req, ev);
     533        }
     534        tevent_req_set_callback(subreq, nb_trans_got_reader, req);
     535        return req;
     536}
     537
     538static int nb_trans_state_destructor(struct nb_trans_state *s)
     539{
     540        if (s->sock != -1) {
     541                close(s->sock);
     542                s->sock = -1;
     543        }
     544        if (s->packet != NULL) {
     545                free_packet(s->packet);
     546                s->packet = NULL;
     547        }
     548        return 0;
     549}
     550
     551static void nb_trans_got_reader(struct tevent_req *subreq)
     552{
     553        struct tevent_req *req = tevent_req_callback_data(
     554                subreq, struct tevent_req);
     555        struct nb_trans_state *state = tevent_req_data(
     556                req, struct nb_trans_state);
     557        NTSTATUS status;
     558
     559        status = nb_packet_reader_recv(subreq, state, &state->reader);
     560        TALLOC_FREE(subreq);
     561
     562        if (!NT_STATUS_IS_OK(status)) {
     563                DEBUG(10, ("nmbd not around\n"));
     564                state->reader = NULL;
     565        }
     566
     567        subreq = sock_packet_read_send(
     568                state, state->ev, state->sock,
     569                state->reader, state->type, state->trn_id,
     570                state->validator, state->private_data);
     571        if (tevent_req_nomem(subreq, req)) {
     572                return;
     573        }
     574        tevent_req_set_callback(subreq, nb_trans_done, req);
     575
     576        subreq = sendto_send(state, state->ev, state->sock,
     577                             state->buf, state->buflen, 0, state->dst_addr);
     578        if (tevent_req_nomem(subreq, req)) {
     579                return;
     580        }
     581        tevent_req_set_callback(subreq, nb_trans_sent, req);
     582}
     583
     584static void nb_trans_sent(struct tevent_req *subreq)
     585{
     586        struct tevent_req *req = tevent_req_callback_data(
     587                subreq, struct tevent_req);
     588        struct nb_trans_state *state = tevent_req_data(
     589                req, struct nb_trans_state);
     590        ssize_t sent;
     591        int err;
     592
     593        sent = sendto_recv(subreq, &err);
     594        TALLOC_FREE(subreq);
     595        if (sent == -1) {
     596                DEBUG(10, ("sendto failed: %s\n", strerror(err)));
     597                tevent_req_nterror(req, map_nt_error_from_unix(err));
     598                return;
     599        }
     600        subreq = tevent_wakeup_send(state, state->ev,
     601                                    timeval_current_ofs(1, 0));
     602        if (tevent_req_nomem(subreq, req)) {
     603                return;
     604        }
     605        tevent_req_set_callback(subreq, nb_trans_send_next, req);
     606}
     607
     608static void nb_trans_send_next(struct tevent_req *subreq)
     609{
     610        struct tevent_req *req = tevent_req_callback_data(
     611                subreq, struct tevent_req);
     612        struct nb_trans_state *state = tevent_req_data(
     613                req, struct nb_trans_state);
     614        bool ret;
     615
     616        ret = tevent_wakeup_recv(subreq);
     617        TALLOC_FREE(subreq);
     618        if (!ret) {
     619                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     620                return;
     621        }
     622        subreq = sendto_send(state, state->ev, state->sock,
     623                             state->buf, state->buflen, 0, state->dst_addr);
     624        if (tevent_req_nomem(subreq, req)) {
     625                return;
     626        }
     627        tevent_req_set_callback(subreq, nb_trans_sent, req);
     628}
     629
     630static void nb_trans_done(struct tevent_req *subreq)
     631{
     632        struct tevent_req *req = tevent_req_callback_data(
     633                subreq, struct tevent_req);
     634        struct nb_trans_state *state = tevent_req_data(
     635                req, struct nb_trans_state);
     636        NTSTATUS status;
     637
     638        status = sock_packet_read_recv(subreq, &state->packet);
     639        TALLOC_FREE(subreq);
     640        if (tevent_req_nterror(req, status)) {
     641                return;
     642        }
     643        tevent_req_done(req);
     644}
     645
     646static NTSTATUS nb_trans_recv(struct tevent_req *req,
     647                              struct packet_struct **ppacket)
     648{
     649        struct nb_trans_state *state = tevent_req_data(
     650                req, struct nb_trans_state);
     651        NTSTATUS status;
     652
     653        if (tevent_req_is_nterror(req, &status)) {
     654                return status;
     655        }
     656        *ppacket = state->packet;
     657        state->packet = NULL;
     658        return NT_STATUS_OK;
     659}
    246660
    247661/****************************************************************************
     
    250664**************************************************************************/
    251665
    252 NODE_STATUS_STRUCT *node_status_query(int fd,
    253                                         struct nmb_name *name,
    254                                         const struct sockaddr_storage *to_ss,
    255                                         int *num_names,
    256                                         struct node_status_extra *extra)
    257 {
    258         bool found=False;
    259         int retries = 2;
    260         int retry_time = 2000;
    261         struct timeval tval;
     666struct node_status_query_state {
     667        struct sockaddr_storage my_addr;
     668        struct sockaddr_storage addr;
     669        uint8_t buf[1024];
     670        ssize_t buflen;
     671        struct packet_struct *packet;
     672};
     673
     674static int node_status_query_state_destructor(
     675        struct node_status_query_state *s);
     676static bool node_status_query_validator(struct packet_struct *p,
     677                                        void *private_data);
     678static void node_status_query_done(struct tevent_req *subreq);
     679
     680struct tevent_req *node_status_query_send(TALLOC_CTX *mem_ctx,
     681                                          struct tevent_context *ev,
     682                                          struct nmb_name *name,
     683                                          const struct sockaddr_storage *addr)
     684{
     685        struct tevent_req *req, *subreq;
     686        struct node_status_query_state *state;
    262687        struct packet_struct p;
    263         struct packet_struct *p2;
    264688        struct nmb_packet *nmb = &p.packet.nmb;
    265         NODE_STATUS_STRUCT *ret;
     689        struct sockaddr_in *in_addr;
     690
     691        req = tevent_req_create(mem_ctx, &state,
     692                                struct node_status_query_state);
     693        if (req == NULL) {
     694                return NULL;
     695        }
     696        talloc_set_destructor(state, node_status_query_state_destructor);
     697
     698        if (addr->ss_family != AF_INET) {
     699                /* Can't do node status to IPv6 */
     700                tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
     701                return tevent_req_post(req, ev);
     702        }
     703
     704        state->addr = *addr;
     705        in_addr = (struct sockaddr_in *)(void *)&state->addr;
     706        in_addr->sin_port = htons(NMB_PORT);
     707
     708        if (!interpret_string_addr(&state->my_addr, lp_socket_address(),
     709                                   AI_NUMERICHOST|AI_PASSIVE)) {
     710                zero_sockaddr(&state->my_addr);
     711        }
    266712
    267713        ZERO_STRUCT(p);
    268 
    269         if (to_ss->ss_family != AF_INET) {
    270                 /* Can't do node status to IPv6 */
    271                 return NULL;
    272         }
    273714        nmb->header.name_trn_id = generate_trn_id();
    274715        nmb->header.opcode = 0;
     
    288729        nmb->question.question_class = 0x1;
    289730
    290         p.ip = ((const struct sockaddr_in *)to_ss)->sin_addr;
    291         p.port = NMB_PORT;
    292         p.recv_fd = -1;
    293         p.send_fd = fd;
    294         p.timestamp = time(NULL);
    295         p.packet_type = NMB_PACKET;
    296 
    297         GetTimeOfDay(&tval);
    298 
    299         if (!send_packet(&p))
    300                 return NULL;
    301 
    302         retries--;
    303 
    304         while (1) {
    305                 struct timeval tval2;
    306                 GetTimeOfDay(&tval2);
    307                 if (TvalDiff(&tval,&tval2) > retry_time) {
    308                         if (!retries)
    309                                 break;
    310                         if (!found && !send_packet(&p))
    311                                 return NULL;
    312                         GetTimeOfDay(&tval);
    313                         retries--;
    314                 }
    315 
    316                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
    317                         struct nmb_packet *nmb2 = &p2->packet.nmb;
    318                         debug_nmb_packet(p2);
    319 
    320                         if (nmb2->header.opcode != 0 ||
    321                             nmb2->header.nm_flags.bcast ||
    322                             nmb2->header.rcode ||
    323                             !nmb2->header.ancount ||
    324                             nmb2->answers->rr_type != 0x21) {
    325                                 /* XXXX what do we do with this? could be a
    326                                    redirect, but we'll discard it for the
    327                                    moment */
    328                                 free_packet(p2);
    329                                 continue;
    330                         }
    331 
    332                         ret = parse_node_status(&nmb2->answers->rdata[0],
    333                                         num_names, extra);
    334                         free_packet(p2);
    335                         return ret;
    336                 }
    337         }
    338 
    339         return NULL;
     731        state->buflen = build_packet((char *)state->buf, sizeof(state->buf),
     732                                     &p);
     733        if (state->buflen == 0) {
     734                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     735                DEBUG(10, ("build_packet failed\n"));
     736                return tevent_req_post(req, ev);
     737        }
     738
     739        subreq = nb_trans_send(state, ev, &state->my_addr, &state->addr, false,
     740                               state->buf, state->buflen,
     741                               NMB_PACKET, nmb->header.name_trn_id,
     742                               node_status_query_validator, NULL);
     743        if (tevent_req_nomem(subreq, req)) {
     744                DEBUG(10, ("nb_trans_send failed\n"));
     745                return tevent_req_post(req, ev);
     746        }
     747        if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(10, 0))) {
     748                return tevent_req_post(req, ev);
     749        }
     750        tevent_req_set_callback(subreq, node_status_query_done, req);
     751        return req;
     752}
     753
     754static bool node_status_query_validator(struct packet_struct *p,
     755                                        void *private_data)
     756{
     757        struct nmb_packet *nmb = &p->packet.nmb;
     758        debug_nmb_packet(p);
     759
     760        if (nmb->header.opcode != 0 ||
     761            nmb->header.nm_flags.bcast ||
     762            nmb->header.rcode ||
     763            !nmb->header.ancount ||
     764            nmb->answers->rr_type != 0x21) {
     765                /*
     766                 * XXXX what do we do with this? could be a redirect,
     767                 * but we'll discard it for the moment
     768                 */
     769                return false;
     770        }
     771        return true;
     772}
     773
     774static int node_status_query_state_destructor(
     775        struct node_status_query_state *s)
     776{
     777        if (s->packet != NULL) {
     778                free_packet(s->packet);
     779                s->packet = NULL;
     780        }
     781        return 0;
     782}
     783
     784static void node_status_query_done(struct tevent_req *subreq)
     785{
     786        struct tevent_req *req = tevent_req_callback_data(
     787                subreq, struct tevent_req);
     788        struct node_status_query_state *state = tevent_req_data(
     789                req, struct node_status_query_state);
     790        NTSTATUS status;
     791
     792        status = nb_trans_recv(subreq, &state->packet);
     793        TALLOC_FREE(subreq);
     794        if (tevent_req_nterror(req, status)) {
     795                return;
     796        }
     797        tevent_req_done(req);
     798}
     799
     800NTSTATUS node_status_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     801                                struct node_status **pnode_status,
     802                                int *pnum_names,
     803                                struct node_status_extra *extra)
     804{
     805        struct node_status_query_state *state = tevent_req_data(
     806                req, struct node_status_query_state);
     807        struct node_status *node_status;
     808        int num_names;
     809        NTSTATUS status;
     810
     811        if (tevent_req_is_nterror(req, &status)) {
     812                return status;
     813        }
     814        node_status = parse_node_status(
     815                mem_ctx, &state->packet->packet.nmb.answers->rdata[0],
     816                &num_names, extra);
     817        if (node_status == NULL) {
     818                return NT_STATUS_NO_MEMORY;
     819        }
     820        *pnode_status = node_status;
     821        *pnum_names = num_names;
     822        return NT_STATUS_OK;
     823}
     824
     825NTSTATUS node_status_query(TALLOC_CTX *mem_ctx, struct nmb_name *name,
     826                           const struct sockaddr_storage *addr,
     827                           struct node_status **pnode_status,
     828                           int *pnum_names,
     829                           struct node_status_extra *extra)
     830{
     831        TALLOC_CTX *frame = talloc_stackframe();
     832        struct tevent_context *ev;
     833        struct tevent_req *req;
     834        NTSTATUS status = NT_STATUS_NO_MEMORY;
     835
     836        ev = tevent_context_init(frame);
     837        if (ev == NULL) {
     838                goto fail;
     839        }
     840        req = node_status_query_send(ev, ev, name, addr);
     841        if (req == NULL) {
     842                goto fail;
     843        }
     844        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     845                goto fail;
     846        }
     847        status = node_status_query_recv(req, mem_ctx, pnode_status,
     848                                        pnum_names, extra);
     849 fail:
     850        TALLOC_FREE(frame);
     851        return status;
    340852}
    341853
     
    353865        char addr[INET6_ADDRSTRLEN];
    354866        struct sockaddr_storage ss;
    355         NODE_STATUS_STRUCT *status = NULL;
     867        struct node_status *addrs = NULL;
    356868        struct nmb_name nname;
    357869        int count, i;
    358         int sock;
    359870        bool result = false;
     871        NTSTATUS status;
    360872
    361873        if (lp_disable_netbios()) {
     
    386898        }
    387899
    388         sock = open_socket_in(SOCK_DGRAM, 0, 3, &ss, True);
    389         if (sock == -1)
    390                 goto done;
    391 
    392900        /* W2K PDC's seem not to respond to '*'#0. JRA */
    393901        make_nmb_name(&nname, q_name, q_type);
    394         status = node_status_query(sock, &nname, to_ss, &count, NULL);
    395         close(sock);
    396         if (!status)
     902        status = node_status_query(talloc_tos(), &nname, to_ss,
     903                                   &addrs, &count, NULL);
     904        if (!NT_STATUS_IS_OK(status)) {
    397905                goto done;
     906        }
    398907
    399908        for (i=0;i<count;i++) {
    400909                /* Find first one of the requested type that's not a GROUP. */
    401                 if (status[i].type == type && ! (status[i].flags & 0x80))
     910                if (addrs[i].type == type && ! (addrs[i].flags & 0x80))
    402911                        break;
    403912        }
     
    405914                goto done;
    406915
    407         pull_ascii_nstring(name, sizeof(fstring), status[i].name);
     916        pull_ascii_nstring(name, sizeof(fstring), addrs[i].name);
    408917
    409918        /* Store the result in the cache. */
     
    418927
    419928 done:
    420         SAFE_FREE(status);
     929        TALLOC_FREE(addrs);
    421930
    422931        DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not "));
     
    434943*/
    435944
    436 static int addr_compare(const struct sockaddr *ss1,
    437                 const struct sockaddr *ss2)
     945static int addr_compare(const struct sockaddr_storage *ss1,
     946                        const struct sockaddr_storage *ss2)
    438947{
    439948        int max_bits1=0, max_bits2=0;
     
    442951
    443952        /* Sort IPv4 addresses first. */
    444         if (ss1->sa_family != ss2->sa_family) {
    445                 if (ss2->sa_family == AF_INET) {
     953        if (ss1->ss_family != ss2->ss_family) {
     954                if (ss2->ss_family == AF_INET) {
    446955                        return 1;
    447956                } else {
     
    461970                int bits1, bits2;
    462971
    463                 if (pss->ss_family != ss1->sa_family) {
     972                if (pss->ss_family != ss1->ss_family) {
    464973                        /* Ignore interfaces of the wrong type. */
    465974                        continue;
     
    4951004
    4961005        /* Bias towards directly reachable IPs */
    497         if (iface_local(ss1)) {
    498                 if (ss1->sa_family == AF_INET) {
     1006        if (iface_local((struct sockaddr *)ss1)) {
     1007                if (ss1->ss_family == AF_INET) {
    4991008                        max_bits1 += 32;
    5001009                } else {
     
    5021011                }
    5031012        }
    504         if (iface_local(ss2)) {
    505                 if (ss2->sa_family == AF_INET) {
     1013        if (iface_local((struct sockaddr *)ss2)) {
     1014                if (ss2->ss_family == AF_INET) {
    5061015                        max_bits2 += 32;
    5071016                } else {
     
    5201029        int result;
    5211030
    522         if ((result = addr_compare((struct sockaddr *)&ss1->ss, (struct sockaddr *)&ss2->ss)) != 0) {
     1031        if ((result = addr_compare(&ss1->ss, &ss2->ss)) != 0) {
    5231032                return result;
    5241033        }
     
    5471056        }
    5481057
    549         qsort(sslist, count, sizeof(struct sockaddr_storage),
    550                         QSORT_CAST addr_compare);
     1058        TYPESAFE_QSORT(sslist, count, addr_compare);
    5511059}
    5521060
     
    5571065        }
    5581066
    559         qsort(servlist, count, sizeof(struct ip_service),
    560                         QSORT_CAST ip_service_compare);
     1067        TYPESAFE_QSORT(servlist, count, ip_service_compare);
    5611068}
    5621069
     
    5741081        /* one loop to remove duplicates */
    5751082        for ( i=0; i<count; i++ ) {
    576                 if ( is_zero_addr((struct sockaddr *)&iplist[i].ss)) {
     1083                if ( is_zero_addr(&iplist[i].ss)) {
    5771084                        continue;
    5781085                }
     
    5891096        /* first ip should never be a zero_ip() */
    5901097        for (i = 0; i<count; ) {
    591                 if (is_zero_addr((struct sockaddr *)&iplist[i].ss) ) {
     1098                if (is_zero_addr(&iplist[i].ss) ) {
    5921099                        if (i != count-1) {
    5931100                                memmove(&iplist[i], &iplist[i+1],
     
    6421149****************************************************************************/
    6431150
    644 struct sockaddr_storage *name_query(int fd,
    645                         const char *name,
    646                         int name_type,
    647                         bool bcast,
    648                         bool recurse,
    649                         const struct sockaddr_storage *to_ss,
    650                         int *count,
    651                         int *flags,
    652                         bool *timed_out)
    653 {
    654         bool found=false;
    655         int i, retries = 3;
    656         int retry_time = bcast?250:2000;
    657         struct timeval tval;
     1151struct name_query_state {
     1152        struct sockaddr_storage my_addr;
     1153        struct sockaddr_storage addr;
     1154        bool bcast;
     1155
     1156
     1157        uint8_t buf[1024];
     1158        ssize_t buflen;
     1159
     1160        NTSTATUS validate_error;
     1161        uint8_t flags;
     1162
     1163        struct sockaddr_storage *addrs;
     1164        int num_addrs;
     1165};
     1166
     1167static bool name_query_validator(struct packet_struct *p, void *private_data);
     1168static void name_query_done(struct tevent_req *subreq);
     1169
     1170struct tevent_req *name_query_send(TALLOC_CTX *mem_ctx,
     1171                                   struct tevent_context *ev,
     1172                                   const char *name, int name_type,
     1173                                   bool bcast, bool recurse,
     1174                                   const struct sockaddr_storage *addr)
     1175{
     1176        struct tevent_req *req, *subreq;
     1177        struct name_query_state *state;
    6581178        struct packet_struct p;
    659         struct packet_struct *p2;
    6601179        struct nmb_packet *nmb = &p.packet.nmb;
    661         struct sockaddr_storage *ss_list = NULL;
     1180        struct sockaddr_in *in_addr;
     1181
     1182        req = tevent_req_create(mem_ctx, &state, struct name_query_state);
     1183        if (req == NULL) {
     1184                return NULL;
     1185        }
     1186        state->bcast = bcast;
     1187
     1188        if (addr->ss_family != AF_INET) {
     1189                /* Can't do node status to IPv6 */
     1190                tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
     1191                return tevent_req_post(req, ev);
     1192        }
    6621193
    6631194        if (lp_disable_netbios()) {
    6641195                DEBUG(5,("name_query(%s#%02x): netbios is disabled\n",
    6651196                                        name, name_type));
    666                 return NULL;
    667         }
    668 
    669         if (to_ss->ss_family != AF_INET) {
    670                 return NULL;
    671         }
    672 
    673         if (timed_out) {
    674                 *timed_out = false;
    675         }
    676 
    677         memset((char *)&p,'\0',sizeof(p));
    678         (*count) = 0;
    679         (*flags) = 0;
    680 
     1197                tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
     1198                return tevent_req_post(req, ev);
     1199        }
     1200
     1201        state->addr = *addr;
     1202        in_addr = (struct sockaddr_in *)(void *)&state->addr;
     1203        in_addr->sin_port = htons(NMB_PORT);
     1204
     1205        if (!interpret_string_addr(&state->my_addr, lp_socket_address(),
     1206                                   AI_NUMERICHOST|AI_PASSIVE)) {
     1207                zero_sockaddr(&state->my_addr);
     1208        }
     1209
     1210        ZERO_STRUCT(p);
    6811211        nmb->header.name_trn_id = generate_trn_id();
    6821212        nmb->header.opcode = 0;
     
    6981228        nmb->question.question_class = 0x1;
    6991229
    700         p.ip = ((struct sockaddr_in *)to_ss)->sin_addr;
    701         p.port = NMB_PORT;
    702         p.recv_fd = -1;
    703         p.send_fd = fd;
    704         p.timestamp = time(NULL);
    705         p.packet_type = NMB_PACKET;
    706 
    707         GetTimeOfDay(&tval);
    708 
    709         if (!send_packet(&p))
    710                 return NULL;
    711 
    712         retries--;
    713 
    714         while (1) {
    715                 struct timeval tval2;
    716 
    717                 GetTimeOfDay(&tval2);
    718                 if (TvalDiff(&tval,&tval2) > retry_time) {
    719                         if (!retries)
     1230        state->buflen = build_packet((char *)state->buf, sizeof(state->buf),
     1231                                     &p);
     1232        if (state->buflen == 0) {
     1233                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     1234                DEBUG(10, ("build_packet failed\n"));
     1235                return tevent_req_post(req, ev);
     1236        }
     1237
     1238        subreq = nb_trans_send(state, ev, &state->my_addr, &state->addr, bcast,
     1239                               state->buf, state->buflen,
     1240                               NMB_PACKET, nmb->header.name_trn_id,
     1241                               name_query_validator, state);
     1242        if (tevent_req_nomem(subreq, req)) {
     1243                DEBUG(10, ("nb_trans_send failed\n"));
     1244                return tevent_req_post(req, ev);
     1245        }
     1246        tevent_req_set_callback(subreq, name_query_done, req);
     1247        return req;
     1248}
     1249
     1250static bool name_query_validator(struct packet_struct *p, void *private_data)
     1251{
     1252        struct name_query_state *state = talloc_get_type_abort(
     1253                private_data, struct name_query_state);
     1254        struct nmb_packet *nmb = &p->packet.nmb;
     1255        struct sockaddr_storage *tmp_addrs;
     1256        bool got_unique_netbios_name = false;
     1257        int i;
     1258
     1259        debug_nmb_packet(p);
     1260
     1261        /*
     1262         * If we get a Negative Name Query Response from a WINS
     1263         * server, we should report it and give up.
     1264         */
     1265        if( 0 == nmb->header.opcode     /* A query response   */
     1266            && !state->bcast            /* from a WINS server */
     1267            && nmb->header.rcode        /* Error returned     */
     1268                ) {
     1269
     1270                if( DEBUGLVL( 3 ) ) {
     1271                        /* Only executed if DEBUGLEVEL >= 3 */
     1272                        dbgtext( "Negative name query "
     1273                                 "response, rcode 0x%02x: ",
     1274                                 nmb->header.rcode );
     1275                        switch( nmb->header.rcode ) {
     1276                        case 0x01:
     1277                                dbgtext("Request was invalidly formatted.\n");
    7201278                                break;
    721                         if (!found && !send_packet(&p))
    722                                 return NULL;
    723                         GetTimeOfDay(&tval);
    724                         retries--;
    725                 }
    726 
    727                 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
    728                         struct nmb_packet *nmb2 = &p2->packet.nmb;
    729                         debug_nmb_packet(p2);
    730 
    731                         /* If we get a Negative Name Query Response from a WINS
    732                          * server, we should report it and give up.
    733                          */
    734                         if( 0 == nmb2->header.opcode    /* A query response   */
    735                             && !(bcast)                 /* from a WINS server */
    736                             && nmb2->header.rcode       /* Error returned     */
    737                                 ) {
    738 
    739                                 if( DEBUGLVL( 3 ) ) {
    740                                         /* Only executed if DEBUGLEVEL >= 3 */
    741                                         dbgtext( "Negative name query "
    742                                                 "response, rcode 0x%02x: ",
    743                                                 nmb2->header.rcode );
    744                                         switch( nmb2->header.rcode ) {
    745                                         case 0x01:
    746                                                 dbgtext( "Request "
    747                                                 "was invalidly formatted.\n" );
    748                                                 break;
    749                                         case 0x02:
    750                                                 dbgtext( "Problem with NBNS, "
    751                                                 "cannot process name.\n");
    752                                                 break;
    753                                         case 0x03:
    754                                                 dbgtext( "The name requested "
    755                                                 "does not exist.\n" );
    756                                                 break;
    757                                         case 0x04:
    758                                                 dbgtext( "Unsupported request "
    759                                                 "error.\n" );
    760                                                 break;
    761                                         case 0x05:
    762                                                 dbgtext( "Query refused "
    763                                                 "error.\n" );
    764                                                 break;
    765                                         default:
    766                                                 dbgtext( "Unrecognized error "
    767                                                 "code.\n" );
    768                                                 break;
    769                                         }
    770                                 }
    771                                 free_packet(p2);
    772                                 return( NULL );
     1279                        case 0x02:
     1280                                dbgtext("Problem with NBNS, cannot process "
     1281                                        "name.\n");
     1282                                break;
     1283                        case 0x03:
     1284                                dbgtext("The name requested does not "
     1285                                        "exist.\n");
     1286                                break;
     1287                        case 0x04:
     1288                                dbgtext("Unsupported request error.\n");
     1289                                break;
     1290                        case 0x05:
     1291                                dbgtext("Query refused error.\n");
     1292                                break;
     1293                        default:
     1294                                dbgtext("Unrecognized error code.\n" );
     1295                                break;
    7731296                        }
    774 
    775                         if (nmb2->header.opcode != 0 ||
    776                             nmb2->header.nm_flags.bcast ||
    777                             nmb2->header.rcode ||
    778                             !nmb2->header.ancount) {
    779                                 /*
    780                                  * XXXX what do we do with this? Could be a
    781                                  * redirect, but we'll discard it for the
    782                                  * moment.
    783                                  */
    784                                 free_packet(p2);
    785                                 continue;
     1297                }
     1298
     1299                /*
     1300                 * We accept this packet as valid, but tell the upper
     1301                 * layers that it's a negative response.
     1302                 */
     1303                state->validate_error = NT_STATUS_NOT_FOUND;
     1304                return true;
     1305        }
     1306
     1307        if (nmb->header.opcode != 0 ||
     1308            nmb->header.nm_flags.bcast ||
     1309            nmb->header.rcode ||
     1310            !nmb->header.ancount) {
     1311                /*
     1312                 * XXXX what do we do with this? Could be a redirect,
     1313                 * but we'll discard it for the moment.
     1314                 */
     1315                return false;
     1316        }
     1317
     1318        tmp_addrs = TALLOC_REALLOC_ARRAY(
     1319                state, state->addrs, struct sockaddr_storage,
     1320                state->num_addrs + nmb->answers->rdlength/6);
     1321        if (tmp_addrs == NULL) {
     1322                state->validate_error = NT_STATUS_NO_MEMORY;
     1323                return true;
     1324        }
     1325        state->addrs = tmp_addrs;
     1326
     1327        DEBUG(2,("Got a positive name query response "
     1328                 "from %s ( ", inet_ntoa(p->ip)));
     1329
     1330        for (i=0; i<nmb->answers->rdlength/6; i++) {
     1331                uint16_t flags;
     1332                struct in_addr ip;
     1333                struct sockaddr_storage addr;
     1334                int j;
     1335
     1336                flags = RSVAL(&nmb->answers->rdata[i*6], 0);
     1337                got_unique_netbios_name |= ((flags & 0x8000) == 0);
     1338
     1339                putip((char *)&ip,&nmb->answers->rdata[2+i*6]);
     1340                in_addr_to_sockaddr_storage(&addr, ip);
     1341
     1342                for (j=0; j<state->num_addrs; j++) {
     1343                        if (sockaddr_equal(
     1344                                    (struct sockaddr *)&addr,
     1345                                    (struct sockaddr *)&state->addrs[j])) {
     1346                                break;
    7861347                        }
    787 
    788                         ss_list = SMB_REALLOC_ARRAY(ss_list,
    789                                                 struct sockaddr_storage,
    790                                                 (*count) +
    791                                                 nmb2->answers->rdlength/6);
    792 
    793                         if (!ss_list) {
    794                                 DEBUG(0,("name_query: Realloc failed.\n"));
    795                                 free_packet(p2);
    796                                 return NULL;
    797                         }
    798 
    799                         DEBUG(2,("Got a positive name query response "
    800                                         "from %s ( ",
    801                                         inet_ntoa(p2->ip)));
    802 
    803                         for (i=0;i<nmb2->answers->rdlength/6;i++) {
    804                                 struct in_addr ip;
    805                                 putip((char *)&ip,&nmb2->answers->rdata[2+i*6]);
    806                                 in_addr_to_sockaddr_storage(&ss_list[(*count)],
    807                                                 ip);
    808                                 DEBUGADD(2,("%s ",inet_ntoa(ip)));
    809                                 (*count)++;
    810                         }
    811                         DEBUGADD(2,(")\n"));
    812 
    813                         found=true;
    814                         retries=0;
    815                         /* We add the flags back ... */
    816                         if (nmb2->header.response)
    817                                 (*flags) |= NM_FLAGS_RS;
    818                         if (nmb2->header.nm_flags.authoritative)
    819                                 (*flags) |= NM_FLAGS_AA;
    820                         if (nmb2->header.nm_flags.trunc)
    821                                 (*flags) |= NM_FLAGS_TC;
    822                         if (nmb2->header.nm_flags.recursion_desired)
    823                                 (*flags) |= NM_FLAGS_RD;
    824                         if (nmb2->header.nm_flags.recursion_available)
    825                                 (*flags) |= NM_FLAGS_RA;
    826                         if (nmb2->header.nm_flags.bcast)
    827                                 (*flags) |= NM_FLAGS_B;
    828                         free_packet(p2);
    829                         /*
    830                          * If we're doing a unicast lookup we only
    831                          * expect one reply. Don't wait the full 2
    832                          * seconds if we got one. JRA.
    833                          */
    834                         if(!bcast && found)
    835                                 break;
    836                 }
    837         }
    838 
    839         /* only set timed_out if we didn't fund what we where looking for*/
    840 
    841         if ( !found && timed_out ) {
    842                 *timed_out = true;
    843         }
    844 
    845         /* sort the ip list so we choose close servers first if possible */
    846         sort_addr_list(ss_list, *count);
    847 
    848         return ss_list;
     1348                }
     1349                if (j < state->num_addrs) {
     1350                        /* Already got it */
     1351                        continue;
     1352                }
     1353
     1354                DEBUGADD(2,("%s ",inet_ntoa(ip)));
     1355
     1356                state->addrs[state->num_addrs] = addr;
     1357                state->num_addrs += 1;
     1358        }
     1359        DEBUGADD(2,(")\n"));
     1360
     1361        /* We add the flags back ... */
     1362        if (nmb->header.response)
     1363                state->flags |= NM_FLAGS_RS;
     1364        if (nmb->header.nm_flags.authoritative)
     1365                state->flags |= NM_FLAGS_AA;
     1366        if (nmb->header.nm_flags.trunc)
     1367                state->flags |= NM_FLAGS_TC;
     1368        if (nmb->header.nm_flags.recursion_desired)
     1369                state->flags |= NM_FLAGS_RD;
     1370        if (nmb->header.nm_flags.recursion_available)
     1371                state->flags |= NM_FLAGS_RA;
     1372        if (nmb->header.nm_flags.bcast)
     1373                state->flags |= NM_FLAGS_B;
     1374
     1375        if (state->bcast) {
     1376                /*
     1377                 * We have to collect all entries coming in from broadcast
     1378                 * queries. If we got a unique name, we're done.
     1379                 */
     1380                return got_unique_netbios_name;
     1381        }
     1382        /*
     1383         * WINS responses are accepted when they are received
     1384         */
     1385        return true;
     1386}
     1387
     1388static void name_query_done(struct tevent_req *subreq)
     1389{
     1390        struct tevent_req *req = tevent_req_callback_data(
     1391                subreq, struct tevent_req);
     1392        struct name_query_state *state = tevent_req_data(
     1393                req, struct name_query_state);
     1394        NTSTATUS status;
     1395        struct packet_struct *p = NULL;
     1396
     1397        status = nb_trans_recv(subreq, &p);
     1398        TALLOC_FREE(subreq);
     1399        if (tevent_req_nterror(req, status)) {
     1400                return;
     1401        }
     1402        if (!NT_STATUS_IS_OK(state->validate_error)) {
     1403                tevent_req_nterror(req, state->validate_error);
     1404                return;
     1405        }
     1406        if (p != NULL) {
     1407                /*
     1408                 * Free the packet here, we've collected the response in the
     1409                 * validator
     1410                 */
     1411                free_packet(p);
     1412        }
     1413        tevent_req_done(req);
     1414}
     1415
     1416NTSTATUS name_query_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     1417                         struct sockaddr_storage **addrs, int *num_addrs,
     1418                         uint8_t *flags)
     1419{
     1420        struct name_query_state *state = tevent_req_data(
     1421                req, struct name_query_state);
     1422        NTSTATUS status;
     1423
     1424        if (tevent_req_is_nterror(req, &status)
     1425            && !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
     1426                return status;
     1427        }
     1428        if (state->num_addrs == 0) {
     1429                return NT_STATUS_NOT_FOUND;
     1430        }
     1431        *addrs = talloc_move(mem_ctx, &state->addrs);
     1432        sort_addr_list(*addrs, state->num_addrs);
     1433        *num_addrs = state->num_addrs;
     1434        if (flags != NULL) {
     1435                *flags = state->flags;
     1436        }
     1437        return NT_STATUS_OK;
     1438}
     1439
     1440NTSTATUS name_query(const char *name, int name_type,
     1441                    bool bcast, bool recurse,
     1442                    const struct sockaddr_storage *to_ss,
     1443                    TALLOC_CTX *mem_ctx,
     1444                    struct sockaddr_storage **addrs,
     1445                    int *num_addrs, uint8_t *flags)
     1446{
     1447        TALLOC_CTX *frame = talloc_stackframe();
     1448        struct tevent_context *ev;
     1449        struct tevent_req *req;
     1450        struct timeval timeout;
     1451        NTSTATUS status = NT_STATUS_NO_MEMORY;
     1452
     1453        ev = tevent_context_init(frame);
     1454        if (ev == NULL) {
     1455                goto fail;
     1456        }
     1457        req = name_query_send(ev, ev, name, name_type, bcast, recurse, to_ss);
     1458        if (req == NULL) {
     1459                goto fail;
     1460        }
     1461        if (bcast) {
     1462                timeout = timeval_current_ofs(0, 250000);
     1463        } else {
     1464                timeout = timeval_current_ofs(2, 0);
     1465        }
     1466        if (!tevent_req_set_endtime(req, ev, timeout)) {
     1467                goto fail;
     1468        }
     1469        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     1470                goto fail;
     1471        }
     1472        status = name_query_recv(req, mem_ctx, addrs, num_addrs, flags);
     1473 fail:
     1474        TALLOC_FREE(frame);
     1475        return status;
    8491476}
    8501477
     
    8851512NTSTATUS name_resolve_bcast(const char *name,
    8861513                        int name_type,
    887                         struct ip_service **return_iplist,
     1514                        TALLOC_CTX *mem_ctx,
     1515                        struct sockaddr_storage **return_iplist,
    8881516                        int *return_count)
    8891517{
    890         int sock, i;
     1518        int i;
    8911519        int num_interfaces = iface_count();
    8921520        struct sockaddr_storage *ss_list;
    893         struct sockaddr_storage ss;
    894         NTSTATUS status;
     1521        NTSTATUS status = NT_STATUS_NOT_FOUND;
    8951522
    8961523        if (lp_disable_netbios()) {
     
    9101537                "for name %s<0x%x>\n", name, name_type));
    9111538
    912         if (!interpret_string_addr(&ss, lp_socket_address(),
    913                                 AI_NUMERICHOST|AI_PASSIVE)) {
    914                 zero_sockaddr(&ss);
    915         }
    916 
    917         sock = open_socket_in( SOCK_DGRAM, 0, 3, &ss, true );
    918         if (sock == -1) {
    919                 return NT_STATUS_UNSUCCESSFUL;
    920         }
    921 
    922         set_socket_options(sock,"SO_BROADCAST");
    9231539        /*
    9241540         * Lookup the name on all the interfaces, return on
     
    9271543        for( i = num_interfaces-1; i >= 0; i--) {
    9281544                const struct sockaddr_storage *pss = iface_n_bcast(i);
    929                 int flags;
    9301545
    9311546                /* Done this way to fix compiler error on IRIX 5.x */
     
    9331548                        continue;
    9341549                }
    935                 ss_list = name_query(sock, name, name_type, true,
    936                                     true, pss, return_count, &flags, NULL);
    937                 if (ss_list) {
     1550                status = name_query(name, name_type, true, true, pss,
     1551                                    talloc_tos(), &ss_list, return_count,
     1552                                    NULL);
     1553                if (NT_STATUS_IS_OK(status)) {
    9381554                        goto success;
    9391555                }
     
    9421558        /* failed - no response */
    9431559
    944         close(sock);
    945         return NT_STATUS_UNSUCCESSFUL;
     1560        return status;
    9461561
    9471562success:
    948 
    949         status = NT_STATUS_OK;
    950         if (!convert_ss2service(return_iplist, ss_list, *return_count) )
    951                 status = NT_STATUS_INVALID_PARAMETER;
    952 
    953         SAFE_FREE(ss_list);
    954         close(sock);
     1563        *return_iplist = ss_list;
    9551564        return status;
    9561565}
     
    9651574                int *return_count)
    9661575{
    967         int sock, t, i;
     1576        int t, i;
    9681577        char **wins_tags;
    9691578        struct sockaddr_storage src_ss, *ss_list = NULL;
     
    10221631                        struct sockaddr_storage wins_ss;
    10231632                        struct in_addr wins_ip;
    1024                         int flags;
    1025                         bool timed_out;
    10261633
    10271634                        wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
     
    10411648                                inet_ntoa(wins_ip), wins_tags[t]));
    10421649
    1043                         sock = open_socket_in(SOCK_DGRAM, 0, 3, &src_ss, true);
    1044                         if (sock == -1) {
    1045                                 continue;
    1046                         }
    1047 
    10481650                        in_addr_to_sockaddr_storage(&wins_ss, wins_ip);
    1049                         ss_list = name_query(sock,
    1050                                                 name,
     1651                        status = name_query(name,
    10511652                                                name_type,
    10521653                                                false,
    10531654                                                true,
    10541655                                                &wins_ss,
     1656                                                talloc_tos(),
     1657                                                &ss_list,
    10551658                                                return_count,
    1056                                                 &flags,
    1057                                                 &timed_out);
     1659                                                NULL);
    10581660
    10591661                        /* exit loop if we got a list of addresses */
    10601662
    1061                         if (ss_list)
     1663                        if (NT_STATUS_IS_OK(status)) {
    10621664                                goto success;
    1063 
    1064                         close(sock);
    1065 
    1066                         if (timed_out) {
    1067                                 /* Timed out wating for WINS server to respond.
     1665                        }
     1666
     1667                        if (NT_STATUS_EQUAL(status,
     1668                                            NT_STATUS_IO_TIMEOUT)) {
     1669                                /* Timed out waiting for WINS server to
     1670                                 * respond.
    10681671                                 * Mark it dead. */
    10691672                                wins_srv_died(wins_ip, src_ip);
    10701673                        } else {
    1071                                 /* The name definately isn't in this
     1674                                /* The name definitely isn't in this
    10721675                                   group of WINS servers.
    10731676                                   goto the next group  */
     
    10861689                status = NT_STATUS_INVALID_PARAMETER;
    10871690
    1088         SAFE_FREE(ss_list);
     1691        TALLOC_FREE(ss_list);
    10891692        wins_srv_tags_free(wins_tags);
    1090         close(sock);
    10911693
    10921694        return status;
     
    11041706         * "lmhosts" means parse the local lmhosts file.
    11051707         */
    1106 
    1107         XFILE *fp;
    1108         char *lmhost_name = NULL;
    1109         int name_type2;
    1110         struct sockaddr_storage return_ss;
     1708        struct sockaddr_storage *ss_list;
    11111709        NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
    11121710        TALLOC_CTX *ctx = NULL;
     
    11191717                name, name_type));
    11201718
    1121         fp = startlmhosts(get_dyn_LMHOSTSFILE());
    1122 
    1123         if ( fp == NULL )
    1124                 return NT_STATUS_NO_SUCH_FILE;
    1125 
    11261719        ctx = talloc_init("resolve_lmhosts");
    11271720        if (!ctx) {
    1128                 endlmhosts(fp);
    11291721                return NT_STATUS_NO_MEMORY;
    11301722        }
    11311723
    1132         while (getlmhostsent(ctx, fp, &lmhost_name, &name_type2, &return_ss)) {
    1133 
    1134                 if (!strequal(name, lmhost_name)) {
    1135                         TALLOC_FREE(lmhost_name);
    1136                         continue;
    1137                 }
    1138 
    1139                 if ((name_type2 != -1) && (name_type != name_type2)) {
    1140                         TALLOC_FREE(lmhost_name);
    1141                         continue;
    1142                 }
    1143 
    1144                 *return_iplist = SMB_REALLOC_ARRAY((*return_iplist),
    1145                                         struct ip_service,
    1146                                         (*return_count)+1);
    1147 
    1148                 if ((*return_iplist) == NULL) {
    1149                         TALLOC_FREE(ctx);
    1150                         endlmhosts(fp);
    1151                         DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
     1724        status = resolve_lmhosts_file_as_sockaddr(get_dyn_LMHOSTSFILE(),
     1725                                                  name, name_type,
     1726                                                  ctx,
     1727                                                  &ss_list,
     1728                                                  return_count);
     1729        if (NT_STATUS_IS_OK(status)) {
     1730                if (convert_ss2service(return_iplist,
     1731                                       ss_list,
     1732                                       *return_count)) {
     1733                        talloc_free(ctx);
     1734                        return NT_STATUS_OK;
     1735                } else {
     1736                        talloc_free(ctx);
    11521737                        return NT_STATUS_NO_MEMORY;
    11531738                }
    1154 
    1155                 (*return_iplist)[*return_count].ss = return_ss;
    1156                 (*return_iplist)[*return_count].port = PORT_NONE;
    1157                 *return_count += 1;
    1158 
    1159                 /* we found something */
    1160                 status = NT_STATUS_OK;
    1161 
    1162                 /* Multiple names only for DC lookup */
    1163                 if (name_type != 0x1c)
    1164                         break;
    1165         }
    1166 
    1167         TALLOC_FREE(ctx);
    1168         endlmhosts(fp);
     1739        }
     1740        talloc_free(ctx);
    11691741        return status;
    11701742}
     
    12571829 Resolve via "ADS" method.
    12581830*********************************************************/
     1831
     1832/* Special name type used to cause a _kerberos DNS lookup. */
     1833#define KDC_NAME_TYPE 0xDCDC
    12591834
    12601835static NTSTATUS resolve_ads(const char *name,
     
    13611936                 * doesn't know anything about the DC's   -- jerry */
    13621937
    1363                 if (!is_zero_addr((struct sockaddr *)&r->ss)) {
     1938                if (!is_zero_addr(&r->ss)) {
    13641939                        (*return_count)++;
    13651940                }
     
    14932068                        }
    14942069                } else if(strequal( tok, "bcast")) {
    1495                         status = name_resolve_bcast(name, name_type,
    1496                                                     return_iplist,
    1497                                                     return_count);
     2070                        struct sockaddr_storage *ss_list;
     2071                        status = name_resolve_bcast(
     2072                                name, name_type, talloc_tos(),
     2073                                &ss_list, return_count);
    14982074                        if (NT_STATUS_IS_OK(status)) {
     2075                                if (!convert_ss2service(return_iplist,
     2076                                                        ss_list,
     2077                                                        *return_count)) {
     2078                                        status = NT_STATUS_NO_MEMORY;
     2079                                }
    14992080                                goto done;
    15002081                        }
     
    15912172                if (prefer_ipv4) {
    15922173                        for (i=0; i<count; i++) {
    1593                                 if (!is_zero_addr((struct sockaddr *)&ss_list[i].ss) &&
     2174                                if (!is_zero_addr(&ss_list[i].ss) &&
    15942175                                                !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss) &&
    15952176                                                (ss_list[i].ss.ss_family == AF_INET)) {
     
    16042185                /* only return valid addresses for TCP connections */
    16052186                for (i=0; i<count; i++) {
    1606                         if (!is_zero_addr((struct sockaddr *)&ss_list[i].ss) &&
     2187                        if (!is_zero_addr(&ss_list[i].ss) &&
    16072188                                        !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
    16082189                                *return_ss = ss_list[i].ss;
     
    16682249        /* only return valid addresses for TCP connections */
    16692250        for (i=0, num_entries = 0; i<count; i++) {
    1670                 if (!is_zero_addr((struct sockaddr *)&ss_list[i].ss) &&
     2251                if (!is_zero_addr(&ss_list[i].ss) &&
    16712252                                !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
    16722253                        num_entries++;
     
    16872268
    16882269        for (i=0, num_entries = 0; i<count; i++) {
    1689                 if (!is_zero_addr((struct sockaddr *)&ss_list[i].ss) &&
     2270                if (!is_zero_addr(&ss_list[i].ss) &&
    16902271                                !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss)) {
    16912272                        (*return_ss_arr)[num_entries++] = ss_list[i].ss;
     
    18552436
    18562437        if (strequal(domain, lp_workgroup()) || strequal(domain, lp_realm())) {
    1857                 pserver = talloc_asprintf(NULL, "%s, %s",
     2438                pserver = talloc_asprintf(ctx, "%s, %s",
    18582439                        saf_servername ? saf_servername : "",
    18592440                        lp_passwordserver());
    18602441        } else {
    1861                 pserver = talloc_asprintf(NULL, "%s, *",
     2442                pserver = talloc_asprintf(ctx, "%s, *",
    18622443                        saf_servername ? saf_servername : "");
    18632444        }
  • vendor/current/source3/libsmb/namequery_dc.c

    r478 r740  
    77   Copyright (C) Andrew Bartlett 2002
    88   Copyright (C) Gerald Carter 2003
    9    
     9
    1010   This program is free software; you can redistribute it and/or modify
    1111   it under the terms of the GNU General Public License as published by
    1212   the Free Software Foundation; either version 3 of the License, or
    1313   (at your option) any later version.
    14    
     14
    1515   This program is distributed in the hope that it will be useful,
    1616   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1717   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1818   GNU General Public License for more details.
    19    
     19
    2020   You should have received a copy of the GNU General Public License
    2121   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2424
    2525#include "includes.h"
     26#include "libads/sitename_cache.h"
     27#include "ads.h"
     28#include "../librpc/gen_ndr/nbt.h"
    2629
    2730/**********************************************************************
     
    4649 Find the name and IP address for a server in the realm/domain
    4750 *************************************************************************/
    48  
     51
    4952static bool ads_dc_name(const char *domain,
    5053                        const char *realm,
     
    99102                }
    100103
    101 #ifdef HAVE_KRB5
     104#ifdef HAVE_ADS
    102105                if (is_our_primary_domain(domain) && (ads->config.flags & NBT_SERVER_KDC)) {
    103106                        if (ads_closest_dc(ads)) {
     
    174177
    175178        for (i = 0; i < count; i++) {
    176                 if (is_zero_addr((struct sockaddr *)&ip_list[i].ss))
     179                if (is_zero_addr(&ip_list[i].ss))
    177180                        continue;
    178181
  • vendor/current/source3/libsmb/nmblib.c

    r594 r740  
    2121
    2222#include "includes.h"
     23#include "libsmb/nmblib.h"
    2324
    2425static const struct opcode_names {
     
    726727}
    727728
     729int packet_trn_id(struct packet_struct *p)
     730{
     731        int result;
     732        switch (p->packet_type) {
     733        case NMB_PACKET:
     734                result = p->packet.nmb.header.name_trn_id;
     735                break;
     736        case DGRAM_PACKET:
     737                result = p->packet.dgram.header.dgm_id;
     738                break;
     739        default:
     740                result = -1;
     741        }
     742        return result;
     743}
     744
    728745/*******************************************************************
    729746 Parse a packet buffer into a packet structure.
     
    10851102
    10861103/****************************************************************************
    1087  Receive a packet with timeout on a open UDP filedescriptor.
    1088  The timeout is in milliseconds
    1089 ***************************************************************************/
    1090 
    1091 struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
    1092 {
    1093         fd_set fds;
    1094         struct timeval timeout;
    1095         int ret;
    1096 
    1097         if (fd < 0 || fd >= FD_SETSIZE) {
    1098                 errno = EBADF;
    1099                 return NULL;
    1100         }
    1101 
    1102         FD_ZERO(&fds);
    1103         FD_SET(fd,&fds);
    1104         timeout.tv_sec = t/1000;
    1105         timeout.tv_usec = 1000*(t%1000);
    1106 
    1107         if ((ret = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout)) == -1) {
    1108                 /* errno should be EBADF or EINVAL. */
    1109                 DEBUG(0,("select returned -1, errno = %s (%d)\n",
    1110                                         strerror(errno), errno));
    1111                 return NULL;
    1112         }
    1113 
    1114         if (ret == 0) /* timeout */
    1115                 return NULL;
    1116 
    1117         if (FD_ISSET(fd,&fds))
    1118                 return(read_packet(fd,type));
    1119 
    1120         return(NULL);
    1121 }
    1122 
    1123 /****************************************************************************
    1124  Receive a UDP/137 packet either via UDP or from the unexpected packet
    1125  queue. The packet must be a reply packet and have the specified trn_id.
    1126  The timeout is in milliseconds.
    1127 ***************************************************************************/
    1128 
    1129 struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
    1130 {
    1131         struct packet_struct *p;
    1132 
    1133         p = receive_packet(fd, NMB_PACKET, t);
    1134 
    1135         if (p && p->packet.nmb.header.response &&
    1136                         p->packet.nmb.header.name_trn_id == trn_id) {
    1137                 return p;
    1138         }
    1139         if (p)
    1140                 free_packet(p);
    1141 
    1142         /* try the unexpected packet queue */
    1143         return receive_unexpected(NMB_PACKET, trn_id, NULL);
    1144 }
    1145 
    1146 /****************************************************************************
    11471104 Receive a UDP/138 packet either via UDP or from the unexpected packet
    11481105 queue. The packet must be a reply packet and have the specified mailslot name
    11491106 The timeout is in milliseconds.
    11501107***************************************************************************/
    1151 
    1152 struct packet_struct *receive_dgram_packet(int fd, int t,
    1153                 const char *mailslot_name)
    1154 {
    1155         struct packet_struct *p;
    1156 
    1157         p = receive_packet(fd, DGRAM_PACKET, t);
    1158 
    1159         if (p && match_mailslot_name(p, mailslot_name)) {
    1160                 return p;
    1161         }
    1162         if (p)
    1163                 free_packet(p);
    1164 
    1165         /* try the unexpected packet queue */
    1166         return receive_unexpected(DGRAM_PACKET, 0, mailslot_name);
    1167 }
    11681108
    11691109/****************************************************************************
     
    12381178        putip(sort_ip, (char *)&ip);
    12391179
     1180        /* TODO:
     1181           this can't use TYPESAFE_QSORT() as the types are wrong.
     1182           It should be fixed to use a real type instead of char*
     1183        */
    12401184        qsort(data, n, 6, QSORT_CAST name_query_comp);
    12411185}
  • vendor/current/source3/libsmb/nterr.c

    r414 r740  
    1 /* 
     1/*
    22 *  Unix SMB/CIFS implementation.
    33 *  RPC Pipe client / server routines
    44 *  Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
    5  * 
     5 *
    66 *  This program is free software; you can redistribute it and/or modify
    77 *  it under the terms of the GNU General Public License as published by
    88 *  the Free Software Foundation; either version 3 of the License, or
    99 *  (at your option) any later version.
    10  * 
     10 *
    1111 *  This program is distributed in the hope that it will be useful,
    1212 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1313 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1414 *  GNU General Public License for more details.
    15  * 
     15 *
    1616 *  You should have received a copy of the GNU General Public License
    1717 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
     
    2121
    2222#include "includes.h"
     23#include "smb_ldap.h"
     24#undef strcasecmp
     25
     26#if !defined(N_)
     27#define N_(string) string
     28#endif
    2329
    2430typedef struct
     
    3137{
    3238        { "NT_STATUS_OK", NT_STATUS_OK },
     39        { "STATUS_NO_MORE_FILES", STATUS_NO_MORE_FILES },
     40        { "STATUS_NO_MORE_EAS", STATUS_NO_MORE_EAS },
     41        { "STATUS_INVALID_EA_NAME", STATUS_INVALID_EA_NAME },
     42        { "STATUS_EA_LIST_INCONSISTENT", STATUS_EA_LIST_INCONSISTENT },
     43        { "STATUS_INVALID_EA_FLAG", STATUS_INVALID_EA_FLAG },
    3344        { "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL },
    3445        { "NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED },
     
    535546        { "NT_STATUS_DS_NO_MORE_RIDS", NT_STATUS_DS_NO_MORE_RIDS },
    536547        { "NT_STATUS_NOT_A_REPARSE_POINT", NT_STATUS_NOT_A_REPARSE_POINT },
     548        { "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES },
     549        { "NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED", NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED },
     550        { "NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX", NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX },
     551        { "NT_STATUS_RPC_UNKNOWN_IF", NT_STATUS_RPC_UNKNOWN_IF },
     552        { "NT_STATUS_RPC_CALL_FAILED", NT_STATUS_RPC_CALL_FAILED },
     553        { "NT_STATUS_RPC_PROTOCOL_ERROR", NT_STATUS_RPC_PROTOCOL_ERROR },
     554        { "NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE", NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE },
     555        { "NT_STATUS_RPC_CANNOT_SUPPORT", NT_STATUS_RPC_CANNOT_SUPPORT },
     556        { "NT_STATUS_RPC_SEC_PKG_ERROR", NT_STATUS_RPC_SEC_PKG_ERROR },
     557        { "NT_STATUS_RPC_SS_CONTEXT_MISMATCH", NT_STATUS_RPC_SS_CONTEXT_MISMATCH },
     558        { "NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE", NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE },
     559        { "NT_STATUS_RPC_BAD_STUB_DATA", NT_STATUS_RPC_BAD_STUB_DATA },
     560        { "NT_STATUS_RPC_INVALID_PIPE_OBJECT", NT_STATUS_RPC_INVALID_PIPE_OBJECT },
     561        { "NT_STATUS_RPC_INVALID_PIPE_OPERATION", NT_STATUS_RPC_INVALID_PIPE_OPERATION },
     562        { "NT_STATUS_RPC_WRONG_PIPE_VERSION", NT_STATUS_RPC_WRONG_PIPE_VERSION },
     563        { "NT_STATUS_RPC_PIPE_CLOSED", NT_STATUS_RPC_PIPE_CLOSED },
     564        { "NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR", NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR },
     565        { "NT_STATUS_RPC_PIPE_EMPTY", NT_STATUS_RPC_PIPE_EMPTY },
     566        { "NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED", NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED },
     567        { "NT_STATUS_OBJECTID_NOT_FOUND", NT_STATUS_OBJECTID_NOT_FOUND },
    537568        { "NT_STATUS_DOWNGRADE_DETECTED", NT_STATUS_DOWNGRADE_DETECTED },
    538         { "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES },
     569        { "NT_STATUS_NO_S4U_PROT_SUPPORT", NT_STATUS_NO_S4U_PROT_SUPPORT },
     570        { "NT_STATUS_CROSSREALM_DELEGATION_FAILURE", NT_STATUS_CROSSREALM_DELEGATION_FAILURE },
     571        { "NT_STATUS_INVALID_LOCK_RANGE", NT_STATUS_INVALID_LOCK_RANGE },
     572        { "NT_STATUS_ERROR_DS_OBJ_STRING_NAME_EXISTS", NT_STATUS_ERROR_DS_OBJ_STRING_NAME_EXISTS },
     573        { "NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION", NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION },
    539574        { "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES },
    540575        { "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED },
    541         { "STATUS_NO_MORE_FILES", STATUS_NO_MORE_FILES },
    542         { "NT_STATUS_RPC_CANNOT_SUPPORT", NT_STATUS_RPC_CANNOT_SUPPORT },
    543         { "NT_STATUS_RPC_NT_CALL_FAILED", NT_STATUS_RPC_NT_CALL_FAILED },
    544         { "NT_STATUS_RPC_NT_PROTOCOL_ERROR", NT_STATUS_RPC_NT_PROTOCOL_ERROR },
    545         { "NT_STATUS_RPC_NT_PROCNUM_OUT_OF_RANGE", NT_STATUS_RPC_NT_PROCNUM_OUT_OF_RANGE },
    546         { "NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED", NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED },
     576        { "STATUS_NOTIFY_CLEANUP", STATUS_NOTIFY_CLEANUP },
     577        { "STATUS_NOTIFY_ENUM_DIR", STATUS_NOTIFY_ENUM_DIR },
     578
    547579        { NULL, NT_STATUS(0) }
    548580};
     
    550582/* These need sorting..... */
    551583
    552 nt_err_code_struct nt_err_desc[] =
     584static const nt_err_code_struct nt_err_desc[] =
    553585{
    554         { "Success",                            NT_STATUS_OK },
    555         { "Undetermined error",                 NT_STATUS_UNSUCCESSFUL },
    556         { "Access denied",                      NT_STATUS_ACCESS_DENIED },
    557         { "Account locked out",                 NT_STATUS_ACCOUNT_LOCKED_OUT },
    558         { "Must change password",               NT_STATUS_PASSWORD_MUST_CHANGE },
    559         { "Password is too short",              NT_STATUS_PWD_TOO_SHORT },
    560         { "Password is too recent",             NT_STATUS_PWD_TOO_RECENT },
    561         { "Password history conflict",          NT_STATUS_PWD_HISTORY_CONFLICT },
    562         { "No logon servers",                   NT_STATUS_NO_LOGON_SERVERS },
    563         { "Improperly formed account name",     NT_STATUS_INVALID_ACCOUNT_NAME },
    564         { "User exists",                        NT_STATUS_USER_EXISTS },
    565         { "No such user",                       NT_STATUS_NO_SUCH_USER },
    566         { "Group exists",                       NT_STATUS_GROUP_EXISTS },
    567         { "No such group",                      NT_STATUS_NO_SUCH_GROUP },
    568         { "Member not in group",                NT_STATUS_MEMBER_NOT_IN_GROUP },
    569         { "Wrong Password",                     NT_STATUS_WRONG_PASSWORD },
    570         { "Ill formed password",                NT_STATUS_ILL_FORMED_PASSWORD },
    571         { "Password restriction",               NT_STATUS_PASSWORD_RESTRICTION },
    572         { "Logon failure",                      NT_STATUS_LOGON_FAILURE },
    573         { "Account restriction",                NT_STATUS_ACCOUNT_RESTRICTION },
    574         { "Invalid logon hours",                NT_STATUS_INVALID_LOGON_HOURS },
    575         { "Invalid workstation",                NT_STATUS_INVALID_WORKSTATION },
    576         { "Password expired",                   NT_STATUS_PASSWORD_EXPIRED },
    577         { "Account disabled",                   NT_STATUS_ACCOUNT_DISABLED },
    578         { "Memory allocation error",            NT_STATUS_NO_MEMORY },
    579         { "No domain controllers located",      NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND },
    580         { "Named pipe not available",           NT_STATUS_PIPE_NOT_AVAILABLE },
    581         { "Not implemented",                    NT_STATUS_NOT_IMPLEMENTED },
    582         { "Invalid information class",          NT_STATUS_INVALID_INFO_CLASS },
    583         { "Information length mismatch",        NT_STATUS_INFO_LENGTH_MISMATCH },
    584         { "Access violation",                   NT_STATUS_ACCESS_VIOLATION },
    585         { "Invalid handle",                     NT_STATUS_INVALID_HANDLE },
    586         { "Invalid parameter",                  NT_STATUS_INVALID_PARAMETER },
    587         { "No memory",                          NT_STATUS_NO_MEMORY },
    588         { "Buffer too small",                   NT_STATUS_BUFFER_TOO_SMALL },
    589         { "Revision mismatch",                  NT_STATUS_REVISION_MISMATCH },
    590         { "No such logon session",              NT_STATUS_NO_SUCH_LOGON_SESSION },
    591         { "No such privilege",                  NT_STATUS_NO_SUCH_PRIVILEGE },
    592         { "Procedure not found",                NT_STATUS_PROCEDURE_NOT_FOUND },
    593         { "Server disabled",                    NT_STATUS_SERVER_DISABLED },
    594         { "Invalid pipe state",                 NT_STATUS_INVALID_PIPE_STATE },
    595         { "Named pipe busy",                    NT_STATUS_PIPE_BUSY },
    596         { "Illegal function",                   NT_STATUS_ILLEGAL_FUNCTION },
    597         { "Named pipe dicconnected",            NT_STATUS_PIPE_DISCONNECTED },
    598         { "Named pipe closing",                 NT_STATUS_PIPE_CLOSING },
    599         { "Remote host not listening",          NT_STATUS_REMOTE_NOT_LISTENING },
    600         { "Duplicate name on network",          NT_STATUS_DUPLICATE_NAME },
    601         { "Print queue is full",                NT_STATUS_PRINT_QUEUE_FULL },
    602         { "No print spool space available",     NT_STATUS_NO_SPOOL_SPACE },
    603         { "The network name cannot be found",   NT_STATUS_BAD_NETWORK_NAME },
    604         { "The connection was refused",         NT_STATUS_CONNECTION_REFUSED },
    605         { "Too many names",                     NT_STATUS_TOO_MANY_NAMES },
    606         { "Too many sessions",                  NT_STATUS_TOO_MANY_SESSIONS },
    607         { "Invalid server state",               NT_STATUS_INVALID_SERVER_STATE },
    608         { "Invalid domain state",               NT_STATUS_INVALID_DOMAIN_STATE },
    609         { "Invalid domain role",                NT_STATUS_INVALID_DOMAIN_ROLE },
    610         { "No such domain",                     NT_STATUS_NO_SUCH_DOMAIN },
    611         { "Domain exists",                      NT_STATUS_DOMAIN_EXISTS },
    612         { "Domain limit exceeded",              NT_STATUS_DOMAIN_LIMIT_EXCEEDED },
    613         { "Bad logon session state",            NT_STATUS_BAD_LOGON_SESSION_STATE },
    614         { "Logon session collision",            NT_STATUS_LOGON_SESSION_COLLISION },
    615         { "Invalid logon type",                 NT_STATUS_INVALID_LOGON_TYPE },
    616         { "Cancelled",                          NT_STATUS_CANCELLED },
    617         { "Invalid computer name",              NT_STATUS_INVALID_COMPUTER_NAME },     
    618         { "Logon server conflict",              NT_STATUS_LOGON_SERVER_CONFLICT },
    619         { "Time difference at domain controller", NT_STATUS_TIME_DIFFERENCE_AT_DC },
    620         { "Pipe broken",                        NT_STATUS_PIPE_BROKEN },
    621         { "Registry corrupt",                   NT_STATUS_REGISTRY_CORRUPT },
    622         { "Too many secrets",                   NT_STATUS_TOO_MANY_SECRETS },
    623         { "Too many SIDs",                      NT_STATUS_TOO_MANY_SIDS },
    624         { "Lanmanager cross encryption required", NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED },
    625         { "Log file full",                      NT_STATUS_LOG_FILE_FULL },
    626         { "No trusted LSA secret",              NT_STATUS_NO_TRUST_LSA_SECRET },
    627         { "No trusted SAM account",             NT_STATUS_NO_TRUST_SAM_ACCOUNT },
    628         { "Trusted domain failure",             NT_STATUS_TRUSTED_DOMAIN_FAILURE },
    629         { "Trust relationship failure",         NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE },
    630         { "Trust failure",                      NT_STATUS_TRUST_FAILURE },
    631         { "Netlogon service not started",       NT_STATUS_NETLOGON_NOT_STARTED },
    632         { "Account expired",                    NT_STATUS_ACCOUNT_EXPIRED },
    633         { "Network credential conflict",        NT_STATUS_NETWORK_CREDENTIAL_CONFLICT },
    634         { "Remote session limit",               NT_STATUS_REMOTE_SESSION_LIMIT },
    635         { "No logon interdomain trust account", NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT },
    636         { "No logon workstation trust account", NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT },
    637         { "No logon server trust account",      NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT },
    638         { "Domain trust inconsistent",          NT_STATUS_DOMAIN_TRUST_INCONSISTENT },
    639         { "No user session key available",      NT_STATUS_NO_USER_SESSION_KEY },
    640         { "User session deleted",               NT_STATUS_USER_SESSION_DELETED },
    641         { "Insufficient server resources",      NT_STATUS_INSUFF_SERVER_RESOURCES },
    642         { "Insufficient logon information",     NT_STATUS_INSUFFICIENT_LOGON_INFO },
    643        
    644         { "License quota exceeded",             NT_STATUS_LICENSE_QUOTA_EXCEEDED },
    645         { "No more files",                      STATUS_NO_MORE_FILES },
     586        { N_("Success"),                                NT_STATUS_OK },
     587        { N_("Undetermined error"),             NT_STATUS_UNSUCCESSFUL },
     588        { N_("Access denied"),                  NT_STATUS_ACCESS_DENIED },
     589        { N_("Account locked out"),             NT_STATUS_ACCOUNT_LOCKED_OUT },
     590        { N_("Must change password"),           NT_STATUS_PASSWORD_MUST_CHANGE },
     591        { N_("Password is too short"),          NT_STATUS_PWD_TOO_SHORT },
     592        { N_("Password is too recent"),                 NT_STATUS_PWD_TOO_RECENT },
     593        { N_("Password history conflict"),              NT_STATUS_PWD_HISTORY_CONFLICT },
     594        { N_("No logon servers"),                       NT_STATUS_NO_LOGON_SERVERS },
     595        { N_("Improperly formed account name"),         NT_STATUS_INVALID_ACCOUNT_NAME },
     596        { N_("User exists"),                    NT_STATUS_USER_EXISTS },
     597        { N_("No such user"),                   NT_STATUS_NO_SUCH_USER },
     598        { N_("Group exists"),                   NT_STATUS_GROUP_EXISTS },
     599        { N_("No such group"),                  NT_STATUS_NO_SUCH_GROUP },
     600        { N_("Member not in group"),            NT_STATUS_MEMBER_NOT_IN_GROUP },
     601        { N_("Wrong Password"),                         NT_STATUS_WRONG_PASSWORD },
     602        { N_("Ill formed password"),            NT_STATUS_ILL_FORMED_PASSWORD },
     603        { N_("Password restriction"),           NT_STATUS_PASSWORD_RESTRICTION },
     604        { N_("Logon failure"),                  NT_STATUS_LOGON_FAILURE },
     605        { N_("Account restriction"),            NT_STATUS_ACCOUNT_RESTRICTION },
     606        { N_("Invalid logon hours"),            NT_STATUS_INVALID_LOGON_HOURS },
     607        { N_("Invalid workstation"),            NT_STATUS_INVALID_WORKSTATION },
     608        { N_("Password expired"),                       NT_STATUS_PASSWORD_EXPIRED },
     609        { N_("Account disabled"),                       NT_STATUS_ACCOUNT_DISABLED },
     610        { N_("Unexpected information received"),        NT_STATUS_INVALID_PARAMETER },
     611        { N_("Memory allocation error"),                NT_STATUS_NO_MEMORY },
     612        { N_("No domain controllers located"),  NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND },
     613        { N_("Account locked out"),             NT_STATUS_ACCOUNT_LOCKED_OUT },
     614        { N_("Named pipe not available"),               NT_STATUS_PIPE_NOT_AVAILABLE },
     615        { N_("Not implemented"),                        NT_STATUS_NOT_IMPLEMENTED },
     616        { N_("Invalid information class"),              NT_STATUS_INVALID_INFO_CLASS },
     617        { N_("Information length mismatch"),    NT_STATUS_INFO_LENGTH_MISMATCH },
     618        { N_("Access violation"),                       NT_STATUS_ACCESS_VIOLATION },
     619        { N_("Invalid handle"),                         NT_STATUS_INVALID_HANDLE },
     620        { N_("Invalid parameter"),                      NT_STATUS_INVALID_PARAMETER },
     621        { N_("No memory"),                              NT_STATUS_NO_MEMORY },
     622        { N_("Buffer too small"),                       NT_STATUS_BUFFER_TOO_SMALL },
     623        { N_("Revision mismatch"),                      NT_STATUS_REVISION_MISMATCH },
     624        { N_("No logon servers"),                       NT_STATUS_NO_LOGON_SERVERS },
     625        { N_("No such logon session"),          NT_STATUS_NO_SUCH_LOGON_SESSION },
     626        { N_("No such privilege"),                      NT_STATUS_NO_SUCH_PRIVILEGE },
     627        { N_("Procedure not found"),            NT_STATUS_PROCEDURE_NOT_FOUND },
     628        { N_("Server disabled"),                        NT_STATUS_SERVER_DISABLED },
     629        { N_("Invalid pipe state"),             NT_STATUS_INVALID_PIPE_STATE },
     630        { N_("Named pipe busy"),                        NT_STATUS_PIPE_BUSY },
     631        { N_("Illegal function"),                       NT_STATUS_ILLEGAL_FUNCTION },
     632        { N_("Named pipe disconnected"),                NT_STATUS_PIPE_DISCONNECTED },
     633        { N_("Named pipe closing"),             NT_STATUS_PIPE_CLOSING },
     634        { N_("Remote host not listening"),              NT_STATUS_REMOTE_NOT_LISTENING },
     635        { N_("Duplicate name on network"),              NT_STATUS_DUPLICATE_NAME },
     636        { N_("Print queue is full"),            NT_STATUS_PRINT_QUEUE_FULL },
     637        { N_("No print spool space available"),         NT_STATUS_NO_SPOOL_SPACE },
     638        { N_("The network name cannot be found"),   NT_STATUS_BAD_NETWORK_NAME },
     639        { N_("The connection was refused"),         NT_STATUS_CONNECTION_REFUSED },
     640        { N_("Too many names"),                         NT_STATUS_TOO_MANY_NAMES },
     641        { N_("Too many sessions"),                      NT_STATUS_TOO_MANY_SESSIONS },
     642        { N_("Invalid server state"),           NT_STATUS_INVALID_SERVER_STATE },
     643        { N_("Invalid domain state"),           NT_STATUS_INVALID_DOMAIN_STATE },
     644        { N_("Invalid domain role"),            NT_STATUS_INVALID_DOMAIN_ROLE },
     645        { N_("No such domain"),                         NT_STATUS_NO_SUCH_DOMAIN },
     646        { N_("Domain exists"),                  NT_STATUS_DOMAIN_EXISTS },
     647        { N_("Domain limit exceeded"),          NT_STATUS_DOMAIN_LIMIT_EXCEEDED },
     648        { N_("Bad logon session state"),                NT_STATUS_BAD_LOGON_SESSION_STATE },
     649        { N_("Logon session collision"),                NT_STATUS_LOGON_SESSION_COLLISION },
     650        { N_("Invalid logon type"),             NT_STATUS_INVALID_LOGON_TYPE },
     651        { N_("Cancelled"),                              NT_STATUS_CANCELLED },
     652        { N_("Invalid computer name"),          NT_STATUS_INVALID_COMPUTER_NAME },
     653        { N_("Logon server conflict"),          NT_STATUS_LOGON_SERVER_CONFLICT },
     654        { N_("Time difference at domain controller"), NT_STATUS_TIME_DIFFERENCE_AT_DC },
     655        { N_("Pipe broken"),                    NT_STATUS_PIPE_BROKEN },
     656        { N_("Registry corrupt"),                       NT_STATUS_REGISTRY_CORRUPT },
     657        { N_("Too many secrets"),                       NT_STATUS_TOO_MANY_SECRETS },
     658        { N_("Too many SIDs"),                  NT_STATUS_TOO_MANY_SIDS },
     659        { N_("Lanmanager cross encryption required"), NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED },
     660        { N_("Log file full"),                  NT_STATUS_LOG_FILE_FULL },
     661        { N_("No trusted LSA secret"),          NT_STATUS_NO_TRUST_LSA_SECRET },
     662        { N_("No trusted SAM account"),                 NT_STATUS_NO_TRUST_SAM_ACCOUNT },
     663        { N_("Trusted domain failure"),                 NT_STATUS_TRUSTED_DOMAIN_FAILURE },
     664        { N_("Trust relationship failure"),     NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE },
     665        { N_("Trust failure"),                  NT_STATUS_TRUST_FAILURE },
     666        { N_("Netlogon service not started"),   NT_STATUS_NETLOGON_NOT_STARTED },
     667        { N_("Account expired"),                        NT_STATUS_ACCOUNT_EXPIRED },
     668        { N_("Network credential conflict"),    NT_STATUS_NETWORK_CREDENTIAL_CONFLICT },
     669        { N_("Remote session limit"),           NT_STATUS_REMOTE_SESSION_LIMIT },
     670        { N_("No logon interdomain trust account"), NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT },
     671        { N_("No logon workstation trust account"), NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT },
     672        { N_("No logon server trust account"),  NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT },
     673        { N_("Domain trust inconsistent"),              NT_STATUS_DOMAIN_TRUST_INCONSISTENT },
     674        { N_("No user session key available"),  NT_STATUS_NO_USER_SESSION_KEY },
     675        { N_("User session deleted"),           NT_STATUS_USER_SESSION_DELETED },
     676        { N_("Insufficient server resources"),  NT_STATUS_INSUFF_SERVER_RESOURCES },
     677        { N_("Insufficient logon information"),         NT_STATUS_INSUFFICIENT_LOGON_INFO },
     678
     679        { N_("License quota exceeded"),                 NT_STATUS_LICENSE_QUOTA_EXCEEDED },
     680        { N_("No more files"),                  STATUS_NO_MORE_FILES },
    646681
    647682        { NULL, NT_STATUS(0) }
     
    654689const char *nt_errstr(NTSTATUS nt_code)
    655690{
    656         int idx = 0;
     691        int idx = 0;
    657692        char *result;
    658693
    659694#ifdef HAVE_LDAP
    660         if (NT_STATUS_IS_LDAP(nt_code)) {
    661                 return ldap_err2string(NT_STATUS_LDAP_CODE(nt_code));
     695        if (NT_STATUS_IS_LDAP(nt_code)) {
     696                return ldap_err2string(NT_STATUS_LDAP_CODE(nt_code));
    662697        }
    663698#endif
     
    669704
    670705        while (nt_errs[idx].nt_errstr != NULL) {
    671                 if (NT_STATUS_EQUAL(nt_errs[idx].nt_errcode, nt_code)) {
    672                         return nt_errs[idx].nt_errstr;
     706                if (NT_STATUS_V(nt_errs[idx].nt_errcode) ==
     707                    NT_STATUS_V(nt_code)) {
     708                        return nt_errs[idx].nt_errstr;
    673709                }
    674710                idx++;
     
    684720 Print friendler version fo NT error code
    685721 ***********************************************************************/
    686  
     722
    687723const char *get_friendly_nt_error_msg(NTSTATUS nt_code)
    688724{
    689         int idx = 0;
     725        int idx = 0;
    690726
    691727        while (nt_err_desc[idx].nt_errstr != NULL) {
    692728                if (NT_STATUS_V(nt_err_desc[idx].nt_errcode) == NT_STATUS_V(nt_code)) {
    693                         return nt_err_desc[idx].nt_errstr;
     729                        return nt_err_desc[idx].nt_errstr;
    694730                }
    695731                idx++;
    696732        }
    697        
     733
    698734        /* fall back to NT_STATUS_XXX string */
    699        
     735
    700736        return nt_errstr(nt_code);
    701737}
     
    708744{
    709745        char *result;
    710         int idx = 0;
     746        int idx = 0;
    711747
    712748        while (nt_errs[idx].nt_errstr != NULL) {
    713                 if (NT_STATUS_V(nt_errs[idx].nt_errcode) == 
    714                     NT_STATUS_V(nt_code)) {
    715                         return nt_errs[idx].nt_errstr;
     749                if (NT_STATUS_V(nt_errs[idx].nt_errcode) ==
     750                    NT_STATUS_V(nt_code)) {
     751                        return nt_errs[idx].nt_errstr;
    716752                }
    717753                idx++;
     
    730766NTSTATUS nt_status_string_to_code(const char *nt_status_str)
    731767{
    732         int idx = 0;
     768        int idx = 0;
    733769
    734770        while (nt_errs[idx].nt_errstr != NULL) {
    735                 if (strcmp(nt_errs[idx].nt_errstr, nt_status_str) == 0) {
    736                         return nt_errs[idx].nt_errcode;
     771                if (strcasecmp(nt_errs[idx].nt_errstr, nt_status_str) == 0) {
     772                        return nt_errs[idx].nt_errcode;
    737773                }
    738774                idx++;
     
    744780 * Squash an NT_STATUS in line with security requirements.
    745781 * In an attempt to avoid giving the whole game away when users
    746  * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and 
    747  * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations 
     782 * are authenticating, NT replaces both NT_STATUS_NO_SUCH_USER and
     783 * NT_STATUS_WRONG_PASSWORD with NT_STATUS_LOGON_FAILURE in certain situations
    748784 * (session setups in particular).
    749785 *
     
    755791{
    756792        if NT_STATUS_IS_OK(nt_status) {
    757                 return nt_status;               
     793                return nt_status;
    758794        } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
    759795                /* Match WinXP and don't give the game away */
    760796                return NT_STATUS_LOGON_FAILURE;
    761                
     797
    762798        } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
    763799                /* Match WinXP and don't give the game away */
     
    765801        } else {
    766802                return nt_status;
    767         } 
     803        }
    768804}
  • vendor/current/source3/libsmb/ntlmssp.c

    r414 r740  
    55
    66   Copyright (C) Andrew Tridgell      2001
    7    Copyright (C) Andrew Bartlett 2001-2003
    8    Copyright (C) Andrew Bartlett 2005 (Updated from gensec).
     7   Copyright (C) Andrew Bartlett 2001-2010
     8   Copyright (C) Stefan Metzmacher 2005
    99
    1010   This program is free software; you can redistribute it and/or modify
     
    2323
    2424#include "includes.h"
     25#include "../libcli/auth/ntlmssp.h"
     26#include "../libcli/auth/ntlmssp_private.h"
    2527#include "../libcli/auth/libcli_auth.h"
    2628#include "../librpc/gen_ndr/ndr_ntlmssp.h"
    27 #include "libsmb/ntlmssp_ndr.h"
     29#include "../libcli/auth/ntlmssp_ndr.h"
     30#include "../lib/crypto/md5.h"
     31#include "../lib/crypto/arcfour.h"
     32#include "../lib/crypto/hmacmd5.h"
     33#include "../nsswitch/libwbclient/wbclient.h"
    2834
    2935static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
     36                                       TALLOC_CTX *out_mem_ctx, /* Unused at this time */
    3037                                       DATA_BLOB reply, DATA_BLOB *next_request);
    31 static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
    32                                          const DATA_BLOB in, DATA_BLOB *out);
    3338static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
     39                                         TALLOC_CTX *out_mem_ctx, /* Unused at this time */
    3440                                         const DATA_BLOB reply, DATA_BLOB *next_request);
    35 static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
    36                                     const DATA_BLOB request, DATA_BLOB *reply);
    37 
    3841/**
    3942 * Callbacks for NTLMSSP - for both client and server operating modes
     
    4245
    4346static const struct ntlmssp_callbacks {
    44         enum NTLMSSP_ROLE role;
    45         enum NTLM_MESSAGE_TYPE ntlmssp_command;
     47        enum ntlmssp_role role;
     48        enum ntlmssp_message_type ntlmssp_command;
    4649        NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state,
     50                       TALLOC_CTX *out_mem_ctx,
    4751                       DATA_BLOB in, DATA_BLOB *out);
    4852} ntlmssp_callbacks[] = {
     
    5761
    5862/**
    59  * Print out the NTLMSSP flags for debugging
    60  * @param neg_flags The flags from the packet
    61  */
    62 
    63 void debug_ntlmssp_flags(uint32 neg_flags)
    64 {
    65         DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags));
    66 
    67         if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE)
    68                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_UNICODE\n"));
    69         if (neg_flags & NTLMSSP_NEGOTIATE_OEM)
    70                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM\n"));
    71         if (neg_flags & NTLMSSP_REQUEST_TARGET)
    72                 DEBUGADD(4, ("  NTLMSSP_REQUEST_TARGET\n"));
    73         if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
    74                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SIGN\n"));
    75         if (neg_flags & NTLMSSP_NEGOTIATE_SEAL)
    76                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SEAL\n"));
    77         if (neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM)
    78                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_DATAGRAM\n"));
    79         if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
    80                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_LM_KEY\n"));
    81         if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE)
    82                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NETWARE\n"));
    83         if (neg_flags & NTLMSSP_NEGOTIATE_NTLM)
    84                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM\n"));
    85         if (neg_flags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED)
    86                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED\n"));
    87         if (neg_flags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)
    88                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED\n"));
    89         if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL)
    90                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
    91         if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
    92                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
    93         if (neg_flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY)
    94                 DEBUGADD(4, ("  NTLMSSP_REQUEST_NON_NT_SESSION_KEY\n"));
    95         if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
    96                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM2\n"));
    97         if (neg_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
    98                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_TARGET_INFO\n"));
    99         if (neg_flags & NTLMSSP_NEGOTIATE_VERSION)
    100                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_VERSION\n"));
    101         if (neg_flags & NTLMSSP_NEGOTIATE_128)
    102                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_128\n"));
    103         if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
    104                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
    105         if (neg_flags & NTLMSSP_NEGOTIATE_56)
    106                 DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_56\n"));
    107 }
    108 
    109 /**
    11063 * Default challenge generation code.
    11164 *
    11265 */
    11366
    114 static void get_challenge(const struct ntlmssp_state *ntlmssp_state,
    115                           uint8_t chal[8])
     67static NTSTATUS get_challenge(const struct ntlmssp_state *ntlmssp_state,
     68                              uint8_t chal[8])
    11669{
    11770        generate_random_buffer(chal, 8);
     71        return NT_STATUS_OK;
    11872}
    11973
     
    146100 */
    147101
    148 NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user)
     102NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user)
    149103{
    150104        ntlmssp_state->user = talloc_strdup(ntlmssp_state, user ? user : "" );
     
    159113 *
    160114 */
    161 NTSTATUS ntlmssp_set_hashes(NTLMSSP_STATE *ntlmssp_state,
    162                 const unsigned char lm_hash[16],
    163                 const unsigned char nt_hash[16])
    164 {
    165         ntlmssp_state->lm_hash = (unsigned char *)
     115NTSTATUS ntlmssp_set_hashes(struct ntlmssp_state *ntlmssp_state,
     116                            const uint8_t lm_hash[16],
     117                            const uint8_t nt_hash[16])
     118{
     119        ntlmssp_state->lm_hash = (uint8_t *)
    166120                TALLOC_MEMDUP(ntlmssp_state, lm_hash, 16);
    167         ntlmssp_state->nt_hash = (unsigned char *)
     121        ntlmssp_state->nt_hash = (uint8_t *)
    168122                TALLOC_MEMDUP(ntlmssp_state, nt_hash, 16);
    169123        if (!ntlmssp_state->lm_hash || !ntlmssp_state->nt_hash) {
     
    179133 *
    180134 */
    181 NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password)
     135NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password)
    182136{
    183137        if (!password) {
     
    185139                ntlmssp_state->nt_hash = NULL;
    186140        } else {
    187                 unsigned char lm_hash[16];
    188                 unsigned char nt_hash[16];
     141                uint8_t lm_hash[16];
     142                uint8_t nt_hash[16];
    189143
    190144                E_deshash(password, lm_hash);
     
    199153 *
    200154 */
    201 NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain)
     155NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain)
    202156{
    203157        ntlmssp_state->domain = talloc_strdup(ntlmssp_state,
     
    210164
    211165/**
    212  * Set a workstation on an NTLMSSP context - ensures it is talloc()ed
    213  *
    214  */
    215 NTSTATUS ntlmssp_set_workstation(NTLMSSP_STATE *ntlmssp_state, const char *workstation)
    216 {
    217         ntlmssp_state->workstation = talloc_strdup(ntlmssp_state, workstation);
    218         if (!ntlmssp_state->workstation) {
    219                 return NT_STATUS_NO_MEMORY;
    220         }
    221         return NT_STATUS_OK;
    222 }
    223 
    224 /**
    225  *  Store a DATA_BLOB containing an NTLMSSP response, for use later.
    226  *  This copies the data blob
    227  */
    228 
    229 NTSTATUS ntlmssp_store_response(NTLMSSP_STATE *ntlmssp_state,
    230                                 DATA_BLOB response)
    231 {
    232         ntlmssp_state->stored_response = data_blob_talloc(ntlmssp_state,
    233                                                           response.data,
    234                                                           response.length);
    235         return NT_STATUS_OK;
    236 }
    237 
    238 /**
    239166 * Request features for the NTLMSSP negotiation
    240167 *
     
    242169 * @param feature_list List of space seperated features requested from NTLMSSP.
    243170 */
    244 void ntlmssp_want_feature_list(NTLMSSP_STATE *ntlmssp_state, char *feature_list)
     171void ntlmssp_want_feature_list(struct ntlmssp_state *ntlmssp_state, char *feature_list)
    245172{
    246173        /*
     
    269196 * @param feature Bit flag specifying the requested feature
    270197 */
    271 void ntlmssp_want_feature(NTLMSSP_STATE *ntlmssp_state, uint32 feature)
     198void ntlmssp_want_feature(struct ntlmssp_state *ntlmssp_state, uint32_t feature)
    272199{
    273200        /* As per JRA's comment above */
     
    295222 */
    296223
    297 NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state,
    298                         const DATA_BLOB in, DATA_BLOB *out)
    299 {
    300         DATA_BLOB input;
    301         uint32 ntlmssp_command;
     224NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state,
     225                        const DATA_BLOB input, DATA_BLOB *out)
     226{
     227        uint32_t ntlmssp_command;
    302228        int i;
    303229
     
    309235
    310236        *out = data_blob_null;
    311 
    312         if (!in.length && ntlmssp_state->stored_response.length) {
    313                 input = ntlmssp_state->stored_response;
    314 
    315                 /* we only want to read the stored response once - overwrite it */
    316                 ntlmssp_state->stored_response = data_blob_null;
    317         } else {
    318                 input = in;
    319         }
    320237
    321238        if (!input.length) {
     
    328245                        ntlmssp_command = NTLMSSP_NEGOTIATE;
    329246                        break;
     247                default:
     248                        DEBUG(1, ("Invalid role: %d\n", ntlmssp_state->role));
     249                        return NT_STATUS_INVALID_PARAMETER;
    330250                }
    331251        } else {
     
    347267                if (ntlmssp_callbacks[i].role == ntlmssp_state->role
    348268                    && ntlmssp_callbacks[i].ntlmssp_command == ntlmssp_command) {
    349                         return ntlmssp_callbacks[i].fn(ntlmssp_state, input, out);
     269                        return ntlmssp_callbacks[i].fn(ntlmssp_state, ntlmssp_state, input, out);
    350270                }
    351271        }
     
    358278
    359279/**
    360  * End an NTLMSSP state machine
    361  *
    362  * @param ntlmssp_state NTLMSSP State, free()ed by this function
    363  */
    364 
    365 void ntlmssp_end(NTLMSSP_STATE **ntlmssp_state)
    366 {
    367         (*ntlmssp_state)->ref_count--;
    368 
    369         if ((*ntlmssp_state)->ref_count == 0) {
    370                 data_blob_free(&(*ntlmssp_state)->chal);
    371                 data_blob_free(&(*ntlmssp_state)->lm_resp);
    372                 data_blob_free(&(*ntlmssp_state)->nt_resp);
    373                 TALLOC_FREE(*ntlmssp_state);
    374         }
    375 
    376         *ntlmssp_state = NULL;
    377         return;
    378 }
    379 
    380 /**
    381  * Determine correct target name flags for reply, given server role
    382  * and negotiated flags
    383  *
    384  * @param ntlmssp_state NTLMSSP State
    385  * @param neg_flags The flags from the packet
    386  * @param chal_flags The flags to be set in the reply packet
    387  * @return The 'target name' string.
    388  */
    389 
    390 static const char *ntlmssp_target_name(struct ntlmssp_state *ntlmssp_state,
    391                                        uint32 neg_flags, uint32 *chal_flags)
    392 {
    393         if (neg_flags & NTLMSSP_REQUEST_TARGET) {
    394                 *chal_flags |= NTLMSSP_NEGOTIATE_TARGET_INFO;
    395                 *chal_flags |= NTLMSSP_REQUEST_TARGET;
    396                 if (ntlmssp_state->server_role == ROLE_STANDALONE) {
    397                         *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
    398                         return ntlmssp_state->get_global_myname();
    399                 } else {
    400                         *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
    401                         return ntlmssp_state->get_domain();
    402                 };
    403         } else {
    404                 return "";
    405         }
    406 }
    407 
    408 static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
    409                                       uint32 neg_flags, bool allow_lm) {
    410         if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
    411                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;
    412                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM;
    413                 ntlmssp_state->unicode = True;
    414         } else {
    415                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE;
    416                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;
    417                 ntlmssp_state->unicode = False;
    418         }
    419 
    420         if ((neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && allow_lm) {
    421                 /* other end forcing us to use LM */
    422                 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
    423                 ntlmssp_state->use_ntlmv2 = False;
    424         } else {
    425                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
    426         }
    427 
    428         if (!(neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) {
    429                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
    430         }
    431 
    432         if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) {
    433                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
    434         }
    435 
    436         if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) {
    437                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
    438         }
    439 
    440         if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) {
    441                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56;
    442         }
    443 
    444         if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
    445                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH;
    446         }
    447 
    448         if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
    449                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
    450         }
    451 
    452         if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
    453                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL;
    454         }
    455 
    456         /* Woop Woop - unknown flag for Windows compatibility...
    457            What does this really do ? JRA. */
    458         if (!(neg_flags & NTLMSSP_NEGOTIATE_VERSION)) {
    459                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_VERSION;
    460         }
    461 
    462         if ((neg_flags & NTLMSSP_REQUEST_TARGET)) {
    463                 ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET;
    464         }
    465 }
    466 
    467 /**
    468  Weaken NTLMSSP keys to cope with down-level clients and servers.
    469 
    470  We probably should have some parameters to control this, but as
    471  it only occours for LM_KEY connections, and this is controlled
    472  by the client lanman auth/lanman auth parameters, it isn't too bad.
    473 */
    474 
    475 DATA_BLOB ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx)
    476 {
    477         DATA_BLOB weakened_key = data_blob_talloc(mem_ctx,
    478                                         ntlmssp_state->session_key.data,
    479                                         ntlmssp_state->session_key.length);
    480 
    481         /* Nothing to weaken.  We certainly don't want to 'extend' the length... */
    482         if (weakened_key.length < 16) {
    483                 /* perhaps there was no key? */
    484                 return weakened_key;
    485         }
    486 
    487         /* Key weakening not performed on the master key for NTLM2
    488            and does not occour for NTLM1.  Therefore we only need
    489            to do this for the LM_KEY.
    490         */
    491 
    492         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
    493                 /* LM key doesn't support 128 bit crypto, so this is
    494                  * the best we can do.  If you negotiate 128 bit, but
    495                  * not 56, you end up with 40 bit... */
    496                 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
    497                         weakened_key.data[7] = 0xa0;
    498                 } else { /* forty bits */
    499                         weakened_key.data[5] = 0xe5;
    500                         weakened_key.data[6] = 0x38;
    501                         weakened_key.data[7] = 0xb0;
    502                 }
    503                 weakened_key.length = 8;
    504         }
    505         return weakened_key;
    506 }
    507 
    508 /**
    509  * Next state function for the Negotiate packet
    510  *
    511  * @param ntlmssp_state NTLMSSP State
    512  * @param request The request, as a DATA_BLOB
    513  * @param request The reply, as an allocated DATA_BLOB, caller to free.
    514  * @return Errors or MORE_PROCESSING_REQUIRED if a reply is sent.
    515  */
    516 
    517 static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
    518                                          const DATA_BLOB request, DATA_BLOB *reply)
    519 {
    520         DATA_BLOB struct_blob;
    521         const char *dnsname;
    522         char *dnsdomname = NULL;
    523         uint32 neg_flags = 0;
    524         uint32 ntlmssp_command, chal_flags;
    525         uint8_t cryptkey[8];
    526         const char *target_name;
    527         struct NEGOTIATE_MESSAGE negotiate;
    528         struct CHALLENGE_MESSAGE challenge;
    529 
    530         /* parse the NTLMSSP packet */
    531 #if 0
    532         file_save("ntlmssp_negotiate.dat", request.data, request.length);
    533 #endif
    534 
    535         if (request.length) {
    536                 if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",
    537                                                           "NTLMSSP",
    538                                                           &ntlmssp_command,
    539                                                           &neg_flags)) {
    540                         DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",
    541                                 (unsigned int)request.length));
    542                         dump_data(2, request.data, request.length);
    543                         return NT_STATUS_INVALID_PARAMETER;
    544                 }
    545                 debug_ntlmssp_flags(neg_flags);
    546 
    547                 if (DEBUGLEVEL >= 10) {
    548                         if (NT_STATUS_IS_OK(ntlmssp_pull_NEGOTIATE_MESSAGE(&request,
    549                                                        ntlmssp_state,
    550                                                        NULL,
    551                                                        &negotiate)))
    552                         {
    553                                 NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE, &negotiate);
    554                         }
    555                 }
    556         }
    557 
    558         ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth());
    559 
    560         /* Ask our caller what challenge they would like in the packet */
    561         ntlmssp_state->get_challenge(ntlmssp_state, cryptkey);
    562 
    563         /* Check if we may set the challenge */
    564         if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {
    565                 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
    566         }
    567 
    568         /* The flags we send back are not just the negotiated flags,
    569          * they are also 'what is in this packet'.  Therfore, we
    570          * operate on 'chal_flags' from here on
    571          */
    572 
    573         chal_flags = ntlmssp_state->neg_flags;
    574 
    575         /* get the right name to fill in as 'target' */
    576         target_name = ntlmssp_target_name(ntlmssp_state,
    577                                           neg_flags, &chal_flags);
    578         if (target_name == NULL)
    579                 return NT_STATUS_INVALID_PARAMETER;
    580 
    581         ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
    582         ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state,
    583                                                         cryptkey, 8);
    584 
    585         /* This should be a 'netbios domain -> DNS domain' mapping */
    586         dnsdomname = get_mydnsdomname(ntlmssp_state);
    587         if (!dnsdomname) {
    588                 dnsdomname = talloc_strdup(ntlmssp_state, "");
    589         }
    590         if (!dnsdomname) {
    591                 return NT_STATUS_NO_MEMORY;
    592         }
    593         strlower_m(dnsdomname);
    594 
    595         dnsname = get_mydnsfullname();
    596         if (!dnsname) {
    597                 dnsname = "";
    598         }
    599 
    600         /* This creates the 'blob' of names that appears at the end of the packet */
    601         if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
    602         {
    603                 msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
    604                           MsvAvNbDomainName, target_name,
    605                           MsvAvNbComputerName, ntlmssp_state->get_global_myname(),
    606                           MsvAvDnsDomainName, dnsdomname,
    607                           MsvAvDnsComputerName, dnsname,
    608                           MsvAvEOL, "");
    609         } else {
    610                 struct_blob = data_blob_null;
    611         }
    612 
    613         {
    614                 /* Marshel the packet in the right format, be it unicode or ASCII */
    615                 const char *gen_string;
    616                 if (ntlmssp_state->unicode) {
    617                         gen_string = "CdUdbddB";
    618                 } else {
    619                         gen_string = "CdAdbddB";
    620                 }
    621 
    622                 msrpc_gen(ntlmssp_state, reply, gen_string,
    623                           "NTLMSSP",
    624                           NTLMSSP_CHALLENGE,
    625                           target_name,
    626                           chal_flags,
    627                           cryptkey, 8,
    628                           0, 0,
    629                           struct_blob.data, struct_blob.length);
    630 
    631                 if (DEBUGLEVEL >= 10) {
    632                         if (NT_STATUS_IS_OK(ntlmssp_pull_CHALLENGE_MESSAGE(reply,
    633                                                        ntlmssp_state,
    634                                                        NULL,
    635                                                        &challenge)))
    636                         {
    637                                 NDR_PRINT_DEBUG(CHALLENGE_MESSAGE, &challenge);
    638                         }
    639                 }
    640         }
    641 
    642         data_blob_free(&struct_blob);
    643 
    644         ntlmssp_state->expected_state = NTLMSSP_AUTH;
    645 
    646         return NT_STATUS_MORE_PROCESSING_REQUIRED;
    647 }
    648 
    649 /**
    650  * Next state function for the Authenticate packet
    651  *
    652  * @param ntlmssp_state NTLMSSP State
    653  * @param request The request, as a DATA_BLOB
    654  * @param request The reply, as an allocated DATA_BLOB, caller to free.
    655  * @return Errors or NT_STATUS_OK.
    656  */
    657 
    658 static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
    659                                     const DATA_BLOB request, DATA_BLOB *reply)
    660 {
    661         DATA_BLOB encrypted_session_key = data_blob_null;
    662         DATA_BLOB user_session_key = data_blob_null;
    663         DATA_BLOB lm_session_key = data_blob_null;
    664         DATA_BLOB session_key = data_blob_null;
    665         uint32 ntlmssp_command, auth_flags;
    666         NTSTATUS nt_status = NT_STATUS_OK;
    667         struct AUTHENTICATE_MESSAGE authenticate;
    668 
    669         /* used by NTLM2 */
    670         bool doing_ntlm2 = False;
    671 
    672         uchar session_nonce[16];
    673         uchar session_nonce_hash[16];
    674 
    675         const char *parse_string;
    676 
    677         /* parse the NTLMSSP packet */
    678         *reply = data_blob_null;
    679 
    680 #if 0
    681         file_save("ntlmssp_auth.dat", request.data, request.length);
    682 #endif
    683 
    684         if (ntlmssp_state->unicode) {
    685                 parse_string = "CdBBUUUBd";
    686         } else {
    687                 parse_string = "CdBBAAABd";
    688         }
    689 
    690         data_blob_free(&ntlmssp_state->lm_resp);
    691         data_blob_free(&ntlmssp_state->nt_resp);
    692 
    693         ntlmssp_state->user = NULL;
    694         ntlmssp_state->domain = NULL;
    695         ntlmssp_state->workstation = NULL;
    696 
    697         /* now the NTLMSSP encoded auth hashes */
    698         if (!msrpc_parse(ntlmssp_state, &request, parse_string,
    699                          "NTLMSSP",
    700                          &ntlmssp_command,
    701                          &ntlmssp_state->lm_resp,
    702                          &ntlmssp_state->nt_resp,
    703                          &ntlmssp_state->domain,
    704                          &ntlmssp_state->user,
    705                          &ntlmssp_state->workstation,
    706                          &encrypted_session_key,
    707                          &auth_flags)) {
    708                 auth_flags = 0;
    709 
    710                 /* Try again with a shorter string (Win9X truncates this packet) */
    711                 if (ntlmssp_state->unicode) {
    712                         parse_string = "CdBBUUU";
    713                 } else {
    714                         parse_string = "CdBBAAA";
    715                 }
    716 
    717                 /* now the NTLMSSP encoded auth hashes */
    718                 if (!msrpc_parse(ntlmssp_state, &request, parse_string,
    719                                  "NTLMSSP",
    720                                  &ntlmssp_command,
    721                                  &ntlmssp_state->lm_resp,
    722                                  &ntlmssp_state->nt_resp,
    723                                  &ntlmssp_state->domain,
    724                                  &ntlmssp_state->user,
    725                                  &ntlmssp_state->workstation)) {
    726                         DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));
    727                         dump_data(2, request.data, request.length);
    728 
    729                         return NT_STATUS_INVALID_PARAMETER;
    730                 }
    731         }
    732 
    733         if (auth_flags)
    734                 ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth());
    735 
    736         if (DEBUGLEVEL >= 10) {
    737                 if (NT_STATUS_IS_OK(ntlmssp_pull_AUTHENTICATE_MESSAGE(&request,
    738                                                   ntlmssp_state,
    739                                                   NULL,
    740                                                   &authenticate)))
    741                 {
    742                         NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE, &authenticate);
    743                 }
    744         }
    745 
    746         DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
    747                  ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length));
    748 
    749 #if 0
    750         file_save("nthash1.dat",  &ntlmssp_state->nt_resp.data,  &ntlmssp_state->nt_resp.length);
    751         file_save("lmhash1.dat",  &ntlmssp_state->lm_resp.data,  &ntlmssp_state->lm_resp.length);
    752 #endif
    753 
    754         /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a
    755            client challenge
    756 
    757            However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
    758         */
    759         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
    760                 if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
    761                         struct MD5Context md5_session_nonce_ctx;
    762                         SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);
    763 
    764                         doing_ntlm2 = True;
    765 
    766                         memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8);
    767                         memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8);
    768 
    769                         MD5Init(&md5_session_nonce_ctx);
    770                         MD5Update(&md5_session_nonce_ctx, session_nonce, 16);
    771                         MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
    772 
    773                         ntlmssp_state->chal = data_blob_talloc(
    774                                 ntlmssp_state, session_nonce_hash, 8);
    775 
    776                         /* LM response is no longer useful */
    777                         data_blob_free(&ntlmssp_state->lm_resp);
    778 
    779                         /* We changed the effective challenge - set it */
    780                         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) {
    781                                 data_blob_free(&encrypted_session_key);
    782                                 return nt_status;
    783                         }
    784 
    785                         /* LM Key is incompatible. */
    786                         ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
    787                 }
    788         }
    789 
    790         /*
    791          * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
    792          * is required (by "ntlm auth = no" and "lm auth = no" being set in the
    793          * smb.conf file) and no NTLMv2 response was sent then the password check
    794          * will fail here. JRA.
    795          */
    796 
    797         /* Finally, actually ask if the password is OK */
    798 
    799         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state,
    800                                                                        &user_session_key, &lm_session_key))) {
    801                 data_blob_free(&encrypted_session_key);
    802                 return nt_status;
    803         }
    804 
    805         dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);
    806         dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);
    807 
    808         /* Handle the different session key derivation for NTLM2 */
    809         if (doing_ntlm2) {
    810                 if (user_session_key.data && user_session_key.length == 16) {
    811                         session_key = data_blob_talloc(ntlmssp_state,
    812                                                        NULL, 16);
    813                         hmac_md5(user_session_key.data, session_nonce,
    814                                  sizeof(session_nonce), session_key.data);
    815                         DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
    816                         dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
    817 
    818                 } else {
    819                         DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
    820                         session_key = data_blob_null;
    821                 }
    822         } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
    823                 if (lm_session_key.data && lm_session_key.length >= 8) {
    824                         if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
    825                                 session_key = data_blob_talloc(ntlmssp_state,
    826                                                                NULL, 16);
    827                                 if (session_key.data == NULL) {
    828                                         return NT_STATUS_NO_MEMORY;
    829                                 }
    830                                 SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data,
    831                                                           session_key.data);
    832                                 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
    833                         } else {
    834                                 uint8 zeros[24];
    835                                 ZERO_STRUCT(zeros);
    836                                 session_key = data_blob_talloc(
    837                                         ntlmssp_state, NULL, 16);
    838                                 if (session_key.data == NULL) {
    839                                         return NT_STATUS_NO_MEMORY;
    840                                 }
    841                                 SMBsesskeygen_lm_sess_key(
    842                                         lm_session_key.data, zeros,
    843                                         session_key.data);
    844                         }
    845                         dump_data_pw("LM session key:\n", session_key.data,
    846                                      session_key.length);
    847                 } else {
    848                         DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
    849                         session_key = data_blob_null;
    850                 }
    851         } else if (user_session_key.data) {
    852                 session_key = user_session_key;
    853                 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
    854                 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
    855         } else if (lm_session_key.data) {
    856                 session_key = lm_session_key;
    857                 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
    858                 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
    859         } else {
    860                 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
    861                 session_key = data_blob_null;
    862         }
    863 
    864         /* With KEY_EXCH, the client supplies the proposed session key,
    865            but encrypts it with the long-term key */
    866         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
    867                 if (!encrypted_session_key.data || encrypted_session_key.length != 16) {
    868                         data_blob_free(&encrypted_session_key);
    869                         DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",
    870                                   (unsigned int)encrypted_session_key.length));
    871                         return NT_STATUS_INVALID_PARAMETER;
    872                 } else if (!session_key.data || session_key.length != 16) {
    873                         DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",
    874                                   (unsigned int)session_key.length));
    875                         ntlmssp_state->session_key = session_key;
    876                 } else {
    877                         dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
    878                         arcfour_crypt_blob(encrypted_session_key.data,
    879                                            encrypted_session_key.length,
    880                                            &session_key);
    881                         ntlmssp_state->session_key = data_blob_talloc(
    882                                 ntlmssp_state, encrypted_session_key.data,
    883                                 encrypted_session_key.length);
    884                         dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data,
    885                                      encrypted_session_key.length);
    886                 }
    887         } else {
    888                 ntlmssp_state->session_key = session_key;
    889         }
    890 
    891         if (!NT_STATUS_IS_OK(nt_status)) {
    892                 ntlmssp_state->session_key = data_blob_null;
    893         } else if (ntlmssp_state->session_key.length) {
    894                 nt_status = ntlmssp_sign_init(ntlmssp_state);
    895         }
    896 
    897         data_blob_free(&encrypted_session_key);
    898 
    899         /* Only one authentication allowed per server state. */
    900         ntlmssp_state->expected_state = NTLMSSP_DONE;
    901 
    902         return nt_status;
    903 }
    904 
    905 /**
    906280 * Create an NTLMSSP state machine
    907281 *
     
    909283 */
    910284
    911 NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
    912 {
    913         *ntlmssp_state = TALLOC_ZERO_P(NULL, NTLMSSP_STATE);
    914         if (!*ntlmssp_state) {
    915                 DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
    916                 talloc_destroy(*ntlmssp_state);
    917                 return NT_STATUS_NO_MEMORY;
    918         }
    919 
    920         (*ntlmssp_state)->role = NTLMSSP_SERVER;
    921 
    922         (*ntlmssp_state)->get_challenge = get_challenge;
    923         (*ntlmssp_state)->set_challenge = set_challenge;
    924         (*ntlmssp_state)->may_set_challenge = may_set_challenge;
    925 
    926         (*ntlmssp_state)->get_global_myname = global_myname;
    927         (*ntlmssp_state)->get_domain = lp_workgroup;
    928         (*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */
    929 
    930         (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE;
    931 
    932         (*ntlmssp_state)->ref_count = 1;
    933 
    934         (*ntlmssp_state)->neg_flags =
     285NTSTATUS ntlmssp_server_start(TALLOC_CTX *mem_ctx,
     286                              bool is_standalone,
     287                              const char *netbios_name,
     288                              const char *netbios_domain,
     289                              const char *dns_name,
     290                              const char *dns_domain,
     291                              struct ntlmssp_state **_ntlmssp_state)
     292{
     293        struct ntlmssp_state *ntlmssp_state;
     294
     295        if (!netbios_name) {
     296                netbios_name = "";
     297        }
     298
     299        if (!netbios_domain) {
     300                netbios_domain = "";
     301        }
     302
     303        if (!dns_domain) {
     304                dns_domain = "";
     305        }
     306
     307        if (!dns_name) {
     308                dns_name = "";
     309        }
     310
     311        ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state);
     312        if (!ntlmssp_state) {
     313                return NT_STATUS_NO_MEMORY;
     314        }
     315
     316        ntlmssp_state->role = NTLMSSP_SERVER;
     317
     318        ntlmssp_state->get_challenge = get_challenge;
     319        ntlmssp_state->set_challenge = set_challenge;
     320        ntlmssp_state->may_set_challenge = may_set_challenge;
     321
     322        ntlmssp_state->server.is_standalone = is_standalone;
     323
     324        ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
     325
     326        ntlmssp_state->allow_lm_key = lp_lanman_auth();
     327
     328        ntlmssp_state->neg_flags =
    935329                NTLMSSP_NEGOTIATE_128 |
    936330                NTLMSSP_NEGOTIATE_56 |
     
    943337                NTLMSSP_NEGOTIATE_SEAL;
    944338
     339        ntlmssp_state->server.netbios_name = talloc_strdup(ntlmssp_state, netbios_name);
     340        if (!ntlmssp_state->server.netbios_name) {
     341                talloc_free(ntlmssp_state);
     342                return NT_STATUS_NO_MEMORY;
     343        }
     344        ntlmssp_state->server.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain);
     345        if (!ntlmssp_state->server.netbios_domain) {
     346                talloc_free(ntlmssp_state);
     347                return NT_STATUS_NO_MEMORY;
     348        }
     349        ntlmssp_state->server.dns_name = talloc_strdup(ntlmssp_state, dns_name);
     350        if (!ntlmssp_state->server.dns_name) {
     351                talloc_free(ntlmssp_state);
     352                return NT_STATUS_NO_MEMORY;
     353        }
     354        ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, dns_domain);
     355        if (!ntlmssp_state->server.dns_domain) {
     356                talloc_free(ntlmssp_state);
     357                return NT_STATUS_NO_MEMORY;
     358        }
     359
     360        *_ntlmssp_state = ntlmssp_state;
    945361        return NT_STATUS_OK;
    946362}
     
    960376
    961377static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
     378                                  TALLOC_CTX *out_mem_ctx, /* Unused at this time */
    962379                                  DATA_BLOB reply, DATA_BLOB *next_request)
    963380{
    964         struct NEGOTIATE_MESSAGE negotiate;
     381        NTSTATUS status;
    965382
    966383        if (ntlmssp_state->unicode) {
     
    975392
    976393        /* generate the ntlmssp negotiate packet */
    977         msrpc_gen(ntlmssp_state, next_request, "CddAA",
     394        status = msrpc_gen(ntlmssp_state, next_request, "CddAA",
    978395                  "NTLMSSP",
    979396                  NTLMSSP_NEGOTIATE,
    980397                  ntlmssp_state->neg_flags,
    981                   ntlmssp_state->get_domain(),
    982                   ntlmssp_state->get_global_myname());
     398                  ntlmssp_state->client.netbios_domain,
     399                  ntlmssp_state->client.netbios_name);
     400        if (!NT_STATUS_IS_OK(status)) {
     401                DEBUG(0, ("ntlmssp_client_initial: failed to generate "
     402                        "ntlmssp negotiate packet\n"));
     403                return status;
     404        }
    983405
    984406        if (DEBUGLEVEL >= 10) {
    985                 if (NT_STATUS_IS_OK(ntlmssp_pull_NEGOTIATE_MESSAGE(next_request,
    986                                                ntlmssp_state,
    987                                                NULL,
    988                                                &negotiate)))
    989                 {
    990                         NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE, &negotiate);
     407                struct NEGOTIATE_MESSAGE *negotiate = talloc(
     408                        talloc_tos(), struct NEGOTIATE_MESSAGE);
     409                if (negotiate != NULL) {
     410                        status = ntlmssp_pull_NEGOTIATE_MESSAGE(
     411                                next_request, negotiate, negotiate);
     412                        if (NT_STATUS_IS_OK(status)) {
     413                                NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
     414                                                negotiate);
     415                        }
     416                        TALLOC_FREE(negotiate);
    991417                }
    992418        }
     
    1007433
    1008434static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
     435                                         TALLOC_CTX *out_mem_ctx, /* Unused at this time */
    1009436                                         const DATA_BLOB reply, DATA_BLOB *next_request)
    1010437{
    1011         uint32 chal_flags, ntlmssp_command, unkn1, unkn2;
     438        uint32_t chal_flags, ntlmssp_command, unkn1, unkn2;
    1012439        DATA_BLOB server_domain_blob;
    1013440        DATA_BLOB challenge_blob;
     
    1021448        DATA_BLOB encrypted_session_key = data_blob_null;
    1022449        NTSTATUS nt_status = NT_STATUS_OK;
    1023         struct CHALLENGE_MESSAGE challenge;
    1024         struct AUTHENTICATE_MESSAGE authenticate;
    1025450
    1026451        if (ntlmssp_state->use_ccache) {
     
    1046471
    1047472                wbc_status = wbcCredentialCache(&params, &info, &error);
    1048                 if (error != NULL) {
    1049                         wbcFreeMemory(error);
    1050                 }
     473                wbcFreeMemory(error);
    1051474                if (!WBC_ERROR_IS_OK(wbc_status)) {
    1052475                        goto noccache;
     
    1088511
    1089512        if (DEBUGLEVEL >= 10) {
    1090                 if (NT_STATUS_IS_OK(ntlmssp_pull_CHALLENGE_MESSAGE(&reply,
    1091                                                ntlmssp_state,
    1092                                                NULL,
    1093                                                &challenge)))
    1094                 {
    1095                         NDR_PRINT_DEBUG(CHALLENGE_MESSAGE, &challenge);
     513                struct CHALLENGE_MESSAGE *challenge = talloc(
     514                        talloc_tos(), struct CHALLENGE_MESSAGE);
     515                if (challenge != NULL) {
     516                        NTSTATUS status;
     517                        challenge->NegotiateFlags = chal_flags;
     518                        status = ntlmssp_pull_CHALLENGE_MESSAGE(
     519                                &reply, challenge, challenge);
     520                        if (NT_STATUS_IS_OK(status)) {
     521                                NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
     522                                                challenge);
     523                        }
     524                        TALLOC_FREE(challenge);
    1096525                }
    1097526        }
     
    1137566        }
    1138567
    1139         ntlmssp_state->server_domain = server_domain;
     568        if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
     569                ntlmssp_state->server.is_standalone = true;
     570        } else {
     571                ntlmssp_state->server.is_standalone = false;
     572        }
     573        /* TODO: parse struct_blob and fill in the rest */
     574        ntlmssp_state->server.netbios_name = "";
     575        ntlmssp_state->server.netbios_domain = server_domain;
     576        ntlmssp_state->server.dns_name = "";
     577        ntlmssp_state->server.dns_domain = "";
    1140578
    1141579        if (challenge_blob.length != 8) {
     
    1145583
    1146584        if (!ntlmssp_state->nt_hash || !ntlmssp_state->lm_hash) {
    1147                 uchar zeros[16];
     585                static const uint8_t zeros[16] = {0, };
    1148586                /* do nothing - blobs are zero length */
    1149 
    1150                 ZERO_STRUCT(zeros);
    1151587
    1152588                /* session key is all zeros */
     
    1178614        } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
    1179615                struct MD5Context md5_session_nonce_ctx;
    1180                 uchar session_nonce[16];
    1181                 uchar session_nonce_hash[16];
    1182                 uchar user_session_key[16];
     616                uint8_t session_nonce[16];
     617                uint8_t session_nonce_hash[16];
     618                uint8_t user_session_key[16];
    1183619
    1184620                lm_response = data_blob_talloc(ntlmssp_state, NULL, 24);
     
    1238674        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
    1239675                /* Make up a new session key */
    1240                 uint8 client_session_key[16];
     676                uint8_t client_session_key[16];
    1241677                generate_random_buffer(client_session_key, sizeof(client_session_key));
    1242678
     
    1255691
    1256692        /* this generates the actual auth packet */
    1257         if (!msrpc_gen(ntlmssp_state, next_request, auth_gen_string,
     693        nt_status = msrpc_gen(ntlmssp_state, next_request, auth_gen_string,
    1258694                       "NTLMSSP",
    1259695                       NTLMSSP_AUTH,
     
    1262698                       ntlmssp_state->domain,
    1263699                       ntlmssp_state->user,
    1264                        ntlmssp_state->get_global_myname(),
     700                       ntlmssp_state->client.netbios_name,
    1265701                       encrypted_session_key.data, encrypted_session_key.length,
    1266                        ntlmssp_state->neg_flags)) {
    1267 
     702                       ntlmssp_state->neg_flags);
     703
     704        if (!NT_STATUS_IS_OK(nt_status)) {
    1268705                return NT_STATUS_NO_MEMORY;
    1269706        }
    1270707
    1271708        if (DEBUGLEVEL >= 10) {
    1272                 if (NT_STATUS_IS_OK(ntlmssp_pull_AUTHENTICATE_MESSAGE(next_request,
    1273                                                   ntlmssp_state,
    1274                                                   NULL,
    1275                                                   &authenticate)))
    1276                 {
    1277                         NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE, &authenticate);
     709                struct AUTHENTICATE_MESSAGE *authenticate = talloc(
     710                        talloc_tos(), struct AUTHENTICATE_MESSAGE);
     711                if (authenticate != NULL) {
     712                        NTSTATUS status;
     713                        authenticate->NegotiateFlags =
     714                                ntlmssp_state->neg_flags;
     715                        status = ntlmssp_pull_AUTHENTICATE_MESSAGE(
     716                                next_request, authenticate, authenticate);
     717                        if (NT_STATUS_IS_OK(status)) {
     718                                NDR_PRINT_DEBUG(AUTHENTICATE_MESSAGE,
     719                                                authenticate);
     720                        }
     721                        TALLOC_FREE(authenticate);
    1278722                }
    1279723        }
     
    1300744}
    1301745
    1302 NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
    1303 {
    1304         *ntlmssp_state = TALLOC_ZERO_P(NULL, NTLMSSP_STATE);
    1305         if (!*ntlmssp_state) {
    1306                 DEBUG(0,("ntlmssp_client_start: talloc failed!\n"));
    1307                 talloc_destroy(*ntlmssp_state);
    1308                 return NT_STATUS_NO_MEMORY;
    1309         }
    1310 
    1311         (*ntlmssp_state)->role = NTLMSSP_CLIENT;
    1312 
    1313         (*ntlmssp_state)->get_global_myname = global_myname;
    1314         (*ntlmssp_state)->get_domain = lp_workgroup;
    1315 
    1316         (*ntlmssp_state)->unicode = True;
    1317 
    1318         (*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth();
    1319 
    1320         (*ntlmssp_state)->expected_state = NTLMSSP_INITIAL;
    1321 
    1322         (*ntlmssp_state)->ref_count = 1;
    1323 
    1324         (*ntlmssp_state)->neg_flags =
     746NTSTATUS ntlmssp_client_start(TALLOC_CTX *mem_ctx,
     747                              const char *netbios_name,
     748                              const char *netbios_domain,
     749                              bool use_ntlmv2,
     750                              struct ntlmssp_state **_ntlmssp_state)
     751{
     752        struct ntlmssp_state *ntlmssp_state;
     753
     754        if (!netbios_name) {
     755                netbios_name = "";
     756        }
     757
     758        if (!netbios_domain) {
     759                netbios_domain = "";
     760        }
     761
     762        ntlmssp_state = talloc_zero(mem_ctx, struct ntlmssp_state);
     763        if (!ntlmssp_state) {
     764                return NT_STATUS_NO_MEMORY;
     765        }
     766
     767        ntlmssp_state->role = NTLMSSP_CLIENT;
     768
     769        ntlmssp_state->unicode = True;
     770
     771        ntlmssp_state->use_ntlmv2 = use_ntlmv2;
     772
     773        ntlmssp_state->expected_state = NTLMSSP_INITIAL;
     774
     775        ntlmssp_state->neg_flags =
    1325776                NTLMSSP_NEGOTIATE_128 |
    1326777                NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
     
    1330781                NTLMSSP_REQUEST_TARGET;
    1331782
     783        ntlmssp_state->client.netbios_name = talloc_strdup(ntlmssp_state, netbios_name);
     784        if (!ntlmssp_state->client.netbios_name) {
     785                talloc_free(ntlmssp_state);
     786                return NT_STATUS_NO_MEMORY;
     787        }
     788        ntlmssp_state->client.netbios_domain = talloc_strdup(ntlmssp_state, netbios_domain);
     789        if (!ntlmssp_state->client.netbios_domain) {
     790                talloc_free(ntlmssp_state);
     791                return NT_STATUS_NO_MEMORY;
     792        }
     793
     794        *_ntlmssp_state = ntlmssp_state;
    1332795        return NT_STATUS_OK;
    1333796}
  • vendor/current/source3/libsmb/passchange.c

    r414 r740  
    1919
    2020#include "includes.h"
     21#include "../librpc/gen_ndr/ndr_samr.h"
     22#include "rpc_client/cli_pipe.h"
     23#include "rpc_client/cli_samr.h"
     24#include "libsmb/libsmb.h"
     25#include "libsmb/clirap.h"
     26#include "libsmb/nmblib.h"
    2127
    2228/*************************************************************
     
    301307                        if (asprintf(err_str, "SAMR connection to machine %s "
    302308                                 "failed. Error was %s, but LANMAN password "
    303                                  "changed are disabled\n",
     309                                 "changes are disabled\n",
    304310                                nt_errstr(result), remote_machine) == -1) {
    305311                                *err_str = NULL;
  • vendor/current/source3/libsmb/samlogon_cache.c

    r414 r740  
    2323
    2424#include "includes.h"
     25#include "system/filesys.h"
    2526#include "librpc/gen_ndr/ndr_krb5pac.h"
     27#include "../libcli/security/security.h"
     28#include "util_tdb.h"
    2629
    2730#define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
     
    4649        path = cache_path(NETSAMLOGON_TDB);
    4750again:
    48         tdb = tdb_open_log(path, 0, TDB_DEFAULT,
     51        tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
    4952                           O_RDWR | O_CREAT, 0600);
    5053        if (tdb == NULL) {
     
    7073
    7174        DEBUG(0,("retry after CLEAR_IF_FIRST for '%s'\n", path));
    72         tdb = tdb_open_log(path, 0, TDB_CLEAR_IF_FIRST,
     75        tdb = tdb_open_log(path, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
    7376                           O_RDWR | O_CREAT, 0600);
    7477        if (tdb) {
     
    99102***********************************************************************/
    100103
    101 void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3)
    102 {
    103         DOM_SID user_sid;
    104         fstring keystr, tmp;
    105 
    106         if (!info3) {
    107                 return;
    108         }
     104void netsamlogon_clear_cached_user(const struct dom_sid *user_sid)
     105{
     106        fstring keystr;
    109107
    110108        if (!netsamlogon_cache_init()) {
     
    114112                return;
    115113        }
    116         sid_copy(&user_sid, info3->base.domain_sid);
    117         sid_append_rid(&user_sid, info3->base.rid);
    118114
    119115        /* Prepare key as DOMAIN-SID/USER-RID string */
    120         slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
     116        sid_to_fstring(keystr, user_sid);
    121117
    122118        DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
     
    133129{
    134130        TDB_DATA data;
    135         fstring keystr, tmp;
     131        fstring keystr;
    136132        bool result = false;
    137         DOM_SID user_sid;
     133        struct dom_sid  user_sid;
    138134        time_t t = time(NULL);
    139135        TALLOC_CTX *mem_ctx;
     
    152148        }
    153149
    154         sid_copy(&user_sid, info3->base.domain_sid);
    155         sid_append_rid(&user_sid, info3->base.rid);
     150        sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid);
    156151
    157152        /* Prepare key as DOMAIN-SID/USER-RID string */
    158         slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
     153        sid_to_fstring(keystr, &user_sid);
    159154
    160155        DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
     
    181176        }
    182177
    183         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &r,
     178        ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r,
    184179                                       (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
    185180        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    206201***********************************************************************/
    207202
    208 struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
     203struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid)
    209204{
    210205        struct netr_SamInfo3 *info3 = NULL;
     
    237232        blob = data_blob_const(data.dptr, data.dsize);
    238233
    239         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r,
     234        ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
    240235                                      (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
    241236
     
    279274}
    280275
    281 bool netsamlogon_cache_have(const DOM_SID *user_sid)
     276bool netsamlogon_cache_have(const struct dom_sid *user_sid)
    282277{
    283278        TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
  • vendor/current/source3/libsmb/smb_seal.c

    r414 r740  
    1919
    2020#include "includes.h"
     21#include "../libcli/auth/ntlmssp.h"
     22#include "smb_crypt.h"
     23#include "libsmb/libsmb.h"
    2124
    2225/******************************************************************************
     
    6063******************************************************************************/
    6164
    62 NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
     65NTSTATUS common_ntlm_decrypt_buffer(struct ntlmssp_state *ntlmssp_state, char *buf)
    6366{
    6467        NTSTATUS status;
     
    108111******************************************************************************/
    109112
    110 NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
     113NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
    111114                                uint16 enc_ctx_num,
    112115                                char *buf,
     
    117120        size_t data_len = smb_len(buf) - 4; /* Ignore the 0xFF SMB bytes. */
    118121        DATA_BLOB sig;
    119 
     122        TALLOC_CTX *frame;
    120123        *ppbuf_out = NULL;
    121124
     
    124127        }
    125128
     129        frame = talloc_stackframe();
    126130        /*
    127131         * We know smb_len can't return a value > 128k, so no int overflow
     
    140144
    141145        status = ntlmssp_seal_packet(ntlmssp_state,
     146                                     frame,
    142147                (unsigned char *)buf_out + 8 + NTLMSSP_SIG_SIZE, /* 4 byte len + 0xFF 'S' <enc> <ctx> */
    143148                data_len,
     
    147152
    148153        if (!NT_STATUS_IS_OK(status)) {
    149                 data_blob_free(&sig);
     154                talloc_free(frame);
    150155                SAFE_FREE(buf_out);
    151156                return status;
     
    154159        /* First 16 data bytes are signature for SSPI compatibility. */
    155160        memcpy(buf_out + 8, sig.data, NTLMSSP_SIG_SIZE);
    156         data_blob_free(&sig);
     161        talloc_free(frame);
    157162        *ppbuf_out = buf_out;
    158163        return NT_STATUS_OK;
     
    369374        if (es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
    370375                if (es->s.ntlmssp_state) {
    371                         ntlmssp_end(&es->s.ntlmssp_state);
     376                        TALLOC_FREE(es->s.ntlmssp_state);
    372377                }
    373378        }
  • vendor/current/source3/libsmb/smb_share_modes.c

    r414 r740  
    2626
    2727#include "includes.h"
     28#include "system/filesys.h"
    2829#include "smb_share_modes.h"
     30#include <tdb.h>
    2931
    3032/* Database context handle. */
     
    6870
    6971        smb_db->smb_tdb = tdb_open(db_path,
    70                                 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST,
     72                                0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
    7173                                O_RDWR|O_CREAT,
    7274                                0644);
     
    156158
    157159static void create_share_mode_entry(struct share_mode_entry *out,
    158                                 const struct smb_share_mode_entry *in)
     160                                const struct smb_share_mode_entry *in,
     161                                uint32_t name_hash)
    159162{
    160163        memset(out, '\0', sizeof(struct share_mode_entry));
     
    171174        out->uid = (uint32)geteuid();
    172175        out->flags = 0;
     176        out->name_hash = name_hash;
    173177}
    174178
     
    256260        }
    257261
    258         *p_delete_on_close = ld->u.s.delete_on_close;
     262        *p_delete_on_close = ld->u.s.num_delete_token_entries != 0;
    259263        *pp_list = list;
    260264        free(db_data.dptr);
    261265        return list_num;
     266}
     267
     268static uint32_t smb_name_hash(const char *sharepath, const char *filename, int *err)
     269{
     270        TDB_DATA key;
     271        char *fullpath = NULL;
     272        size_t sharepath_size = strlen(sharepath);
     273        size_t filename_size = strlen(filename);
     274        uint32_t name_hash;
     275
     276        *err = 0;
     277        fullpath = (char *)malloc(sharepath_size + filename_size + 2);
     278        if (fullpath == NULL) {
     279                *err = 1;
     280                return 0;
     281        }
     282        memcpy(fullpath, sharepath, sharepath_size);
     283        fullpath[sharepath_size] = '/';
     284        memcpy(&fullpath[sharepath_size + 1], filename, filename_size + 1);
     285
     286        key.dptr = (uint8_t *)fullpath;
     287        key.dsize = strlen(fullpath) + 1;
     288        name_hash = tdb_jenkins_hash(&key);
     289        free(fullpath);
     290        return name_hash;
    262291}
    263292
     
    282311        uint8 *new_data_p = NULL;
    283312        size_t new_data_size = 0;
     313        int err = 0;
     314        uint32_t name_hash = smb_name_hash(sharepath, filename, &err);
     315
     316        if (err) {
     317                return -1;
     318        }
    284319
    285320        db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
     
    297332                memset(ld, '\0', sizeof(struct locking_data));
    298333                ld->u.s.num_share_mode_entries = 1;
    299                 ld->u.s.delete_on_close = 0;
    300                 ld->u.s.delete_token_size = 0;
     334                ld->u.s.num_delete_token_entries = 0;
    301335                shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
    302                 create_share_mode_entry(shares, new_entry);
     336                create_share_mode_entry(shares, new_entry, name_hash);
    303337
    304338                memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry),
     
    339373                        (orig_num_share_modes * sizeof(struct share_mode_entry)));
    340374
    341         create_share_mode_entry(shares, new_entry);
     375        create_share_mode_entry(shares, new_entry, name_hash);
    342376
    343377        ld = (struct locking_data *)new_data_p;
    344378        ld->u.s.num_share_mode_entries++;
    345379
    346         /* Append the original delete_token and filenames. */
     380        /* Append the original delete_tokens and filenames. */
    347381        memcpy(new_data_p + sizeof(struct locking_data) + (ld->u.s.num_share_mode_entries * sizeof(struct share_mode_entry)),
    348382                db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)),
     
    461495        }
    462496
    463         /* Copy any delete token plus the terminating filenames. */
     497        /* Copy any delete tokens plus the terminating filenames. */
    464498        remaining_ptr = db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry));
    465499        remaining_size = db_data.dsize - (remaining_ptr - db_data.dptr);
     
    522556
    523557                if (share_mode_entry_equal(set_entry, share)) {
    524                         create_share_mode_entry(share, new_entry);
     558                        create_share_mode_entry(share, new_entry, share->name_hash);
    525559                        found_entry = 1;
    526560                        break;
  • vendor/current/source3/libsmb/smb_signing.c

    r414 r740  
    2121
    2222#include "includes.h"
     23#include "../lib/crypto/md5.h"
     24#include "smb_signing.h"
    2325
    2426/* Used by the SMB signing functions. */
     
    4446        /* the next expected seqnum */
    4547        uint32_t seqnum;
     48
     49        TALLOC_CTX *mem_ctx;
     50        void *(*alloc_fn)(TALLOC_CTX *mem_ctx, size_t len);
     51        void (*free_fn)(TALLOC_CTX *mem_ctx, void *ptr);
    4652};
    4753
     
    5056        si->active = false;
    5157        si->bsrspyl = false;
    52         data_blob_free(&si->mac_key);
    5358        si->seqnum = 0;
     59
     60        if (si->free_fn) {
     61                si->free_fn(si->mem_ctx, si->mac_key.data);
     62        } else {
     63                talloc_free(si->mac_key.data);
     64        }
     65        si->mac_key.data = NULL;
     66        si->mac_key.length = 0;
     67}
     68
     69struct smb_signing_state *smb_signing_init_ex(TALLOC_CTX *mem_ctx,
     70                                              bool allowed,
     71                                              bool mandatory,
     72                                              void *(*alloc_fn)(TALLOC_CTX *, size_t),
     73                                              void (*free_fn)(TALLOC_CTX *, void *))
     74{
     75        struct smb_signing_state *si;
     76
     77        if (alloc_fn) {
     78                void *p = alloc_fn(mem_ctx, sizeof(struct smb_signing_state));
     79                if (p == NULL) {
     80                        return NULL;
     81                }
     82                memset(p, 0, sizeof(struct smb_signing_state));
     83                si = (struct smb_signing_state *)p;
     84                si->mem_ctx = mem_ctx;
     85                si->alloc_fn = alloc_fn;
     86                si->free_fn = free_fn;
     87        } else {
     88                si = talloc_zero(mem_ctx, struct smb_signing_state);
     89                if (si == NULL) {
     90                        return NULL;
     91                }
     92        }
     93
     94        if (mandatory) {
     95                allowed = true;
     96        }
     97
     98        si->allowed = allowed;
     99        si->mandatory = mandatory;
     100
     101        return si;
    54102}
    55103
     
    58106                                           bool mandatory)
    59107{
    60         struct smb_signing_state *si;
    61 
    62         si = talloc_zero(mem_ctx, struct smb_signing_state);
    63         if (si == NULL) {
    64                 return NULL;
    65         }
    66 
    67         if (mandatory) {
    68                 allowed = true;
    69         }
    70 
    71         si->allowed = allowed;
    72         si->mandatory = mandatory;
    73 
    74         return si;
     108        return smb_signing_init_ex(mem_ctx, allowed, mandatory, NULL, NULL);
    75109}
    76110
     
    313347
    314348        len = response.length + user_session_key.length;
    315         si->mac_key = data_blob_talloc(si, NULL, len);
     349        if (si->alloc_fn) {
     350                si->mac_key.data = (uint8_t *)si->alloc_fn(si->mem_ctx, len);
     351                if (si->mac_key.data == NULL) {
     352                        return false;
     353                }
     354        } else {
     355                si->mac_key.data = (uint8_t *)talloc_size(si, len);
     356                if (si->mac_key.data == NULL) {
     357                        return false;
     358                }
     359        }
     360        si->mac_key.length = len;
    316361
    317362        ofs = 0;
  • vendor/current/source3/libsmb/smberr.c

    r414 r740  
    22   Unix SMB/CIFS implementation.
    33   Copyright (C) Andrew Tridgell 1998
    4    
     4
    55   This program is free software; you can redistribute it and/or modify
    66   it under the terms of the GNU General Public License as published by
    77   the Free Software Foundation; either version 3 of the License, or
    88   (at your option) any later version.
    9    
     9
    1010   This program is distributed in the hope that it will be useful,
    1111   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1212   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1313   GNU General Public License for more details.
    14    
     14
    1515   You should have received a copy of the GNU General Public License
    1616   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    163163        char *result;
    164164        int i,j;
    165        
     165
    166166        for (i=0;err_classes[i].e_class;i++)
    167167                if (err_classes[i].code == e_class) {
     
    177177                        return result;
    178178                }
    179        
     179
    180180        result = talloc_asprintf(talloc_tos(), "Error: Unknown error class "
    181181                                 "(%d,%d)", e_class,num);
  • vendor/current/source3/libsmb/smbsock_connect.c

    r600 r740  
    1919
    2020#include "includes.h"
    21 #include "../lib/async_req/async_sock.h"
     21#include "../lib/util/tevent_ntstatus.h"
     22#include "client.h"
    2223#include "async_smb.h"
     24#include "libsmb/nmblib.h"
    2325
    2426struct nb_connect_state {
     
    177179        const struct sockaddr_storage *addr;
    178180        const char *called_name;
     181        uint8_t called_type;
    179182        const char *calling_name;
     183        uint8_t calling_type;
    180184        struct tevent_req *req_139;
    181185        struct tevent_req *req_445;
     
    192196                                        struct tevent_context *ev,
    193197                                        const struct sockaddr_storage *addr,
     198                                        uint16_t port,
    194199                                        const char *called_name,
    195                                         const char *calling_name)
     200                                        int called_type,
     201                                        const char *calling_name,
     202                                        int calling_type)
    196203{
    197204        struct tevent_req *req, *subreq;
     
    207214        state->called_name =
    208215                (called_name != NULL) ? called_name : "*SMBSERVER";
     216        state->called_type =
     217                (called_type != -1) ? called_type : 0x20;
    209218        state->calling_name =
    210219                (calling_name != NULL) ? calling_name : global_myname();
     220        state->calling_type =
     221                (calling_type != -1) ? calling_type : 0x00;
    211222
    212223        talloc_set_destructor(state, smbsock_connect_state_destructor);
     224
     225        if (port == 139) {
     226                subreq = tevent_wakeup_send(state, ev, timeval_set(0, 0));
     227                if (tevent_req_nomem(subreq, req)) {
     228                        return tevent_req_post(req, ev);
     229                }
     230                tevent_req_set_callback(subreq, smbsock_connect_do_139, req);
     231                return req;
     232        }
     233        if (port != 0) {
     234                state->req_445 = open_socket_out_send(state, ev, addr, port,
     235                                                      5000);
     236                if (tevent_req_nomem(state->req_445, req)) {
     237                        return tevent_req_post(req, ev);
     238                }
     239                tevent_req_set_callback(
     240                        state->req_445, smbsock_connect_connected, req);
     241                return req;
     242        }
     243
     244        /*
     245         * port==0, try both
     246         */
    213247
    214248        state->req_445 = open_socket_out_send(state, ev, addr, 445, 5000);
     
    238272        if (state->sock != -1) {
    239273                close(state->sock);
     274                state->sock = -1;
    240275        }
    241276        return 0;
     
    257292        }
    258293        state->req_139 = nb_connect_send(state, state->ev, state->addr,
    259                                          state->called_name, 0x20,
    260                                          state->calling_name, 0x0);
     294                                         state->called_name,
     295                                         state->called_type,
     296                                         state->calling_name,
     297                                         state->calling_type);
    261298        if (tevent_req_nomem(state->req_139, req)) {
    262299                return;
     
    314351
    315352NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock,
    316                           uint16_t *port)
     353                              uint16_t *ret_port)
    317354{
    318355        struct smbsock_connect_state *state = tevent_req_data(
     
    325362        *sock = state->sock;
    326363        state->sock = -1;
    327         if (port != NULL) {
    328                 *port = state->port;
     364        if (ret_port != NULL) {
     365                *ret_port = state->port;
    329366        }
    330367        return NT_STATUS_OK;
    331368}
    332369
    333 NTSTATUS smbsock_connect(const struct sockaddr_storage *addr,
    334                          const char *called_name, const char *calling_name,
    335                          int *pfd, uint16_t *port)
     370NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, uint16_t port,
     371                         const char *called_name, int called_type,
     372                         const char *calling_name, int calling_type,
     373                         int *pfd, uint16_t *ret_port, int sec_timeout)
    336374{
    337375        TALLOC_CTX *frame = talloc_stackframe();
     
    344382                goto fail;
    345383        }
    346         req = smbsock_connect_send(frame, ev, addr, called_name, calling_name);
     384        req = smbsock_connect_send(frame, ev, addr, port,
     385                                   called_name, called_type,
     386                                   calling_name, calling_type);
    347387        if (req == NULL) {
    348388                goto fail;
    349389        }
     390        if ((sec_timeout != 0) &&
     391            !tevent_req_set_endtime(
     392                    req, ev, timeval_current_ofs(sec_timeout, 0))) {
     393                goto fail;
     394        }
    350395        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    351396                goto fail;
    352397        }
    353         status = smbsock_connect_recv(req, pfd, port);
     398        status = smbsock_connect_recv(req, pfd, ret_port);
    354399 fail:
    355400        TALLOC_FREE(frame);
     
    361406        const struct sockaddr_storage *addrs;
    362407        const char **called_names;
     408        int *called_types;
     409        const char **calling_names;
     410        int *calling_types;
    363411        size_t num_addrs;
     412        uint16_t port;
    364413
    365414        struct tevent_req **requests;
     
    368417
    369418        int fd;
    370         uint16_t port;
     419        uint16_t chosen_port;
    371420        size_t chosen_index;
    372421};
     
    381430                                            const struct sockaddr_storage *addrs,
    382431                                            const char **called_names,
    383                                             size_t num_addrs)
     432                                            int *called_types,
     433                                            const char **calling_names,
     434                                            int *calling_types,
     435                                            size_t num_addrs, uint16_t port)
    384436{
    385437        struct tevent_req *req, *subreq;
     
    395447        state->num_addrs = num_addrs;
    396448        state->called_names = called_names;
     449        state->called_types = called_types;
     450        state->calling_names = calling_names;
     451        state->calling_types = calling_types;
     452        state->port = port;
    397453
    398454        if (num_addrs == 0) {
     
    459515        subreq = smbsock_connect_send(
    460516                state->requests, state->ev, &state->addrs[state->num_sent],
     517                state->port,
    461518                (state->called_names != NULL)
    462519                ? state->called_names[state->num_sent] : NULL,
    463                 NULL);
     520                (state->called_types != NULL)
     521                ? state->called_types[state->num_sent] : -1,
     522                (state->calling_names != NULL)
     523                ? state->calling_names[state->num_sent] : NULL,
     524                (state->calling_types != NULL)
     525                ? state->calling_types[state->num_sent] : -1);
    464526        if (tevent_req_nomem(subreq, req)) {
    465527                return false;
     
    481543        NTSTATUS status;
    482544        int fd;
    483         uint16_t port;
     545        uint16_t chosen_port;
    484546        size_t i;
    485547        size_t chosen_index = 0;
     
    496558        }
    497559
    498         status = smbsock_connect_recv(subreq, &fd, &port);
     560        status = smbsock_connect_recv(subreq, &fd, &chosen_port);
    499561
    500562        TALLOC_FREE(subreq);
     
    507569                TALLOC_FREE(state->requests);
    508570                state->fd = fd;
    509                 state->port = port;
     571                state->chosen_port = chosen_port;
    510572                state->chosen_index = chosen_index;
    511573                tevent_req_done(req);
     
    529591
    530592NTSTATUS smbsock_any_connect_recv(struct tevent_req *req, int *pfd,
    531                                   size_t *chosen_index, uint16_t *port)
     593                                  size_t *chosen_index,
     594                                  uint16_t *chosen_port)
    532595{
    533596        struct smbsock_any_connect_state *state = tevent_req_data(
     
    542605                *chosen_index = state->chosen_index;
    543606        }
    544         if (port != NULL) {
    545                 *port = state->port;
     607        if (chosen_port != NULL) {
     608                *chosen_port = state->chosen_port;
    546609        }
    547610        return NT_STATUS_OK;
     
    549612
    550613NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs,
    551                              const char **called_names, size_t num_addrs,
    552                              int *pfd, size_t *chosen_index, uint16_t *port)
     614                             const char **called_names,
     615                             int *called_types,
     616                             const char **calling_names,
     617                             int *calling_types,
     618                             size_t num_addrs,
     619                             uint16_t port,
     620                             int sec_timeout,
     621                             int *pfd, size_t *chosen_index,
     622                             uint16_t *chosen_port)
    553623{
    554624        TALLOC_CTX *frame = talloc_stackframe();
     
    561631                goto fail;
    562632        }
    563         req = smbsock_any_connect_send(frame, ev, addrs, called_names,
    564                                        num_addrs);
     633        req = smbsock_any_connect_send(frame, ev, addrs,
     634                                       called_names, called_types,
     635                                       calling_names, calling_types,
     636                                       num_addrs, port);
    565637        if (req == NULL) {
    566638                goto fail;
    567639        }
     640        if ((sec_timeout != 0) &&
     641            !tevent_req_set_endtime(
     642                    req, ev, timeval_current_ofs(sec_timeout, 0))) {
     643                goto fail;
     644        }
    568645        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
    569646                goto fail;
    570647        }
    571         status = smbsock_any_connect_recv(req, pfd, chosen_index, port);
     648        status = smbsock_any_connect_recv(req, pfd, chosen_index, chosen_port);
    572649 fail:
    573650        TALLOC_FREE(frame);
  • vendor/current/source3/libsmb/trustdom_cache.c

    r414 r740  
    2121
    2222#include "includes.h"
     23#include "../libcli/security/security.h"
    2324
    2425#undef DBGC_CLASS
     
    9697 **/
    9798 
    98 bool trustdom_cache_store(char* name, char* alt_name, const DOM_SID *sid,
     99bool trustdom_cache_store(char* name, char* alt_name, const struct dom_sid *sid,
    99100                          time_t timeout)
    100101{
     
    142143 **/
    143144
    144 bool trustdom_cache_fetch(const char* name, DOM_SID* sid)
     145bool trustdom_cache_fetch(const char* name, struct dom_sid* sid)
    145146{
    146147        char *key = NULL, *value = NULL;
     
    165166        }
    166167
    167         /* convert sid string representation into DOM_SID structure */
     168        /* convert sid string representation into struct dom_sid structure */
    168169        if(! string_to_sid(sid, value)) {
    169170                sid = NULL;
     
    253254{
    254255        char **domain_names;
    255         DOM_SID *dom_sids;
     256        struct dom_sid *dom_sids;
    256257        uint32 num_domains;
    257258        uint32 last_check;
  • vendor/current/source3/libsmb/trusts_util.c

    r414 r740  
    2121#include "includes.h"
    2222#include "../libcli/auth/libcli_auth.h"
    23 #include "../librpc/gen_ndr/cli_lsa.h"
     23#include "../librpc/gen_ndr/ndr_lsa_c.h"
     24#include "rpc_client/cli_lsarpc.h"
     25#include "rpc_client/cli_netlogon.h"
     26#include "rpc_client/cli_pipe.h"
     27#include "../librpc/gen_ndr/ndr_netlogon.h"
     28#include "secrets.h"
     29#include "passdb.h"
     30#include "libsmb/libsmb.h"
    2431
    2532/*********************************************************
     
    136143bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
    137144                                     char ***domain_names, uint32 *num_domains,
    138                                      DOM_SID **sids )
     145                                     struct dom_sid **sids )
    139146{
    140147        struct policy_handle    pol;
    141         NTSTATUS        result = NT_STATUS_UNSUCCESSFUL;
     148        NTSTATUS status, result;
    142149        fstring         dc_name;
    143150        struct sockaddr_storage dc_ss;
     
    145152        struct cli_state *cli = NULL;
    146153        struct rpc_pipe_client *lsa_pipe = NULL;
    147         bool            retry;
    148154        struct lsa_DomainList dom_list;
    149155        int i;
     156        struct dcerpc_binding_handle *b = NULL;
    150157
    151158        *domain_names = NULL;
     
    163170        /* setup the anonymous connection */
    164171
    165         result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC",
    166                 "", "", "", 0, Undefined, &retry);
    167         if ( !NT_STATUS_IS_OK(result) )
     172        status = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC",
     173                "", "", "", 0, Undefined);
     174        if ( !NT_STATUS_IS_OK(status) )
    168175                goto done;
    169176
    170177        /* open the LSARPC_PIPE */
    171178
    172         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
     179        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
    173180                                          &lsa_pipe);
    174         if (!NT_STATUS_IS_OK(result)) {
    175                 goto done;
    176         }
     181        if (!NT_STATUS_IS_OK(status)) {
     182                goto done;
     183        }
     184
     185        b = lsa_pipe->binding_handle;
    177186
    178187        /* get a handle */
    179188
    180         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
     189        status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
    181190                LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol);
    182         if ( !NT_STATUS_IS_OK(result) )
     191        if ( !NT_STATUS_IS_OK(status) )
    183192                goto done;
    184193
    185194        /* Lookup list of trusted domains */
    186195
    187         result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx,
     196        status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
    188197                                         &pol,
    189198                                         &enum_ctx,
    190199                                         &dom_list,
    191                                          (uint32_t)-1);
    192         if ( !NT_STATUS_IS_OK(result) )
    193                 goto done;
     200                                         (uint32_t)-1,
     201                                         &result);
     202        if ( !NT_STATUS_IS_OK(status) )
     203                goto done;
     204        if (!NT_STATUS_IS_OK(result)) {
     205                status = result;
     206                goto done;
     207        }
    194208
    195209        *num_domains = dom_list.count;
     
    197211        *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains);
    198212        if (!*domain_names) {
    199                 result = NT_STATUS_NO_MEMORY;
    200                 goto done;
    201         }
    202 
    203         *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains);
     213                status = NT_STATUS_NO_MEMORY;
     214                goto done;
     215        }
     216
     217        *sids = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, *num_domains);
    204218        if (!*sids) {
    205                 result = NT_STATUS_NO_MEMORY;
     219                status = NT_STATUS_NO_MEMORY;
    206220                goto done;
    207221        }
     
    219233        }
    220234
    221         return NT_STATUS_IS_OK(result);
     235        return NT_STATUS_IS_OK(status);
    222236}
     237
     238NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine)
     239{
     240        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
     241        struct sockaddr_storage pdc_ss;
     242        fstring dc_name;
     243        struct cli_state *cli = NULL;
     244        struct rpc_pipe_client *netlogon_pipe = NULL;
     245
     246        DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n",
     247                domain));
     248
     249        if (remote_machine == NULL || !strcmp(remote_machine, "*")) {
     250                /* Use the PDC *only* for this */
     251
     252                if ( !get_pdc_ip(domain, &pdc_ss) ) {
     253                        DEBUG(0,("Can't get IP for PDC for domain %s\n", domain));
     254                        goto failed;
     255                }
     256
     257                if ( !name_status_find( domain, 0x1b, 0x20, &pdc_ss, dc_name) )
     258                        goto failed;
     259        } else {
     260                /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */
     261                fstrcpy( dc_name, remote_machine );
     262        }
     263
     264        /* if this next call fails, then give up.  We can't do
     265           password changes on BDC's  --jerry */
     266
     267        if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), dc_name,
     268                                           NULL, 0,
     269                                           "IPC$", "IPC",
     270                                           "", "",
     271                                           "", 0, Undefined))) {
     272                DEBUG(0,("modify_trust_password: Connection to %s failed!\n", dc_name));
     273                nt_status = NT_STATUS_UNSUCCESSFUL;
     274                goto failed;
     275        }
     276
     277        /*
     278         * Ok - we have an anonymous connection to the IPC$ share.
     279         * Now start the NT Domain stuff :-).
     280         */
     281
     282        /* Shouldn't we open this with schannel ? JRA. */
     283
     284        nt_status = cli_rpc_pipe_open_noauth(
     285                cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe);
     286        if (!NT_STATUS_IS_OK(nt_status)) {
     287                DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n",
     288                        dc_name, nt_errstr(nt_status)));
     289                cli_shutdown(cli);
     290                cli = NULL;
     291                goto failed;
     292        }
     293
     294        nt_status = trust_pw_find_change_and_store_it(
     295                netlogon_pipe, netlogon_pipe, domain);
     296
     297        cli_shutdown(cli);
     298        cli = NULL;
     299
     300failed:
     301        if (!NT_STATUS_IS_OK(nt_status)) {
     302                DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n",
     303                        current_timestring(talloc_tos(), False), domain));
     304        }
     305        else
     306                DEBUG(5,("change_trust_account_password: sucess!\n"));
     307
     308        return nt_status;
     309}
  • vendor/current/source3/libsmb/unexpected.c

    r414 r740  
    2020
    2121#include "includes.h"
    22 
    23 static TDB_CONTEXT *tdbd = NULL;
    24 
    25 /* the key type used in the unexpected packet database */
    26 struct unexpected_key {
    27         enum packet_type packet_type;
    28         time_t timestamp;
    29         int count;
     22#include "../lib/util/tevent_ntstatus.h"
     23#include "lib/async_req/async_sock.h"
     24#include "libsmb/nmblib.h"
     25
     26static const char *nmbd_socket_dir(void)
     27{
     28        return lp_parm_const_string(-1, "nmbd", "socket dir",
     29                                    get_dyn_NMBDSOCKETDIR());
     30}
     31
     32struct nb_packet_query {
     33        enum packet_type type;
     34        size_t mailslot_namelen;
     35        int trn_id;
    3036};
    3137
    32 /****************************************************************************
    33  All unexpected packets are passed in here, to be stored in a unexpected
    34  packet database. This allows nmblookup and other tools to receive packets
    35  erroneously sent to the wrong port by broken MS systems.
    36 **************************************************************************/
    37 
    38 void unexpected_packet(struct packet_struct *p)
    39 {
    40         static int count;
    41         TDB_DATA kbuf, dbuf;
    42         struct unexpected_key key;
    43         char buf[1024];
    44         int len=0;
    45         uint32_t enc_ip;
    46 
    47         if (!tdbd) {
    48                 tdbd = tdb_open_log(lock_path("unexpected.tdb"), 0,
    49                                TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
    50                                O_RDWR | O_CREAT, 0644);
    51                 if (!tdbd) {
    52                         DEBUG(0,("Failed to open unexpected.tdb\n"));
     38struct nb_packet_client;
     39
     40struct nb_packet_server {
     41        struct tevent_context *ev;
     42        int listen_sock;
     43        int max_clients;
     44        int num_clients;
     45        struct nb_packet_client *clients;
     46};
     47
     48struct nb_packet_client {
     49        struct nb_packet_client *prev, *next;
     50        struct nb_packet_server *server;
     51
     52        enum packet_type type;
     53        int trn_id;
     54        char *mailslot_name;
     55
     56        int sock;
     57        struct tevent_req *read_req;
     58        struct tevent_queue *out_queue;
     59};
     60
     61static int nb_packet_server_destructor(struct nb_packet_server *s);
     62static void nb_packet_server_listener(struct tevent_context *ev,
     63                                      struct tevent_fd *fde,
     64                                      uint16_t flags,
     65                                      void *private_data);
     66
     67NTSTATUS nb_packet_server_create(TALLOC_CTX *mem_ctx,
     68                                 struct tevent_context *ev,
     69                                 int max_clients,
     70                                 struct nb_packet_server **presult)
     71{
     72        struct nb_packet_server *result;
     73        struct tevent_fd *fde;
     74        NTSTATUS status;
     75
     76        result = TALLOC_ZERO_P(mem_ctx, struct nb_packet_server);
     77        if (result == NULL) {
     78                status = NT_STATUS_NO_MEMORY;
     79                goto fail;
     80        }
     81        result->ev = ev;
     82        result->max_clients = max_clients;
     83
     84        result->listen_sock = create_pipe_sock(
     85                nmbd_socket_dir(), "unexpected", 0755);
     86        if (result->listen_sock == -1) {
     87                status = map_nt_error_from_unix(errno);
     88                goto fail;
     89        }
     90        talloc_set_destructor(result, nb_packet_server_destructor);
     91
     92        fde = tevent_add_fd(ev, result, result->listen_sock, TEVENT_FD_READ,
     93                            nb_packet_server_listener, result);
     94        if (fde == NULL) {
     95                status = NT_STATUS_NO_MEMORY;
     96                goto fail;
     97        }
     98
     99        *presult = result;
     100        return NT_STATUS_OK;
     101fail:
     102        TALLOC_FREE(result);
     103        return status;
     104}
     105
     106static int nb_packet_server_destructor(struct nb_packet_server *s)
     107{
     108        if (s->listen_sock != -1) {
     109                close(s->listen_sock);
     110                s->listen_sock = -1;
     111        }
     112        return 0;
     113}
     114
     115static int nb_packet_client_destructor(struct nb_packet_client *c);
     116static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
     117                                     void *private_data);
     118static void nb_packet_got_query(struct tevent_req *req);
     119static void nb_packet_client_read_done(struct tevent_req *req);
     120
     121static void nb_packet_server_listener(struct tevent_context *ev,
     122                                      struct tevent_fd *fde,
     123                                      uint16_t flags,
     124                                      void *private_data)
     125{
     126        struct nb_packet_server *server = talloc_get_type_abort(
     127                private_data, struct nb_packet_server);
     128        struct nb_packet_client *client;
     129        struct tevent_req *req;
     130        struct sockaddr_un sunaddr;
     131        socklen_t len;
     132        int sock;
     133
     134        len = sizeof(sunaddr);
     135
     136        sock = accept(server->listen_sock, (struct sockaddr *)(void *)&sunaddr,
     137                      &len);
     138        if (sock == -1) {
     139                return;
     140        }
     141        DEBUG(6,("accepted socket %d\n", sock));
     142
     143        client = TALLOC_ZERO_P(server, struct nb_packet_client);
     144        if (client == NULL) {
     145                DEBUG(10, ("talloc failed\n"));
     146                close(sock);
     147                return;
     148        }
     149        client->sock = sock;
     150        client->server = server;
     151        talloc_set_destructor(client, nb_packet_client_destructor);
     152
     153        client->out_queue = tevent_queue_create(
     154                client, "unexpected packet output");
     155        if (client->out_queue == NULL) {
     156                DEBUG(10, ("tevent_queue_create failed\n"));
     157                TALLOC_FREE(client);
     158                return;
     159        }
     160
     161        req = read_packet_send(client, ev, client->sock,
     162                               sizeof(struct nb_packet_query),
     163                               nb_packet_client_more, NULL);
     164        if (req == NULL) {
     165                DEBUG(10, ("read_packet_send failed\n"));
     166                TALLOC_FREE(client);
     167                return;
     168        }
     169        tevent_req_set_callback(req, nb_packet_got_query, client);
     170
     171        DLIST_ADD(server->clients, client);
     172        server->num_clients += 1;
     173
     174        if (server->num_clients > server->max_clients) {
     175                DEBUG(10, ("Too many clients, dropping oldest\n"));
     176
     177                /*
     178                 * no TALLOC_FREE here, don't mess with the list structs
     179                 */
     180                talloc_free(server->clients->prev);
     181        }
     182}
     183
     184static ssize_t nb_packet_client_more(uint8_t *buf, size_t buflen,
     185                                     void *private_data)
     186{
     187        struct nb_packet_query q;
     188        if (buflen > sizeof(struct nb_packet_query)) {
     189                return 0;
     190        }
     191        /* Take care of alignment */
     192        memcpy(&q, buf, sizeof(q));
     193        if (q.mailslot_namelen > 1024) {
     194                DEBUG(10, ("Got invalid mailslot namelen %d\n",
     195                           (int)q.mailslot_namelen));
     196                return -1;
     197        }
     198        return q.mailslot_namelen;
     199}
     200
     201static int nb_packet_client_destructor(struct nb_packet_client *c)
     202{
     203        if (c->sock != -1) {
     204                close(c->sock);
     205                c->sock = -1;
     206        }
     207        DLIST_REMOVE(c->server->clients, c);
     208        c->server->num_clients -= 1;
     209        return 0;
     210}
     211
     212static void nb_packet_got_query(struct tevent_req *req)
     213{
     214        struct nb_packet_client *client = tevent_req_callback_data(
     215                req, struct nb_packet_client);
     216        struct nb_packet_query q;
     217        uint8_t *buf;
     218        ssize_t nread, nwritten;
     219        int err;
     220        char c;
     221
     222        nread = read_packet_recv(req, talloc_tos(), &buf, &err);
     223        TALLOC_FREE(req);
     224        if (nread < (ssize_t)sizeof(struct nb_packet_query)) {
     225                DEBUG(10, ("read_packet_recv returned %d (%s)\n",
     226                           (int)nread,
     227                           (nread == -1) ? strerror(err) : "wrong length"));
     228                TALLOC_FREE(client);
     229                return;
     230        }
     231
     232        /* Take care of alignment */
     233        memcpy(&q, buf, sizeof(q));
     234
     235        if (nread != sizeof(struct nb_packet_query) + q.mailslot_namelen) {
     236                DEBUG(10, ("nb_packet_got_query: Invalid mailslot namelength\n"));
     237                TALLOC_FREE(client);
     238                return;
     239        }
     240
     241        client->trn_id = q.trn_id;
     242        client->type = q.type;
     243        if (q.mailslot_namelen > 0) {
     244                client->mailslot_name = talloc_strndup(
     245                        client, (char *)buf + sizeof(q),
     246                        q.mailslot_namelen);
     247                if (client->mailslot_name == NULL) {
     248                        TALLOC_FREE(client);
    53249                        return;
    54250                }
    55251        }
    56252
    57         memset(buf,'\0',sizeof(buf));
    58 
    59         /* Encode the ip addr and port. */
    60         enc_ip = ntohl(p->ip.s_addr);
    61         SIVAL(buf,0,enc_ip);
    62         SSVAL(buf,4,p->port);
    63 
    64         len = build_packet(&buf[6], sizeof(buf)-6, p) + 6;
    65 
    66         ZERO_STRUCT(key);       /* needed for potential alignment */
    67 
    68         key.packet_type = p->packet_type;
    69         key.timestamp = p->timestamp;
    70         key.count = count++;
    71 
    72         kbuf.dptr = (uint8_t *)&key;
    73         kbuf.dsize = sizeof(key);
    74         dbuf.dptr = (uint8_t *)buf;
    75         dbuf.dsize = len;
    76 
    77         tdb_store(tdbd, kbuf, dbuf, TDB_REPLACE);
    78 }
    79 
    80 
    81 static time_t lastt;
    82 
    83 /****************************************************************************
    84  Delete the record if it is too old.
    85 **************************************************************************/
    86 
    87 static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
    88 {
    89         struct unexpected_key key;
    90 
    91         if (kbuf.dsize != sizeof(key)) {
    92                 tdb_delete(ttdb, kbuf);
    93         }
    94 
    95         memcpy(&key, kbuf.dptr, sizeof(key));
    96 
    97         if (lastt - key.timestamp > NMBD_UNEXPECTED_TIMEOUT) {
    98                 tdb_delete(ttdb, kbuf);
    99         }
    100 
     253        /*
     254         * Yes, this is a blocking write of 1 byte into a unix
     255         * domain socket that has never been written to. Highly
     256         * unlikely that this actually blocks.
     257         */
     258        c = 0;
     259        nwritten = sys_write(client->sock, &c, sizeof(c));
     260        if (nwritten != sizeof(c)) {
     261                DEBUG(10, ("Could not write success indicator to client: %s\n",
     262                           strerror(errno)));
     263                TALLOC_FREE(client);
     264                return;
     265        }
     266
     267        client->read_req = read_packet_send(client, client->server->ev,
     268                                            client->sock, 1, NULL, NULL);
     269        if (client->read_req == NULL) {
     270                DEBUG(10, ("Could not activate reader for client exit "
     271                           "detection\n"));
     272                TALLOC_FREE(client);
     273                return;
     274        }
     275        tevent_req_set_callback(client->read_req, nb_packet_client_read_done,
     276                                client);
     277}
     278
     279static void nb_packet_client_read_done(struct tevent_req *req)
     280{
     281        struct nb_packet_client *client = tevent_req_callback_data(
     282                req, struct nb_packet_client);
     283        ssize_t nread;
     284        uint8_t *buf;
     285        int err;
     286
     287        nread = read_packet_recv(req, talloc_tos(), &buf, &err);
     288        TALLOC_FREE(req);
     289        if (nread == 1) {
     290                DEBUG(10, ("Protocol error, received data on write-only "
     291                           "unexpected socket: 0x%2.2x\n", (*buf)));
     292        }
     293        TALLOC_FREE(client);
     294}
     295
     296static void nb_packet_client_send(struct nb_packet_client *client,
     297                                  struct packet_struct *p);
     298
     299void nb_packet_dispatch(struct nb_packet_server *server,
     300                        struct packet_struct *p)
     301{
     302        struct nb_packet_client *c;
     303        uint16_t trn_id;
     304
     305        switch (p->packet_type) {
     306        case NMB_PACKET:
     307                trn_id = p->packet.nmb.header.name_trn_id;
     308                break;
     309        case DGRAM_PACKET:
     310                trn_id = p->packet.dgram.header.dgm_id;
     311                break;
     312        default:
     313                DEBUG(10, ("Got invalid packet type %d\n",
     314                           (int)p->packet_type));
     315                return;
     316        }
     317        for (c = server->clients; c != NULL; c = c->next) {
     318
     319                if (c->type != p->packet_type) {
     320                        DEBUG(10, ("client expects packet %d, got %d\n",
     321                                   c->type, p->packet_type));
     322                        continue;
     323                }
     324
     325                if (p->packet_type == NMB_PACKET) {
     326                        /*
     327                         * See if the client specified transaction
     328                         * ID. Filter if it did.
     329                         */
     330                        if ((c->trn_id != -1) &&
     331                            (c->trn_id != trn_id)) {
     332                                DEBUG(10, ("client expects trn %d, got %d\n",
     333                                           c->trn_id, trn_id));
     334                                continue;
     335                        }
     336                } else {
     337                        /*
     338                         * See if the client specified a mailslot
     339                         * name. Filter if it did.
     340                         */
     341                        if ((c->mailslot_name != NULL) &&
     342                            !match_mailslot_name(p, c->mailslot_name)) {
     343                                continue;
     344                        }
     345                }
     346                nb_packet_client_send(c, p);
     347        }
     348}
     349
     350struct nb_packet_client_header {
     351        size_t len;
     352        enum packet_type type;
     353        time_t timestamp;
     354        struct in_addr ip;
     355        int port;
     356};
     357
     358struct nb_packet_client_state {
     359        struct nb_packet_client *client;
     360        struct iovec iov[2];
     361        struct nb_packet_client_header hdr;
     362        char buf[1024];
     363};
     364
     365static void nb_packet_client_send_done(struct tevent_req *req);
     366
     367static void nb_packet_client_send(struct nb_packet_client *client,
     368                                  struct packet_struct *p)
     369{
     370        struct nb_packet_client_state *state;
     371        struct tevent_req *req;
     372
     373        if (tevent_queue_length(client->out_queue) > 10) {
     374                /*
     375                 * Skip clients that don't listen anyway, some form of DoS
     376                 * protection
     377                 */
     378                return;
     379        }
     380
     381        state = TALLOC_ZERO_P(client, struct nb_packet_client_state);
     382        if (state == NULL) {
     383                DEBUG(10, ("talloc failed\n"));
     384                return;
     385        }
     386
     387        state->client = client;
     388
     389        state->hdr.ip = p->ip;
     390        state->hdr.port = p->port;
     391        state->hdr.timestamp = p->timestamp;
     392        state->hdr.type = p->packet_type;
     393        state->hdr.len = build_packet(state->buf, sizeof(state->buf), p);
     394
     395        state->iov[0].iov_base = (char *)&state->hdr;
     396        state->iov[0].iov_len = sizeof(state->hdr);
     397        state->iov[1].iov_base = state->buf;
     398        state->iov[1].iov_len = state->hdr.len;
     399
     400        TALLOC_FREE(client->read_req);
     401
     402        req = writev_send(client, client->server->ev, client->out_queue,
     403                          client->sock, true, state->iov, 2);
     404        if (req == NULL) {
     405                DEBUG(10, ("writev_send failed\n"));
     406                return;
     407        }
     408        tevent_req_set_callback(req, nb_packet_client_send_done, state);
     409}
     410
     411static void nb_packet_client_send_done(struct tevent_req *req)
     412{
     413        struct nb_packet_client_state *state = tevent_req_callback_data(
     414                req, struct nb_packet_client_state);
     415        struct nb_packet_client *client = state->client;
     416        ssize_t nwritten;
     417        int err;
     418
     419        nwritten = writev_recv(req, &err);
     420
     421        TALLOC_FREE(req);
     422        TALLOC_FREE(state);
     423
     424        if (nwritten == -1) {
     425                DEBUG(10, ("writev failed: %s\n", strerror(err)));
     426                TALLOC_FREE(client);
     427        }
     428
     429        if (tevent_queue_length(client->out_queue) == 0) {
     430                client->read_req = read_packet_send(client, client->server->ev,
     431                                                    client->sock, 1,
     432                                                    NULL, NULL);
     433                if (client->read_req == NULL) {
     434                        DEBUG(10, ("Could not activate reader for client exit "
     435                                   "detection\n"));
     436                        TALLOC_FREE(client);
     437                        return;
     438                }
     439                tevent_req_set_callback(client->read_req,
     440                                        nb_packet_client_read_done,
     441                                        client);
     442        }
     443}
     444
     445struct nb_packet_reader {
     446        int sock;
     447};
     448
     449struct nb_packet_reader_state {
     450        struct tevent_context *ev;
     451        struct sockaddr_un addr;
     452        struct nb_packet_query query;
     453        const char *mailslot_name;
     454        struct iovec iov[2];
     455        char c;
     456        struct nb_packet_reader *reader;
     457};
     458
     459static int nb_packet_reader_destructor(struct nb_packet_reader *r);
     460static void nb_packet_reader_connected(struct tevent_req *subreq);
     461static void nb_packet_reader_sent_query(struct tevent_req *subreq);
     462static void nb_packet_reader_got_ack(struct tevent_req *subreq);
     463
     464struct tevent_req *nb_packet_reader_send(TALLOC_CTX *mem_ctx,
     465                                         struct tevent_context *ev,
     466                                         enum packet_type type,
     467                                         int trn_id,
     468                                         const char *mailslot_name)
     469{
     470        struct tevent_req *req, *subreq;
     471        struct nb_packet_reader_state *state;
     472        char *path;
     473
     474        req = tevent_req_create(mem_ctx, &state,
     475                                struct nb_packet_reader_state);
     476        if (req == NULL) {
     477                return NULL;
     478        }
     479        state->ev = ev;
     480        state->query.trn_id = trn_id;
     481        state->query.type = type;
     482        state->mailslot_name = mailslot_name;
     483
     484        if (mailslot_name != NULL) {
     485                state->query.mailslot_namelen = strlen(mailslot_name);
     486        }
     487
     488        state->reader = TALLOC_ZERO_P(state, struct nb_packet_reader);
     489        if (tevent_req_nomem(state->reader, req)) {
     490                return tevent_req_post(req, ev);
     491        }
     492
     493        path = talloc_asprintf(talloc_tos(), "%s/%s", nmbd_socket_dir(),
     494                               "unexpected");
     495        if (tevent_req_nomem(path, req)) {
     496                return tevent_req_post(req, ev);
     497        }
     498        state->addr.sun_family = AF_UNIX;
     499        strlcpy(state->addr.sun_path, path, sizeof(state->addr.sun_path));
     500        TALLOC_FREE(path);
     501
     502        state->reader->sock = socket(AF_UNIX, SOCK_STREAM, 0);
     503        if (state->reader->sock == -1) {
     504                tevent_req_nterror(req, map_nt_error_from_unix(errno));
     505                return tevent_req_post(req, ev);
     506        }
     507        talloc_set_destructor(state->reader, nb_packet_reader_destructor);
     508
     509        subreq = async_connect_send(state, ev, state->reader->sock,
     510                                    (struct sockaddr *)(void *)&state->addr,
     511                                    sizeof(state->addr));
     512        if (tevent_req_nomem(subreq, req)) {
     513                return tevent_req_post(req, ev);
     514        }
     515        tevent_req_set_callback(subreq, nb_packet_reader_connected, req);
     516        return req;
     517}
     518
     519static int nb_packet_reader_destructor(struct nb_packet_reader *r)
     520{
     521        if (r->sock != -1) {
     522                close(r->sock);
     523                r->sock = -1;
     524        }
    101525        return 0;
    102526}
    103527
    104 
    105 /****************************************************************************
    106  Delete all old unexpected packets.
    107 **************************************************************************/
    108 
    109 void clear_unexpected(time_t t)
    110 {
    111         if (!tdbd) return;
    112 
    113         if ((lastt != 0) && (t < lastt + NMBD_UNEXPECTED_TIMEOUT))
    114                 return;
    115 
    116         lastt = t;
    117 
    118         tdb_traverse(tdbd, traverse_fn, NULL);
    119 }
    120 
    121 struct receive_unexpected_state {
    122         struct packet_struct *matched_packet;
    123         int match_id;
    124         enum packet_type match_type;
    125         const char *match_name;
     528static void nb_packet_reader_connected(struct tevent_req *subreq)
     529{
     530        struct tevent_req *req = tevent_req_callback_data(
     531                subreq, struct tevent_req);
     532        struct nb_packet_reader_state *state = tevent_req_data(
     533                req, struct nb_packet_reader_state);
     534        int res, err;
     535        int num_iovecs = 1;
     536
     537        res = async_connect_recv(subreq, &err);
     538        TALLOC_FREE(subreq);
     539        if (res == -1) {
     540                DEBUG(10, ("async_connect failed: %s\n", strerror(err)));
     541                tevent_req_nterror(req, map_nt_error_from_unix(err));
     542                return;
     543        }
     544
     545        state->iov[0].iov_base = (char *)&state->query;
     546        state->iov[0].iov_len = sizeof(state->query);
     547
     548        if (state->mailslot_name != NULL) {
     549                num_iovecs = 2;
     550                state->iov[1].iov_base = discard_const_p(
     551                        char, state->mailslot_name);
     552                state->iov[1].iov_len = state->query.mailslot_namelen;
     553        }
     554
     555        subreq = writev_send(state, state->ev, NULL, state->reader->sock,
     556                             true, state->iov, num_iovecs);
     557        if (tevent_req_nomem(subreq, req)) {
     558                return;
     559        }
     560        tevent_req_set_callback(subreq, nb_packet_reader_sent_query, req);
     561}
     562
     563static void nb_packet_reader_sent_query(struct tevent_req *subreq)
     564{
     565        struct tevent_req *req = tevent_req_callback_data(
     566                subreq, struct tevent_req);
     567        struct nb_packet_reader_state *state = tevent_req_data(
     568                req, struct nb_packet_reader_state);
     569        ssize_t written;
     570        int err;
     571
     572        written = writev_recv(subreq, &err);
     573        TALLOC_FREE(subreq);
     574        if (written == -1) {
     575                tevent_req_nterror(req, map_nt_error_from_unix(err));
     576                return;
     577        }
     578        if (written != sizeof(state->query) + state->query.mailslot_namelen) {
     579                tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
     580                return;
     581        }
     582        subreq = read_packet_send(state, state->ev, state->reader->sock,
     583                                  sizeof(state->c), NULL, NULL);
     584        if (tevent_req_nomem(subreq, req)) {
     585                return;
     586        }
     587        tevent_req_set_callback(subreq, nb_packet_reader_got_ack, req);
     588}
     589
     590static void nb_packet_reader_got_ack(struct tevent_req *subreq)
     591{
     592        struct tevent_req *req = tevent_req_callback_data(
     593                subreq, struct tevent_req);
     594        struct nb_packet_reader_state *state = tevent_req_data(
     595                req, struct nb_packet_reader_state);
     596        ssize_t nread;
     597        int err;
     598        uint8_t *buf;
     599
     600        nread = read_packet_recv(subreq, state, &buf, &err);
     601        TALLOC_FREE(subreq);
     602        if (nread == -1) {
     603                DEBUG(10, ("read_packet_recv returned %s\n",
     604                           strerror(err)));
     605                tevent_req_nterror(req, map_nt_error_from_unix(err));
     606                return;
     607        }
     608        if (nread != sizeof(state->c)) {
     609                DEBUG(10, ("read = %d, expected %d\n", (int)nread,
     610                           (int)sizeof(state->c)));
     611                tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
     612                return;
     613        }
     614        tevent_req_done(req);
     615}
     616
     617NTSTATUS nb_packet_reader_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     618                               struct nb_packet_reader **preader)
     619{
     620        struct nb_packet_reader_state *state = tevent_req_data(
     621                req, struct nb_packet_reader_state);
     622        NTSTATUS status;
     623
     624        if (tevent_req_is_nterror(req, &status)) {
     625                return status;
     626        }
     627        *preader = talloc_move(mem_ctx, &state->reader);
     628        return NT_STATUS_OK;
     629}
     630
     631struct nb_packet_read_state {
     632        struct nb_packet_client_header hdr;
     633        uint8_t *buf;
     634        size_t buflen;
    126635};
    127636
    128 /****************************************************************************
    129  tdb traversal fn to find a matching 137 packet.
    130 **************************************************************************/
    131 
    132 static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf,
    133                           void *private_data)
    134 {
    135         struct receive_unexpected_state *state =
    136                 (struct receive_unexpected_state *)private_data;
    137         struct unexpected_key key;
    138         struct in_addr ip;
    139         uint32_t enc_ip;
    140         int port;
    141         struct packet_struct *p;
    142 
    143         if (kbuf.dsize != sizeof(key)) {
     637static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p);
     638static void nb_packet_read_done(struct tevent_req *subreq);
     639
     640struct tevent_req *nb_packet_read_send(TALLOC_CTX *mem_ctx,
     641                                       struct tevent_context *ev,
     642                                       struct nb_packet_reader *reader)
     643{
     644        struct tevent_req *req, *subreq;
     645        struct nb_packet_read_state *state;
     646
     647        req = tevent_req_create(mem_ctx, &state, struct nb_packet_read_state);
     648        if (req == NULL) {
     649                return NULL;
     650        }
     651        subreq = read_packet_send(state, ev, reader->sock,
     652                                  sizeof(struct nb_packet_client_header),
     653                                  nb_packet_read_more, state);
     654        if (tevent_req_nomem(subreq, req)) {
     655                return tevent_req_post(req, ev);
     656        }
     657        tevent_req_set_callback(subreq, nb_packet_read_done, req);
     658        return req;
     659}
     660
     661static ssize_t nb_packet_read_more(uint8_t *buf, size_t buflen, void *p)
     662{
     663        struct nb_packet_read_state *state = talloc_get_type_abort(
     664                p, struct nb_packet_read_state);
     665
     666        if (buflen > sizeof(struct nb_packet_client_header)) {
     667                /*
     668                 * Been here, done
     669                 */
    144670                return 0;
    145671        }
    146 
    147         memcpy(&key, kbuf.dptr, sizeof(key));
    148 
    149         if (key.packet_type != state->match_type) return 0;
    150 
    151         if (dbuf.dsize < 6) {
    152                 return 0;
    153         }
    154 
    155         /* Decode the ip addr and port. */
    156         enc_ip = IVAL(dbuf.dptr,0);
    157         ip.s_addr = htonl(enc_ip);
    158         port = SVAL(dbuf.dptr,4);
    159 
    160         p = parse_packet((char *)&dbuf.dptr[6],
    161                         dbuf.dsize-6,
    162                         state->match_type,
    163                         ip,
    164                         port);
    165         if (!p)
    166                 return 0;
    167 
    168         if ((state->match_type == NMB_PACKET &&
    169              p->packet.nmb.header.name_trn_id == state->match_id) ||
    170             (state->match_type == DGRAM_PACKET &&
    171              match_mailslot_name(p, state->match_name))) {
    172                 state->matched_packet = p;
    173                 return -1;
    174         }
    175 
    176         free_packet(p);
    177 
    178         return 0;
    179 }
    180 
    181 /****************************************************************************
    182  Check for a particular packet in the unexpected packet queue.
    183 **************************************************************************/
    184 
    185 struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
    186                                          const char *mailslot_name)
    187 {
    188         TDB_CONTEXT *tdb2;
    189         struct receive_unexpected_state state;
    190 
    191         tdb2 = tdb_open_log(lock_path("unexpected.tdb"), 0, 0, O_RDONLY, 0);
    192         if (!tdb2) return NULL;
    193 
    194         state.matched_packet = NULL;
    195         state.match_id = id;
    196         state.match_type = packet_type;
    197         state.match_name = mailslot_name;
    198 
    199         tdb_traverse(tdb2, traverse_match, &state);
    200 
    201         tdb_close(tdb2);
    202 
    203         return state.matched_packet;
    204 }
     672        memcpy(&state->hdr, buf, sizeof(struct nb_packet_client_header));
     673        return state->hdr.len;
     674}
     675
     676static void nb_packet_read_done(struct tevent_req *subreq)
     677{
     678        struct tevent_req *req = tevent_req_callback_data(
     679                subreq, struct tevent_req);
     680        struct nb_packet_read_state *state = tevent_req_data(
     681                req, struct nb_packet_read_state);
     682        ssize_t nread;
     683        int err;
     684
     685        nread = read_packet_recv(subreq, state, &state->buf, &err);
     686        if (nread == -1) {
     687                tevent_req_nterror(req, map_nt_error_from_unix(err));
     688                return;
     689        }
     690        state->buflen = nread;
     691        tevent_req_done(req);
     692}
     693
     694NTSTATUS nb_packet_read_recv(struct tevent_req *req,
     695                             struct packet_struct **ppacket)
     696{
     697        struct nb_packet_read_state *state = tevent_req_data(
     698                req, struct nb_packet_read_state);
     699        struct nb_packet_client_header hdr;
     700        struct packet_struct *packet;
     701        NTSTATUS status;
     702
     703        if (tevent_req_is_nterror(req, &status)) {
     704                return status;
     705        }
     706
     707        memcpy(&hdr, state->buf, sizeof(hdr));
     708
     709        packet = parse_packet(
     710                (char *)state->buf + sizeof(struct nb_packet_client_header),
     711                state->buflen - sizeof(struct nb_packet_client_header),
     712                state->hdr.type, state->hdr.ip, state->hdr.port);
     713        if (packet == NULL) {
     714                return NT_STATUS_INVALID_NETWORK_RESPONSE;
     715        }
     716        *ppacket = packet;
     717        return NT_STATUS_OK;
     718}
Note: See TracChangeset for help on using the changeset viewer.