summaryrefslogtreecommitdiff
path: root/source3/smbd/reply.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2012-08-03 08:42:43 +0200
committerStefan Metzmacher <metze@samba.org>2012-08-04 12:33:06 +0200
commitff75fd9eda805d0d937b442f8221be89504131eb (patch)
treeb1c63eaf5f4053057ff81fb7ad60c5f6fe4a038b /source3/smbd/reply.c
parent3a0db4d865d404ce7ab3ae787c163fef951e2dd9 (diff)
downloadsamba-ff75fd9eda805d0d937b442f8221be89504131eb.tar.gz
samba-ff75fd9eda805d0d937b442f8221be89504131eb.tar.bz2
samba-ff75fd9eda805d0d937b442f8221be89504131eb.zip
s3:smbd: setup the application session key with the first tcon on a session
Look for Server.Session.SessionKeyState in [MS-SMB]. The first SMBtconX sets the state to available, which makes it possible to protect the session key at that stage, if client and server support TREE_CONNECT_ANDX_EXTENDED_SIGNATURE. metze
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r--source3/smbd/reply.c86
1 files changed, 85 insertions, 1 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index a89338082f..94c18b0c65 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -721,7 +721,10 @@ void reply_tcon_and_X(struct smb_request *req)
int passlen;
char *path = NULL;
const char *p, *q;
- uint16 tcon_flags;
+ uint16_t tcon_flags;
+ struct smbXsrv_session *session = NULL;
+ NTTIME now = timeval_to_nttime(&req->request_time);
+ bool session_key_updated = false;
struct smbd_server_connection *sconn = req->sconn;
START_PROFILE(SMBtconX);
@@ -812,11 +815,92 @@ void reply_tcon_and_X(struct smb_request *req)
DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
+ nt_status = smb1srv_session_lookup(req->sconn->conn,
+ req->vuid, now, &session);
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
+ reply_force_doserror(req, ERRSRV, ERRbaduid);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
+ reply_nterror(req, nt_status);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+
+ if (session->global->auth_session_info == NULL) {
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+
+ /*
+ * If there is no application key defined yet
+ * we create one.
+ *
+ * This means we setup the application key on the
+ * first tcon that happens via the given session.
+ *
+ * Once the application key is defined, it does not
+ * change any more.
+ */
+ if (session->global->application_key.length == 0 &&
+ session->global->signing_key.length > 0)
+ {
+ struct smbXsrv_session *x = session;
+ struct auth_session_info *session_info =
+ session->global->auth_session_info;
+ uint8_t session_key[16];
+
+ ZERO_STRUCT(session_key);
+ memcpy(session_key, x->global->signing_key.data,
+ MIN(x->global->signing_key.length, sizeof(session_key)));
+
+ /*
+ * The application key is truncated/padded to 16 bytes
+ */
+ x->global->application_key = data_blob_talloc(x->global,
+ session_key,
+ sizeof(session_key));
+ ZERO_STRUCT(session_key);
+ if (x->global->application_key.data == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+
+ /*
+ * Place the application key into the session_info
+ */
+ data_blob_clear_free(&session_info->session_key);
+ session_info->session_key = data_blob_dup_talloc(session_info,
+ x->global->application_key);
+ if (session_info->session_key.data == NULL) {
+ data_blob_clear_free(&x->global->application_key);
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBtconX);
+ return;
+ }
+ session_key_updated = true;
+ }
+
conn = make_connection(sconn, service, client_devicetype,
req->vuid, &nt_status);
req->conn =conn;
if (!conn) {
+ if (session_key_updated) {
+ struct smbXsrv_session *x = session;
+ struct auth_session_info *session_info =
+ session->global->auth_session_info;
+ data_blob_clear_free(&x->global->application_key);
+ data_blob_clear_free(&session_info->session_key);
+ }
reply_nterror(req, nt_status);
END_PROFILE(SMBtconX);
return;