1/* 2 Unix SMB/CIFS implementation. 3 SMB client session context management functions 4 5 Copyright (C) Andrew Tridgell 1994-2005 6 Copyright (C) James Myers 2003 <myersjj@samba.org> 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "libcli/raw/libcliraw.h" 24#include "libcli/raw/raw_proto.h" 25#include "system/filesys.h" 26 27#define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \ 28 req = smbcli_request_setup_session(session, cmd, wct, buflen); \ 29 if (!req) return NULL; \ 30} while (0) 31 32 33/**************************************************************************** 34 Initialize the session context 35****************************************************************************/ 36struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport, 37 TALLOC_CTX *parent_ctx, bool primary, 38 struct smbcli_session_options options) 39{ 40 struct smbcli_session *session; 41 uint16_t flags2; 42 uint32_t capabilities; 43 44 session = talloc_zero(parent_ctx, struct smbcli_session); 45 if (!session) { 46 return NULL; 47 } 48 49 if (primary) { 50 session->transport = talloc_steal(session, transport); 51 } else { 52 session->transport = talloc_reference(session, transport); 53 } 54 session->pid = (uint16_t)getpid(); 55 session->vuid = UID_FIELD_INVALID; 56 session->options = options; 57 58 capabilities = transport->negotiate.capabilities; 59 60 flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES; 61 62 if (capabilities & CAP_UNICODE) { 63 flags2 |= FLAGS2_UNICODE_STRINGS; 64 } 65 if (capabilities & CAP_STATUS32) { 66 flags2 |= FLAGS2_32_BIT_ERROR_CODES; 67 } 68 if (capabilities & CAP_EXTENDED_SECURITY) { 69 flags2 |= FLAGS2_EXTENDED_SECURITY; 70 } 71 if (session->transport->negotiate.sign_info.doing_signing) { 72 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES; 73 } 74 75 session->flags2 = flags2; 76 77 return session; 78} 79 80/**************************************************************************** 81 Perform a session setup (async send) 82****************************************************************************/ 83struct smbcli_request *smb_raw_sesssetup_send(struct smbcli_session *session, 84 union smb_sesssetup *parms) 85{ 86 struct smbcli_request *req = NULL; 87 88 switch (parms->old.level) { 89 case RAW_SESSSETUP_OLD: 90 SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0); 91 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 92 SSVAL(req->out.vwv, VWV(1), 0); 93 SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize); 94 SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max); 95 SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num); 96 SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey); 97 SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length); 98 SIVAL(req->out.vwv,VWV(8), 0); /* reserved */ 99 smbcli_req_append_blob(req, &parms->old.in.password); 100 smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE); 101 smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER); 102 smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE); 103 smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE); 104 break; 105 106 case RAW_SESSSETUP_NT1: 107 SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0); 108 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 109 SSVAL(req->out.vwv, VWV(1), 0); 110 SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize); 111 SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max); 112 SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num); 113 SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey); 114 SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length); 115 SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length); 116 SIVAL(req->out.vwv, VWV(9), 0); /* reserved */ 117 SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities); 118 smbcli_req_append_blob(req, &parms->nt1.in.password1); 119 smbcli_req_append_blob(req, &parms->nt1.in.password2); 120 smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE); 121 smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER); 122 smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE); 123 smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE); 124 break; 125 126 case RAW_SESSSETUP_SPNEGO: 127 SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0); 128 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 129 SSVAL(req->out.vwv, VWV(1), 0); 130 SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize); 131 SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max); 132 SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num); 133 SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey); 134 SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length); 135 SIVAL(req->out.vwv, VWV(8), 0); /* reserved */ 136 SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities); 137 smbcli_req_append_blob(req, &parms->spnego.in.secblob); 138 smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE); 139 smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE); 140 smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE); 141 break; 142 143 case RAW_SESSSETUP_SMB2: 144 return NULL; 145 } 146 147 if (!smbcli_request_send(req)) { 148 smbcli_request_destroy(req); 149 return NULL; 150 } 151 152 return req; 153} 154 155 156/**************************************************************************** 157 Perform a session setup (async recv) 158****************************************************************************/ 159NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, 160 TALLOC_CTX *mem_ctx, 161 union smb_sesssetup *parms) 162{ 163 uint16_t len; 164 uint8_t *p; 165 166 if (!smbcli_request_receive(req)) { 167 return smbcli_request_destroy(req); 168 } 169 170 if (!NT_STATUS_IS_OK(req->status) && 171 !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) { 172 return smbcli_request_destroy(req); 173 } 174 175 switch (parms->old.level) { 176 case RAW_SESSSETUP_OLD: 177 SMBCLI_CHECK_WCT(req, 3); 178 ZERO_STRUCT(parms->old.out); 179 parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID); 180 parms->old.out.action = SVAL(req->in.vwv, VWV(2)); 181 p = req->in.data; 182 if (p) { 183 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE); 184 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE); 185 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE); 186 } 187 break; 188 189 case RAW_SESSSETUP_NT1: 190 SMBCLI_CHECK_WCT(req, 3); 191 ZERO_STRUCT(parms->nt1.out); 192 parms->nt1.out.vuid = SVAL(req->in.hdr, HDR_UID); 193 parms->nt1.out.action = SVAL(req->in.vwv, VWV(2)); 194 p = req->in.data; 195 if (p) { 196 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE); 197 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE); 198 if (p < (req->in.data + req->in.data_size)) { 199 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE); 200 } 201 } 202 break; 203 204 case RAW_SESSSETUP_SPNEGO: 205 SMBCLI_CHECK_WCT(req, 4); 206 ZERO_STRUCT(parms->spnego.out); 207 parms->spnego.out.vuid = SVAL(req->in.hdr, HDR_UID); 208 parms->spnego.out.action = SVAL(req->in.vwv, VWV(2)); 209 len = SVAL(req->in.vwv, VWV(3)); 210 p = req->in.data; 211 if (!p) { 212 break; 213 } 214 215 parms->spnego.out.secblob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, p, len); 216 p += parms->spnego.out.secblob.length; 217 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE); 218 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE); 219 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE); 220 break; 221 222 case RAW_SESSSETUP_SMB2: 223 req->status = NT_STATUS_INTERNAL_ERROR; 224 break; 225 } 226 227failed: 228 return smbcli_request_destroy(req); 229} 230 231 232/* 233 Perform a session setup (sync interface) 234*/ 235NTSTATUS smb_raw_sesssetup(struct smbcli_session *session, 236 TALLOC_CTX *mem_ctx, union smb_sesssetup *parms) 237{ 238 struct smbcli_request *req = smb_raw_sesssetup_send(session, parms); 239 return smb_raw_sesssetup_recv(req, mem_ctx, parms); 240} 241 242 243/**************************************************************************** 244 Send a ulogoff (async send) 245*****************************************************************************/ 246struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session) 247{ 248 struct smbcli_request *req; 249 250 SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0); 251 252 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE); 253 SSVAL(req->out.vwv, VWV(1), 0); 254 255 if (!smbcli_request_send(req)) { 256 smbcli_request_destroy(req); 257 return NULL; 258 } 259 260 return req; 261} 262 263/**************************************************************************** 264 Send a ulogoff (sync interface) 265*****************************************************************************/ 266NTSTATUS smb_raw_ulogoff(struct smbcli_session *session) 267{ 268 struct smbcli_request *req = smb_raw_ulogoff_send(session); 269 return smbcli_request_simple_recv(req); 270} 271 272 273/**************************************************************************** 274 Send a exit (async send) 275*****************************************************************************/ 276struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session) 277{ 278 struct smbcli_request *req; 279 280 SETUP_REQUEST_SESSION(SMBexit, 0, 0); 281 282 if (!smbcli_request_send(req)) { 283 smbcli_request_destroy(req); 284 return NULL; 285 } 286 287 return req; 288} 289 290/**************************************************************************** 291 Send a exit (sync interface) 292*****************************************************************************/ 293_PUBLIC_ NTSTATUS smb_raw_exit(struct smbcli_session *session) 294{ 295 struct smbcli_request *req = smb_raw_exit_send(session); 296 return smbcli_request_simple_recv(req); 297} 298