summaryrefslogtreecommitdiff
path: root/libcli/smb
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2016-10-25 15:40:59 +0200
committerAndreas Schneider <asn@cryptomilk.org>2016-11-15 11:00:26 +0100
commit35ed3eeb0670ce90c704ca3aac6f31f81b4750e8 (patch)
treef3380739eec69b09a056702bb2800d7e8d50fa8c /libcli/smb
parent2182817c9705c16e39acae3cf4aff8b1c3d27913 (diff)
downloadsamba-35ed3eeb0670ce90c704ca3aac6f31f81b4750e8.tar.gz
libcli/smb: add smb1cli_session_setup_nt1_send/recv()
This does a session setup for the NT1 protocol (without CAP_EXTENDED_SECURITY). Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'libcli/smb')
-rw-r--r--libcli/smb/smb1cli_session.c308
-rw-r--r--libcli/smb/smbXcli_base.h24
2 files changed, 332 insertions, 0 deletions
diff --git a/libcli/smb/smb1cli_session.c b/libcli/smb/smb1cli_session.c
index 1f6779a6d31..c2ed267797a 100644
--- a/libcli/smb/smb1cli_session.c
+++ b/libcli/smb/smb1cli_session.c
@@ -257,3 +257,311 @@ NTSTATUS smb1cli_session_setup_lm21_recv(struct tevent_req *req,
tevent_req_received(req);
return NT_STATUS_OK;
}
+
+struct smb1cli_session_setup_nt1_state {
+ struct smbXcli_session *session;
+ uint16_t vwv[13];
+ struct iovec *recv_iov;
+ uint8_t *inbuf;
+ uint16_t out_session_id;
+ uint16_t out_action;
+ char *out_native_os;
+ char *out_native_lm;
+ char *out_primary_domain;
+};
+
+static void smb1cli_session_setup_nt1_done(struct tevent_req *subreq);
+
+struct tevent_req *smb1cli_session_setup_nt1_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct smbXcli_conn *conn,
+ uint32_t timeout_msec,
+ uint32_t pid,
+ struct smbXcli_session *session,
+ uint16_t in_buf_size,
+ uint16_t in_mpx_max,
+ uint16_t in_vc_num,
+ uint32_t in_sess_key,
+ const char *in_user,
+ const char *in_domain,
+ const DATA_BLOB in_apassword,
+ const DATA_BLOB in_upassword,
+ uint32_t in_capabilities,
+ const char *in_native_os,
+ const char *in_native_lm)
+{
+ struct tevent_req *req = NULL;
+ struct smb1cli_session_setup_nt1_state *state = NULL;
+ struct tevent_req *subreq = NULL;
+ uint16_t *vwv = NULL;
+ uint8_t *bytes = NULL;
+ size_t align_upassword = 0;
+ size_t apassword_ofs = 0;
+ size_t upassword_ofs = 0;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct smb1cli_session_setup_nt1_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->session = session;
+ vwv = state->vwv;
+
+ if (in_user == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return tevent_req_post(req, ev);
+ }
+
+ if (in_domain == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return tevent_req_post(req, ev);
+ }
+
+ if (in_apassword.length > UINT16_MAX) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return tevent_req_post(req, ev);
+ }
+
+ if (in_upassword.length > UINT16_MAX) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return tevent_req_post(req, ev);
+ }
+
+ if (in_native_os == NULL && in_native_lm != NULL) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
+ return tevent_req_post(req, ev);
+ }
+
+ SCVAL(vwv+0, 0, 0xff);
+ SCVAL(vwv+0, 1, 0);
+ SSVAL(vwv+1, 0, 0);
+ SSVAL(vwv+2, 0, in_buf_size);
+ SSVAL(vwv+3, 0, in_mpx_max);
+ SSVAL(vwv+4, 0, in_vc_num);
+ SIVAL(vwv+5, 0, in_sess_key);
+ SSVAL(vwv+7, 0, in_apassword.length);
+ SSVAL(vwv+8, 0, in_upassword.length);
+ SSVAL(vwv+9, 0, 0); /* reserved */
+ SSVAL(vwv+10, 0, 0); /* reserved */
+ SIVAL(vwv+11, 0, in_capabilities);
+
+ if (in_apassword.length == 0 && in_upassword.length > 0) {
+ /*
+ * This is plaintext auth with a unicode password,
+ * we need to align the buffer.
+ *
+ * This is what smbclient and Windows XP send as
+ * a client. And what smbd expects.
+ *
+ * But it doesn't follow [MS-CIFS] (v20160714)
+ * 2.2.4.53.1 SMB_COM_SESSION_SETUP_ANDX Request:
+ *
+ * ...
+ *
+ * If SMB_FLAGS2_UNICODE is set (1), the value of OEMPasswordLen
+ * MUST be 0x0000 and the password MUST be encoded using
+ * UTF-16LE Unicode. Padding MUST NOT be added to
+ * align this plaintext Unicode string to a word boundary.
+ *
+ * ...
+ */
+ uint16_t security_mode = smb1cli_conn_server_security_mode(conn);
+
+ if (!(security_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) {
+ align_upassword = 1;
+ }
+ }
+
+ bytes = talloc_array(state, uint8_t,
+ in_apassword.length +
+ align_upassword +
+ in_upassword.length);
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
+ }
+ if (in_apassword.length != 0) {
+ memcpy(bytes + apassword_ofs,
+ in_apassword.data,
+ in_apassword.length);
+ upassword_ofs += in_apassword.length;
+ }
+ if (align_upassword != 0) {
+ memset(bytes + upassword_ofs, 0, align_upassword);
+ upassword_ofs += align_upassword;
+ }
+ if (in_upassword.length != 0) {
+ memcpy(bytes + upassword_ofs,
+ in_upassword.data,
+ in_upassword.length);
+ }
+
+ bytes = smb_bytes_push_str(bytes,
+ smbXcli_conn_use_unicode(conn),
+ in_user, strlen(in_user)+1,
+ NULL);
+ bytes = smb_bytes_push_str(bytes,
+ smbXcli_conn_use_unicode(conn),
+ in_domain, strlen(in_domain)+1,
+ NULL);
+ if (in_native_os != NULL) {
+ bytes = smb_bytes_push_str(bytes,
+ smbXcli_conn_use_unicode(conn),
+ in_native_os, strlen(in_native_os)+1,
+ NULL);
+ }
+ if (in_native_lm != NULL) {
+ bytes = smb_bytes_push_str(bytes,
+ smbXcli_conn_use_unicode(conn),
+ in_native_lm, strlen(in_native_lm)+1,
+ NULL);
+ }
+ if (tevent_req_nomem(bytes, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = smb1cli_req_send(state, ev, conn,
+ SMBsesssetupX,
+ 0, /* additional_flags */
+ 0, /* clear_flags */
+ 0, /* additional_flags2 */
+ 0, /* clear_flags2 */
+ timeout_msec,
+ pid,
+ NULL, /* tcon */
+ session,
+ 13, /* wct */
+ vwv,
+ talloc_get_size(bytes),
+ bytes);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, smb1cli_session_setup_nt1_done, req);
+
+ return req;
+}
+
+static void smb1cli_session_setup_nt1_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct smb1cli_session_setup_nt1_state *state =
+ tevent_req_data(req,
+ struct smb1cli_session_setup_nt1_state);
+ NTSTATUS status;
+ uint8_t *inhdr = NULL;
+ uint8_t wct;
+ uint16_t *vwv = NULL;
+ uint32_t num_bytes;
+ uint8_t *bytes = NULL;
+ const uint8_t *p = NULL;
+ size_t ret = 0;
+ uint16_t flags2;
+ bool use_unicode = false;
+ struct smb1cli_req_expected_response expected[] = {
+ {
+ .status = NT_STATUS_OK,
+ .wct = 3,
+ },
+ };
+
+ status = smb1cli_req_recv(subreq, state,
+ &state->recv_iov,
+ &inhdr,
+ &wct,
+ &vwv,
+ NULL, /* pvwv_offset */
+ &num_bytes,
+ &bytes,
+ NULL, /* pbytes_offset */
+ &state->inbuf,
+ expected, ARRAY_SIZE(expected));
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ flags2 = SVAL(inhdr, HDR_FLG2);
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ use_unicode = true;
+ }
+
+ state->out_session_id = SVAL(inhdr, HDR_UID);
+ state->out_action = SVAL(vwv+2, 0);
+
+ p = bytes;
+
+ status = smb_bytes_pull_str(state, &state->out_native_os,
+ use_unicode, p,
+ bytes+num_bytes-p, &ret);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ p += ret;
+
+ status = smb_bytes_pull_str(state, &state->out_native_lm,
+ use_unicode, p,
+ bytes+num_bytes-p, &ret);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ p += ret;
+
+ status = smb_bytes_pull_str(state, &state->out_primary_domain,
+ use_unicode, p,
+ bytes+num_bytes-p, &ret);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ p += ret;
+
+ smb1cli_session_set_id(state->session, state->out_session_id);
+ smb1cli_session_set_action(state->session, state->out_action);
+
+ tevent_req_done(req);
+}
+
+NTSTATUS smb1cli_session_setup_nt1_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct iovec **precv_iov,
+ const uint8_t **precv_inbuf,
+ char **out_native_os,
+ char **out_native_lm,
+ char **out_primary_domain)
+{
+ struct smb1cli_session_setup_nt1_state *state =
+ tevent_req_data(req,
+ struct smb1cli_session_setup_nt1_state);
+ NTSTATUS status;
+ struct iovec *recv_iov = NULL;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
+ return status;
+ }
+
+ recv_iov = talloc_move(mem_ctx, &state->recv_iov);
+ if (precv_iov != NULL) {
+ *precv_iov = recv_iov;
+ }
+ if (precv_inbuf != NULL) {
+ *precv_inbuf = state->inbuf;
+ }
+
+ if (out_native_os != NULL) {
+ *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
+ }
+
+ if (out_native_lm != NULL) {
+ *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
+ }
+
+ if (out_primary_domain != NULL) {
+ *out_primary_domain = talloc_move(mem_ctx,
+ &state->out_primary_domain);
+ }
+
+ tevent_req_received(req);
+ return NT_STATUS_OK;
+}
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index c1a9c701611..ad4272171ed 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -220,6 +220,30 @@ NTSTATUS smb1cli_session_setup_lm21_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
char **out_native_os,
char **out_native_lm);
+struct tevent_req *smb1cli_session_setup_nt1_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct smbXcli_conn *conn,
+ uint32_t timeout_msec,
+ uint32_t pid,
+ struct smbXcli_session *session,
+ uint16_t in_buf_size,
+ uint16_t in_mpx_max,
+ uint16_t in_vc_num,
+ uint32_t in_sess_key,
+ const char *in_user,
+ const char *in_domain,
+ const DATA_BLOB in_apassword,
+ const DATA_BLOB in_upassword,
+ uint32_t in_capabilities,
+ const char *in_native_os,
+ const char *in_native_lm);
+NTSTATUS smb1cli_session_setup_nt1_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct iovec **precv_iov,
+ const uint8_t **precv_inbuf,
+ char **out_native_os,
+ char **out_native_lm,
+ char **out_primary_domain);
struct tevent_req *smb1cli_ntcreatex_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,