summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/process.c2
-rw-r--r--source3/smbd/sesssetup.c433
2 files changed, 249 insertions, 186 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 1159589e8d..85e061710d 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -749,7 +749,7 @@ static const struct smb_message_struct {
/* 0x70 */ { "SMBtcon",reply_tcon,NULL,0},
/* 0x71 */ { "SMBtdis",reply_tdis,NULL,DO_CHDIR},
/* 0x72 */ { "SMBnegprot",NULL,reply_negprot,0},
-/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,NULL,0},
+/* 0x73 */ { "SMBsesssetupX",NULL,reply_sesssetup_and_X,0},
/* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */
/* 0x75 */ { "SMBtconX",NULL,reply_tcon_and_X,0},
/* 0x76 */ { NULL, NULL, NULL, 0 },
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 70819831f6..e9808e0040 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -60,25 +60,43 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv
Add the standard 'Samba' signature to the end of the session setup.
****************************************************************************/
-static int add_signature(char *outbuf, char *p)
+static int push_signature(uint8 **outbuf)
{
- char *start = p;
- fstring lanman;
+ char *lanman;
+ int result, tmp;
- fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
+ result = 0;
- p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
+ tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
- return PTR_DIFF(p, start);
+ if (tmp == -1) return -1;
+ result += tmp;
+
+ if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
+ tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
+ SAFE_FREE(lanman);
+ }
+ else {
+ tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
+ }
+
+ if (tmp == -1) return -1;
+ result += tmp;
+
+ tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
+
+ if (tmp == -1) return -1;
+ result += tmp;
+
+ return result;
}
/****************************************************************************
Start the signing engine if needed. Don't fail signing here.
****************************************************************************/
-static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
+static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info,
+ const uint8 *inbuf)
{
if (!server_info->guest && !srv_signing_started()) {
/* We need to start the signing engine
@@ -87,7 +105,7 @@ static void sessionsetup_start_signing_engine(const auth_serversupplied_info *se
* correct one. Subsequent packets will
* be correct.
*/
- srv_check_sign_mac(inbuf, False);
+ srv_check_sign_mac((char *)inbuf, False);
}
}
@@ -95,36 +113,29 @@ static void sessionsetup_start_signing_engine(const auth_serversupplied_info *se
Send a security blob via a session setup reply.
****************************************************************************/
-static BOOL reply_sesssetup_blob(connection_struct *conn,
- const char *inbuf,
- char *outbuf,
- DATA_BLOB blob,
- NTSTATUS nt_status)
+static void reply_sesssetup_blob(connection_struct *conn,
+ struct smb_request *req,
+ DATA_BLOB blob,
+ NTSTATUS nt_status)
{
- char *p;
-
- if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- ERROR_NT(nt_status_squash(nt_status));
+ if (!NT_STATUS_IS_OK(nt_status) &&
+ !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ reply_nterror(req, nt_status_squash(nt_status));
} else {
- set_message(inbuf,outbuf,4,0,True);
-
nt_status = nt_status_squash(nt_status);
- SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
- SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
- SSVAL(outbuf, smb_vwv3, blob.length);
- p = smb_buf(outbuf);
-
- /* should we cap this? */
- memcpy(p, blob.data, blob.length);
- p += blob.length;
+ SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
+ SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
+ SSVAL(req->outbuf, smb_vwv3, blob.length);
- p += add_signature( outbuf, p );
-
- set_message_end(inbuf,outbuf,p);
+ if ((message_push_blob(&req->outbuf, blob) == -1)
+ || (push_signature(&req->outbuf) == -1)) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ }
}
- show_msg(outbuf);
- return send_smb(smbd_server_fd(),outbuf);
+ show_msg((char *)req->outbuf);
+ send_smb(smbd_server_fd(),(char *)req->outbuf);
+ TALLOC_FREE(req->outbuf);
}
/****************************************************************************
@@ -225,11 +236,11 @@ static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
Reply to a session setup spnego negotiate packet for kerberos.
****************************************************************************/
-static int reply_spnego_kerberos(connection_struct *conn,
- char *inbuf, char *outbuf,
- int length, int bufsize,
- DATA_BLOB *secblob,
- BOOL *p_invalidate_vuid)
+static void reply_spnego_kerberos(connection_struct *conn,
+ struct smb_request *req,
+ DATA_BLOB *secblob,
+ uint16 vuid,
+ BOOL *p_invalidate_vuid)
{
TALLOC_CTX *mem_ctx;
DATA_BLOB ticket;
@@ -261,12 +272,14 @@ static int reply_spnego_kerberos(connection_struct *conn,
mem_ctx = talloc_init("reply_spnego_kerberos");
if (mem_ctx == NULL) {
- return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
+ reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
+ return;
}
if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
talloc_destroy(mem_ctx);
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ return;
}
ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
@@ -319,7 +332,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
#endif
DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));
talloc_destroy(mem_ctx);
- return ERROR_NT(nt_status_squash(ret));
+ reply_nterror(req, nt_status_squash(ret));
+ return;
}
DEBUG(3,("Ticket name is [%s]\n", client));
@@ -331,7 +345,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&session_key);
SAFE_FREE(client);
talloc_destroy(mem_ctx);
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ return;
}
*p = 0;
@@ -352,7 +367,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&session_key);
SAFE_FREE(client);
talloc_destroy(mem_ctx);
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ return;
}
}
@@ -421,7 +438,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
- return ERROR_NT(nt_status_squash(ret));
+ reply_nterror(req, nt_status_squash(ret));
+ return;
}
}
@@ -445,7 +463,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ return;
}
}
@@ -469,7 +489,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
- return ERROR_NT(nt_status_squash(ret));
+ reply_nterror(req, nt_status_squash(ret));
+ return;
}
} else {
@@ -482,7 +503,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
- return ERROR_NT(nt_status_squash(ret));
+ reply_nterror(req, nt_status_squash(ret));
+ return;
}
/* make_server_info_pw does not set the domain. Without this
@@ -507,7 +529,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&session_key);
TALLOC_FREE( mem_ctx );
TALLOC_FREE( server_info );
- return ERROR_NT(nt_status_squash(ret));
+ reply_nterror(req, nt_status_squash(ret));
+ return;
}
}
@@ -518,22 +541,24 @@ static int reply_spnego_kerberos(connection_struct *conn,
SAFE_FREE(client);
+ reply_outbuf(req, 4, 0);
+ SSVAL(req->outbuf,smb_uid,vuid);
+
if (sess_vuid == UID_FIELD_INVALID ) {
ret = NT_STATUS_LOGON_FAILURE;
} else {
/* current_user_info is changed on new vuid */
reload_services( True );
- set_message(inbuf,outbuf,4,0,True);
- SSVAL(outbuf, smb_vwv3, 0);
+ SSVAL(req->outbuf, smb_vwv3, 0);
if (server_info->guest) {
- SSVAL(outbuf,smb_vwv2,1);
+ SSVAL(req->outbuf,smb_vwv2,1);
}
- SSVAL(outbuf, smb_uid, sess_vuid);
+ SSVAL(req->outbuf, smb_uid, sess_vuid);
- sessionsetup_start_signing_engine(server_info, inbuf);
+ sessionsetup_start_signing_engine(server_info, req->inbuf);
}
/* wrap that up in a nice GSS-API wrapping */
@@ -543,15 +568,14 @@ static int reply_spnego_kerberos(connection_struct *conn,
ap_rep_wrapped = data_blob_null;
}
response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
- reply_sesssetup_blob(conn, inbuf, outbuf, response, ret);
+ reply_sesssetup_blob(conn, req, response, ret);
data_blob_free(&ap_rep);
data_blob_free(&ap_rep_wrapped);
data_blob_free(&response);
TALLOC_FREE(mem_ctx);
-
- return -1; /* already replied */
}
+
#endif
/****************************************************************************
@@ -562,13 +586,13 @@ static int reply_spnego_kerberos(connection_struct *conn,
leg of the NTLM auth steps.
***************************************************************************/
-static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
+static void reply_spnego_ntlmssp(connection_struct *conn,
+ struct smb_request *req,
uint16 vuid,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
- DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
- BOOL wrap)
+ DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
+ BOOL wrap)
{
- BOOL ret;
DATA_BLOB response;
struct auth_serversupplied_info *server_info = NULL;
@@ -581,6 +605,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
(*auth_ntlmssp_state)->ntlmssp_state->domain);
}
+ reply_outbuf(req, 4, 0);
+
+ SSVAL(req->outbuf, smb_uid, vuid);
+
if (NT_STATUS_IS_OK(nt_status)) {
int sess_vuid;
DATA_BLOB nullblob = data_blob_null;
@@ -597,16 +625,15 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
/* current_user_info is changed on new vuid */
reload_services( True );
- set_message(inbuf,outbuf,4,0,True);
- SSVAL(outbuf, smb_vwv3, 0);
+ SSVAL(req->outbuf, smb_vwv3, 0);
if (server_info->guest) {
- SSVAL(outbuf,smb_vwv2,1);
+ SSVAL(req->outbuf,smb_vwv2,1);
}
- SSVAL(outbuf,smb_uid,sess_vuid);
+ SSVAL(req->outbuf,smb_uid,sess_vuid);
- sessionsetup_start_signing_engine(server_info, inbuf);
+ sessionsetup_start_signing_engine(server_info, req->inbuf);
}
}
@@ -616,7 +643,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
response = *ntlmssp_blob;
}
- ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status);
+ reply_sesssetup_blob(conn, req, response, nt_status);
if (wrap) {
data_blob_free(&response);
}
@@ -624,14 +651,12 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
/* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
and the other end, that we are not finished yet. */
- if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
/* NB. This is *NOT* an error case. JRA */
auth_ntlmssp_end(auth_ntlmssp_state);
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
}
-
- return ret;
}
/****************************************************************************
@@ -678,13 +703,11 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *
Reply to a session setup spnego negotiate packet.
****************************************************************************/
-static int reply_spnego_negotiate(connection_struct *conn,
- char *inbuf,
- char *outbuf,
- uint16 vuid,
- int length, int bufsize,
- DATA_BLOB blob1,
- AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
+static void reply_spnego_negotiate(connection_struct *conn,
+ struct smb_request *req,
+ uint16 vuid,
+ DATA_BLOB blob1,
+ AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
DATA_BLOB secblob;
DATA_BLOB chal;
@@ -695,7 +718,8 @@ static int reply_spnego_negotiate(connection_struct *conn,
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
- return ERROR_NT(nt_status_squash(status));
+ reply_nterror(req, nt_status_squash(status));
+ return;
}
DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
@@ -703,14 +727,14 @@ static int reply_spnego_negotiate(connection_struct *conn,
#ifdef HAVE_KRB5
if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
BOOL destroy_vuid = True;
- int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
- length, bufsize, &secblob, &destroy_vuid);
+ reply_spnego_kerberos(conn, req, &secblob, vuid,
+ &destroy_vuid);
data_blob_free(&secblob);
if (destroy_vuid) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
}
- return ret;
+ return;
}
#endif
@@ -722,7 +746,8 @@ static int reply_spnego_negotiate(connection_struct *conn,
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
- return ERROR_NT(nt_status_squash(status));
+ reply_nterror(req, nt_status_squash(status));
+ return;
}
status = auth_ntlmssp_update(*auth_ntlmssp_state,
@@ -730,24 +755,24 @@ static int reply_spnego_negotiate(connection_struct *conn,
data_blob_free(&secblob);
- reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
+ reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state,
&chal, status, True);
data_blob_free(&chal);
/* already replied */
- return -1;
+ return;
}
/****************************************************************************
Reply to a session setup spnego auth packet.
****************************************************************************/
-static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
- uint16 vuid,
- int length, int bufsize,
- DATA_BLOB blob1,
- AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
+static void reply_spnego_auth(connection_struct *conn,
+ struct smb_request *req,
+ uint16 vuid,
+ DATA_BLOB blob1,
+ AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
DATA_BLOB auth = data_blob_null;
DATA_BLOB auth_reply = data_blob_null;
@@ -761,7 +786,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
- return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ return;
}
if (auth.data[0] == ASN1_APPLICATION(0)) {
@@ -774,15 +801,15 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
#ifdef HAVE_KRB5
if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
BOOL destroy_vuid = True;
- int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
- length, bufsize, &secblob, &destroy_vuid);
+ reply_spnego_kerberos(conn, req, &secblob,
+ vuid, &destroy_vuid);
data_blob_free(&secblob);
data_blob_free(&auth);
if (destroy_vuid) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
}
- return ret;
+ return;
}
#endif
}
@@ -796,7 +823,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
invalidate_vuid(vuid);
/* auth before negotiatiate? */
- return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ return;
}
status = auth_ntlmssp_update(*auth_ntlmssp_state,
@@ -804,14 +833,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
data_blob_free(&auth);
- reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
+ reply_spnego_ntlmssp(conn, req, vuid,
auth_ntlmssp_state,
&auth_reply, status, True);
data_blob_free(&auth_reply);
/* and tell smbd that we have already replied to this packet */
- return -1;
+ return;
}
/****************************************************************************
@@ -1012,28 +1041,26 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
- char *outbuf,
- int length,int bufsize)
+static void reply_sesssetup_and_X_spnego(connection_struct *conn,
+ struct smb_request *req)
{
uint8 *p;
DATA_BLOB blob1;
- int ret;
size_t bufrem;
fstring native_os, native_lanman, primary_domain;
- char *p2;
- uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
+ const char *p2;
+ uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
enum remote_arch_types ra_type = get_remote_arch();
- int vuid = SVAL(inbuf,smb_uid);
+ int vuid = SVAL(req->inbuf,smb_uid);
user_struct *vuser = NULL;
NTSTATUS status = NT_STATUS_OK;
- uint16 smbpid = SVAL(inbuf,smb_pid);
- uint16 smb_flag2 = SVAL(inbuf, smb_flg2);
+ uint16 smbpid = req->smbpid;
+ uint16 smb_flag2 = req->flags2;
DEBUG(3,("Doing spnego session setup\n"));
if (global_client_caps == 0) {
- global_client_caps = IVAL(inbuf,smb_vwv10);
+ global_client_caps = IVAL(req->inbuf,smb_vwv10);
if (!(global_client_caps & CAP_STATUS32)) {
remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
@@ -1041,14 +1068,15 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
}
- p = (uint8 *)smb_buf(inbuf);
+ p = (uint8 *)smb_buf(req->inbuf);
if (data_blob_len == 0) {
/* an invalid request */
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ return;
}
- bufrem = smb_bufrem(inbuf, p);
+ bufrem = smb_bufrem(req->inbuf, p);
/* pull the spnego blob */
blob1 = data_blob(p, MIN(bufrem, data_blob_len));
@@ -1056,12 +1084,12 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
file_save("negotiate.dat", blob1.data, blob1.length);
#endif
- p2 = inbuf + smb_vwv13 + data_blob_len;
- p2 += srvstr_pull_buf(inbuf, smb_flag2, native_os, p2,
+ p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
+ p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
sizeof(native_os), STR_TERMINATE);
- p2 += srvstr_pull_buf(inbuf, smb_flag2, native_lanman, p2,
+ p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
sizeof(native_lanman), STR_TERMINATE);
- p2 += srvstr_pull_buf(inbuf, smb_flag2, primary_domain, p2,
+ p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
sizeof(primary_domain), STR_TERMINATE);
DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
native_os, native_lanman, primary_domain));
@@ -1097,7 +1125,9 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL);
if (vuid == UID_FIELD_INVALID ) {
data_blob_free(&blob1);
- return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ return;
}
vuser = get_partial_auth_user_struct(vuid);
@@ -1105,11 +1135,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
if (!vuser) {
data_blob_free(&blob1);
- return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ return;
}
- SSVAL(outbuf,smb_uid,vuid);
-
/* Large (greater than 4k) SPNEGO blobs are split into multiple
* sessionsetup requests as the Windows limit on the security blob
* field is 4k. Bug #4400. JRA.
@@ -1122,34 +1152,41 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
invalidate_vuid(vuid);
}
data_blob_free(&blob1);
- return ERROR_NT(nt_status_squash(status));
+ reply_nterror(req, nt_status_squash(status));
+ return;
}
if (blob1.data[0] == ASN1_APPLICATION(0)) {
+
/* its a negTokenTarg packet */
- ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
- &vuser->auth_ntlmssp_state);
+
+ reply_spnego_negotiate(conn, req, vuid, blob1,
+ &vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
- return ret;
+ return;
}
if (blob1.data[0] == ASN1_CONTEXT(1)) {
+
/* its a auth packet */
- ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
- &vuser->auth_ntlmssp_state);
+
+ reply_spnego_auth(conn, req, vuid, blob1,
+ &vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
- return ret;
+ return;
}
if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
DATA_BLOB chal;
+
if (!vuser->auth_ntlmssp_state) {
status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
data_blob_free(&blob1);
- return ERROR_NT(nt_status_squash(status));
+ reply_nterror(req, nt_status_squash(status));
+ return;
}
}
@@ -1158,11 +1195,11 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
data_blob_free(&blob1);
- reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
- &vuser->auth_ntlmssp_state,
- &chal, status, False);
+ reply_spnego_ntlmssp(conn, req, vuid,
+ &vuser->auth_ntlmssp_state,
+ &chal, status, False);
data_blob_free(&chal);
- return -1;
+ return;
}
/* what sort of packet is this? */
@@ -1170,7 +1207,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
data_blob_free(&blob1);
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
/****************************************************************************
@@ -1219,8 +1256,7 @@ static void setup_new_vc_session(void)
Reply to a session setup command.
****************************************************************************/
-int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
- int length,int bufsize)
+void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req)
{
int sess_vuid;
int smb_bufsize;
@@ -1236,75 +1272,88 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
static BOOL done_sesssetup = False;
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
- uint16 smb_flag2 = SVAL(inbuf, smb_flg2);
+ uint16 smb_flag2 = req->flags2;
NTSTATUS nt_status;
BOOL doencrypt = global_encrypted_passwords_negotiated;
DATA_BLOB session_key;
+
+
START_PROFILE(SMBsesssetupX);
ZERO_STRUCT(lm_resp);
ZERO_STRUCT(nt_resp);
ZERO_STRUCT(plaintext_password);
- DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), smb_flag2));
+ DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
/* a SPNEGO session setup has 12 command words, whereas a normal
NT1 session setup has 13. See the cifs spec. */
- if (CVAL(inbuf, smb_wct) == 12 &&
- (smb_flag2 & FLAGS2_EXTENDED_SECURITY)) {
+ if (req->wct == 12 &&
+ (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
+
if (!global_spnego_negotiated) {
- DEBUG(0, ("reply_sesssetup_and_X: Rejecting attempt "
- "at SPNEGO session setup when it was not "
- "negotiated.\n"));
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
+ "at SPNEGO session setup when it was not "
+ "negotiated.\n"));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ return;
}
- if (SVAL(inbuf,smb_vwv4) == 0) {
+ if (SVAL(req->inbuf,smb_vwv4) == 0) {
setup_new_vc_session();
}
- return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
+
+ reply_sesssetup_and_X_spnego(conn, req);
+
+ return;
}
- smb_bufsize = SVAL(inbuf,smb_vwv2);
+ smb_bufsize = SVAL(req->inbuf,smb_vwv2);
if (Protocol < PROTOCOL_NT1) {
- uint16 passlen1 = SVAL(inbuf,smb_vwv7);
+ uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
/* Never do NT status codes with protocols before NT1 as we don't get client caps. */
remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
- if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
- return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
+ if ((passlen1 > MAX_PASS_LEN)
+ || (passlen1 > smb_bufrem(req->inbuf,
+ smb_buf(req->inbuf)))) {
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ return;
}
if (doencrypt) {
- lm_resp = data_blob(smb_buf(inbuf), passlen1);
+ lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
} else {
- plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
+ plaintext_password = data_blob(smb_buf(req->inbuf),
+ passlen1+1);
/* Ensure null termination */
plaintext_password.data[passlen1] = 0;
}
- srvstr_pull_buf(inbuf, smb_flag2, user,
- smb_buf(inbuf)+passlen1, sizeof(user),
+ srvstr_pull_buf(req->inbuf, req->flags2, user,
+ smb_buf(req->inbuf)+passlen1, sizeof(user),
STR_TERMINATE);
*domain = 0;
} else {
- uint16 passlen1 = SVAL(inbuf,smb_vwv7);
- uint16 passlen2 = SVAL(inbuf,smb_vwv8);
+ uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
+ uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
enum remote_arch_types ra_type = get_remote_arch();
- char *p = smb_buf(inbuf);
- char *save_p = smb_buf(inbuf);
+ char *p = smb_buf(req->inbuf);
+ char *save_p = smb_buf(req->inbuf);
uint16 byte_count;
if(global_client_caps == 0) {
- global_client_caps = IVAL(inbuf,smb_vwv11);
+ global_client_caps = IVAL(req->inbuf,smb_vwv11);
if (!(global_client_caps & CAP_STATUS32)) {
remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
@@ -1340,12 +1389,18 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
}
/* check for nasty tricks */
- if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
- return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
+ if (passlen1 > MAX_PASS_LEN
+ || passlen1 > smb_bufrem(req->inbuf, p)) {
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ return;
}
- if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
- return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
+ if (passlen2 > MAX_PASS_LEN
+ || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ return;
}
/* Save the lanman2 password and the NT md4 password. */
@@ -1371,12 +1426,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
if (unic && (passlen2 == 0) && passlen1) {
/* Only a ascii plaintext password was sent. */
- srvstr_pull(inbuf, smb_flag2, pass,
- smb_buf(inbuf), sizeof(pass),
+ srvstr_pull(req->inbuf, req->flags2, pass,
+ smb_buf(req->inbuf), sizeof(pass),
passlen1, STR_TERMINATE|STR_ASCII);
} else {
- srvstr_pull(inbuf, smb_flag2, pass,
- smb_buf(inbuf), sizeof(pass),
+ srvstr_pull(req->inbuf, req->flags2, pass,
+ smb_buf(req->inbuf), sizeof(pass),
unic ? passlen2 : passlen1,
STR_TERMINATE);
}
@@ -1384,13 +1439,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
}
p += passlen1 + passlen2;
- p += srvstr_pull_buf(inbuf, smb_flag2, user, p,
+ p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
sizeof(user), STR_TERMINATE);
- p += srvstr_pull_buf(inbuf, smb_flag2, domain, p,
+ p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
sizeof(domain), STR_TERMINATE);
- p += srvstr_pull_buf(inbuf, smb_flag2, native_os,
+ p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
p, sizeof(native_os), STR_TERMINATE);
- p += srvstr_pull_buf(inbuf, smb_flag2,
+ p += srvstr_pull_buf(req->inbuf, req->flags2,
native_lanman, p, sizeof(native_lanman),
STR_TERMINATE);
@@ -1400,9 +1455,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
the native lanman string. Windows 9x does not include a string here
at all so we have to check if we have any extra bytes left */
- byte_count = SVAL(inbuf, smb_vwv13);
+ byte_count = SVAL(req->inbuf, smb_vwv13);
if ( PTR_DIFF(p, save_p) < byte_count)
- p += srvstr_pull_buf(inbuf, smb_flag2,
+ p += srvstr_pull_buf(req->inbuf, req->flags2,
primary_domain, p,
sizeof(primary_domain),
STR_TERMINATE);
@@ -1421,7 +1476,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
}
- if (SVAL(inbuf,smb_vwv4) == 0) {
+ if (SVAL(req->inbuf,smb_vwv4) == 0) {
setup_new_vc_session();
}
@@ -1433,7 +1488,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
/* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ return;
}
fstrcpy(sub_user, user);
} else {
@@ -1465,7 +1522,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
} else if (doencrypt) {
if (!negprot_global_auth_context) {
DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ return;
}
nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
lm_resp, nt_resp);
@@ -1509,12 +1568,14 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
data_blob_clear_free(&plaintext_password);
- return ERROR_NT(nt_status_squash(nt_status));
+ reply_nterror(req, nt_status_squash(nt_status));
+ return;
}
/* Ensure we can't possible take a code path leading to a null defref. */
if (!server_info) {
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ return;
}
nt_status = create_local_token(server_info);
@@ -1524,7 +1585,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
data_blob_clear_free(&plaintext_password);
- return ERROR_NT(nt_status_squash(nt_status));
+ reply_nterror(req, nt_status_squash(nt_status));
+ return;
}
if (server_info->user_session_key.data) {
@@ -1536,16 +1598,14 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
data_blob_clear_free(&plaintext_password);
/* it's ok - setup a reply */
- set_message(inbuf,outbuf,3,0,True);
+ reply_outbuf(req, 3, 0);
if (Protocol >= PROTOCOL_NT1) {
- char *p = smb_buf( outbuf );
- p += add_signature( outbuf, p );
- set_message_end(inbuf, outbuf, p );
+ push_signature(&req->outbuf);
/* perhaps grab OS version here?? */
}
if (server_info->guest) {
- SSVAL(outbuf,smb_vwv2,1);
+ SSVAL(req->outbuf,smb_vwv2,1);
}
/* register the name and uid as being validated, so further connections
@@ -1563,20 +1623,22 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
- return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ return;
}
/* current_user_info is changed on new vuid */
reload_services( True );
- sessionsetup_start_signing_engine(server_info, inbuf);
+ sessionsetup_start_signing_engine(server_info, req->inbuf);
}
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
- SSVAL(outbuf,smb_uid,sess_vuid);
- SSVAL(inbuf,smb_uid,sess_vuid);
+ SSVAL(req->outbuf,smb_uid,sess_vuid);
+ SSVAL(req->inbuf,smb_uid,sess_vuid);
if (!done_sesssetup)
max_send = MIN(max_send,smb_bufsize);
@@ -1584,5 +1646,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
done_sesssetup = True;
END_PROFILE(SMBsesssetupX);
- return chain_reply(inbuf,&outbuf,length,bufsize);
+ chain_reply_new(req);
+ return;
}