*/
#include "includes.h"
+#include "smbd/globals.h"
-extern struct auth_context *negprot_global_auth_context;
-extern bool global_encrypted_passwords_negotiated;
-extern bool global_spnego_negotiated;
extern enum protocol_types Protocol;
-extern int max_send;
-uint32 global_client_caps = 0;
+/* For split krb5 SPNEGO blobs. */
+struct pending_auth_data {
+ struct pending_auth_data *prev, *next;
+ uint16 vuid; /* Tag for this entry. */
+ uint16 smbpid; /* Alternate tag for this entry. */
+ size_t needed_len;
+ DATA_BLOB partial_data;
+};
/*
on a logon error possibly map the error to success if "map to guest"
if (tmp == -1) return -1;
result += tmp;
- if (asprintf(&lanman, "Samba %s", SAMBA_VERSION_STRING) != -1) {
+ if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
SAFE_FREE(lanman);
}
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,
- const uint8 *inbuf)
-{
- if (!server_info->guest && !srv_signing_started()) {
- /* We need to start the signing engine
- * here but a W2K client sends the old
- * "BSRSPYL " signature instead of the
- * correct one. Subsequent packets will
- * be correct.
- */
- srv_check_sign_mac((char *)inbuf, False);
- }
-}
-
/****************************************************************************
Send a security blob via a session setup reply.
****************************************************************************/
bool map_domainuser_to_guest = False;
bool username_was_mapped;
struct PAC_LOGON_INFO *logon_info = NULL;
+ struct smbd_server_connection *sconn = smbd_server_conn;
ZERO_STRUCT(ticket);
ZERO_STRUCT(ap_rep);
DEBUG(3,("Doesn't look like a valid principal\n"));
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- SAFE_FREE(client);
talloc_destroy(mem_ctx);
reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
return;
if (!lp_allow_trusted_domains()) {
data_blob_free(&ap_rep);
data_blob_free(&session_key);
- SAFE_FREE(client);
talloc_destroy(mem_ctx);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
/* lookup the passwd struct, create a new user if necessary */
- username_was_mapped = map_username( user );
+ username_was_mapped = map_username(sconn, user);
pw = smb_getpwnam( mem_ctx, user, real_username, True );
if ( !pw ) {
DEBUG(1,("Username %s is invalid on this system\n",
user));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
if ( !NT_STATUS_IS_OK(ret) ) {
DEBUG(1,("make_server_info_info3 failed: %s!\n",
nt_errstr(ret)));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
if ( !NT_STATUS_IS_OK(ret) ) {
DEBUG(1,("make_server_info_pw failed: %s!\n",
nt_errstr(ret)));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE(mem_ctx);
if ( !NT_STATUS_IS_OK(ret) ) {
DEBUG(10,("failed to create local token: %s\n",
nt_errstr(ret)));
- SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
TALLOC_FREE( mem_ctx );
}
}
- if (!is_partial_auth_vuid(sess_vuid)) {
- sess_vuid = register_initial_vuid();
+ if (!is_partial_auth_vuid(sconn, sess_vuid)) {
+ sess_vuid = register_initial_vuid(sconn);
}
data_blob_free(&server_info->user_session_key);
* no need to free after this on success. A better interface would copy
* it.... */
- sess_vuid = register_existing_vuid(sess_vuid,
+ sess_vuid = register_existing_vuid(sconn,
+ sess_vuid,
server_info,
nullblob,
client);
- SAFE_FREE(client);
-
reply_outbuf(req, 4, 0);
SSVAL(req->outbuf,smb_uid,sess_vuid);
SSVAL(req->outbuf, smb_uid, sess_vuid);
- sessionsetup_start_signing_engine(server_info, req->inbuf);
/* Successful logon. Keep this vuid. */
*p_invalidate_vuid = False;
}
{
DATA_BLOB response;
struct auth_serversupplied_info *server_info = NULL;
+ struct smbd_server_connection *sconn = smbd_server_conn;
if (NT_STATUS_IS_OK(nt_status)) {
server_info = (*auth_ntlmssp_state)->server_info;
if (NT_STATUS_IS_OK(nt_status)) {
DATA_BLOB nullblob = data_blob_null;
- if (!is_partial_auth_vuid(vuid)) {
+ if (!is_partial_auth_vuid(sconn, vuid)) {
nt_status = NT_STATUS_LOGON_FAILURE;
goto out;
}
(*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
/* register_existing_vuid keeps the server info */
- if (register_existing_vuid(vuid,
+ if (register_existing_vuid(sconn, vuid,
server_info, nullblob,
(*auth_ntlmssp_state)->ntlmssp_state->user) !=
vuid) {
if (server_info->guest) {
SSVAL(req->outbuf,smb_vwv2,1);
}
-
- sessionsetup_start_signing_engine(server_info,
- (uint8 *)req->inbuf);
}
out:
auth_ntlmssp_end(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(nt_status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
}
}
}
DATA_BLOB chal;
char *kerb_mech = NULL;
NTSTATUS status;
+ struct smbd_server_connection *sconn = smbd_server_conn;
status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
#ifdef HAVE_KRB5
if (kerb_mech && ((lp_security()==SEC_ADS) ||
- lp_use_kerberos_keytab()) ) {
+ USE_KERBEROS_KEYTAB) ) {
bool destroy_vuid = True;
reply_spnego_kerberos(req, &secblob, kerb_mech,
vuid, &destroy_vuid);
data_blob_free(&secblob);
if (destroy_vuid) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
}
SAFE_FREE(kerb_mech);
return;
status = auth_ntlmssp_start(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
DATA_BLOB auth_reply = data_blob_null;
DATA_BLOB secblob = data_blob_null;
NTSTATUS status = NT_STATUS_LOGON_FAILURE;
+ struct smbd_server_connection *sconn = smbd_server_conn;
if (!spnego_parse_auth(blob1, &auth)) {
#if 0
file_save("auth.dat", blob1.data, blob1.length);
#endif
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
(unsigned long)secblob.length));
#ifdef HAVE_KRB5
if (kerb_mech && ((lp_security()==SEC_ADS) ||
- lp_use_kerberos_keytab()) ) {
+ USE_KERBEROS_KEYTAB)) {
bool destroy_vuid = True;
reply_spnego_kerberos(req, &secblob, kerb_mech,
vuid, &destroy_vuid);
data_blob_free(&auth);
if (destroy_vuid) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
}
SAFE_FREE(kerb_mech);
return;
if (kerb_mech) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
DEBUG(3,("reply_spnego_auth: network "
"misconfiguration, client sent us a "
"krb5 ticket and kerberos security "
status = auth_ntlmssp_start(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
return;
}
-/****************************************************************************
- List to store partial SPNEGO auth fragments.
-****************************************************************************/
-
-static struct pending_auth_data *pd_list;
-
/****************************************************************************
Delete an entry on the list.
****************************************************************************/
-static void delete_partial_auth(struct pending_auth_data *pad)
+static void delete_partial_auth(struct smbd_server_connection *sconn,
+ struct pending_auth_data *pad)
{
if (!pad) {
return;
}
- DLIST_REMOVE(pd_list, pad);
+ DLIST_REMOVE(sconn->smb1.pd_list, pad);
data_blob_free(&pad->partial_data);
SAFE_FREE(pad);
}
Search for a partial SPNEGO auth fragment matching an smbpid.
****************************************************************************/
-static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
+static struct pending_auth_data *get_pending_auth_data(
+ struct smbd_server_connection *sconn,
+ uint16_t smbpid)
{
struct pending_auth_data *pad;
-
- for (pad = pd_list; pad; pad = pad->next) {
+/*
+ * NOTE: using the smbpid here is completely wrong...
+ * see [MS-SMB]
+ * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
+ */
+ for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
if (pad->smbpid == smbpid) {
break;
}
the blob to be more than 64k.
****************************************************************************/
-static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
- DATA_BLOB *pblob)
+static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
+ uint16 smbpid, uint16 vuid,
+ DATA_BLOB *pblob)
{
struct pending_auth_data *pad = NULL;
ASN1_DATA *data;
size_t needed_len = 0;
- pad = get_pending_auth_data(smbpid);
+ pad = get_pending_auth_data(sconn, smbpid);
/* Ensure we have some data. */
if (pblob->length == 0) {
/* Caller can cope. */
DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
- delete_partial_auth(pad);
+ delete_partial_auth(sconn, pad);
return NT_STATUS_OK;
}
(unsigned int)pad->partial_data.length,
(unsigned int)copy_len ));
- delete_partial_auth(pad);
+ delete_partial_auth(sconn, pad);
return NT_STATUS_INVALID_PARAMETER;
}
data_blob_free(pblob);
*pblob = pad->partial_data;
ZERO_STRUCT(pad->partial_data);
- delete_partial_auth(pad);
+ delete_partial_auth(sconn, pad);
return NT_STATUS_OK;
}
}
pad->smbpid = smbpid;
pad->vuid = vuid;
- DLIST_ADD(pd_list, pad);
+ DLIST_ADD(sconn->smb1.pd_list, pad);
return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
user_struct *vuser = NULL;
NTSTATUS status = NT_STATUS_OK;
uint16 smbpid = req->smbpid;
+ struct smbd_server_connection *sconn = smbd_server_conn;
DEBUG(3,("Doing spnego session setup\n"));
}
/* Did we get a valid vuid ? */
- if (!is_partial_auth_vuid(vuid)) {
+ if (!is_partial_auth_vuid(sconn, vuid)) {
/* No, then try and see if this is an intermediate sessionsetup
* for a large SPNEGO packet. */
- struct pending_auth_data *pad = get_pending_auth_data(smbpid);
+ struct pending_auth_data *pad;
+ pad = get_pending_auth_data(sconn, smbpid);
if (pad) {
DEBUG(10,("reply_sesssetup_and_X_spnego: found "
"pending vuid %u\n",
}
/* Do we have a valid vuid now ? */
- if (!is_partial_auth_vuid(vuid)) {
+ if (!is_partial_auth_vuid(sconn, vuid)) {
/* No, start a new authentication setup. */
- vuid = register_initial_vuid();
+ vuid = register_initial_vuid(sconn);
if (vuid == UID_FIELD_INVALID) {
data_blob_free(&blob1);
reply_nterror(req, nt_status_squash(
}
}
- vuser = get_partial_auth_user_struct(vuid);
+ vuser = get_partial_auth_user_struct(sconn, vuid);
/* This MUST be valid. */
if (!vuser) {
smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
* field is 4k. Bug #4400. JRA.
*/
- status = check_spnego_blob_complete(smbpid, vuid, &blob1);
+ status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
if (!NT_STATUS_IS_OK(status)) {
if (!NT_STATUS_EQUAL(status,
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
/* Real error - kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
}
data_blob_free(&blob1);
reply_nterror(req, nt_status_squash(status));
status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(vuid);
+ invalidate_vuid(sconn, vuid);
data_blob_free(&blob1);
reply_nterror(req, nt_status_squash(status));
return;
return 0;
}
- DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
- "(IP %s)\n", procid_to_pid(&crec->pid), ip));
+ DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
+ "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
&data_blob_null);
const char *native_os;
const char *native_lanman;
const char *primary_domain;
- static bool done_sesssetup = False;
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
uint16 smb_flag2 = req->flags2;
NTSTATUS nt_status;
+ struct smbd_server_connection *sconn = smbd_server_conn;
- bool doencrypt = global_encrypted_passwords_negotiated;
+ bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
START_PROFILE(SMBsesssetupX);
if (req->wct == 12 &&
(req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
- if (!global_spnego_negotiated) {
+ if (!sconn->smb1.negprot.spnego) {
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
"at SPNEGO session setup when it was not "
"negotiated.\n"));
domain, user, get_remote_machine_name()));
if (*user) {
- if (global_spnego_negotiated) {
+ if (sconn->smb1.negprot.spnego) {
/* This has to be here, because this is a perfectly
* valid behaviour for guest logons :-( */
data_blob_free(&nt_resp);
data_blob_clear_free(&plaintext_password);
- map_username(sub_user);
- add_session_user(sub_user);
- add_session_workgroup(domain);
+ map_username(sconn, sub_user);
+ add_session_user(sconn, sub_user);
+ add_session_workgroup(sconn, domain);
/* Then force it to null for the benfit of the code below */
user = "";
}
nt_status = check_guest_password(&server_info);
} else if (doencrypt) {
- if (!negprot_global_auth_context) {
+ struct auth_context *negprot_auth_context = NULL;
+ negprot_auth_context = sconn->smb1.negprot.auth_context;
+ if (!negprot_auth_context) {
DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
"session setup without negprot denied!\n"));
reply_nterror(req, nt_status_squash(
domain,
lm_resp, nt_resp);
if (NT_STATUS_IS_OK(nt_status)) {
- nt_status = negprot_global_auth_context->check_ntlm_password(
- negprot_global_auth_context,
+ nt_status = negprot_auth_context->check_ntlm_password(
+ negprot_auth_context,
user_info,
&server_info);
}
} else {
struct auth_context *plaintext_auth_context = NULL;
- const uint8 *chal;
nt_status = make_auth_context_subsystem(
&plaintext_auth_context);
if (NT_STATUS_IS_OK(nt_status)) {
- chal = plaintext_auth_context->get_ntlm_challenge(
- plaintext_auth_context);
+ uint8_t chal[8];
+
+ plaintext_auth_context->get_ntlm_challenge(
+ plaintext_auth_context, chal);
if (!make_user_info_for_reply(&user_info,
user, domain, chal,
TALLOC_FREE(server_info);
} else {
/* Ignore the initial vuid. */
- sess_vuid = register_initial_vuid();
+ sess_vuid = register_initial_vuid(sconn);
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
return;
}
/* register_existing_vuid keeps the server info */
- sess_vuid = register_existing_vuid(sess_vuid,
+ sess_vuid = register_existing_vuid(sconn, sess_vuid,
server_info,
nt_resp.data ? nt_resp : lm_resp,
sub_user);
/* current_user_info is changed on new vuid */
reload_services( True );
-
- sessionsetup_start_signing_engine(server_info, req->inbuf);
}
data_blob_free(&nt_resp);
SSVAL(req->outbuf,smb_uid,sess_vuid);
SSVAL(req->inbuf,smb_uid,sess_vuid);
+ req->vuid = sess_vuid;
- if (!done_sesssetup)
- max_send = MIN(max_send,smb_bufsize);
-
- done_sesssetup = True;
+ if (!sconn->smb1.sessions.done_sesssetup) {
+ sconn->smb1.sessions.max_send =
+ MIN(sconn->smb1.sessions.max_send,smb_bufsize);
+ }
+ sconn->smb1.sessions.done_sesssetup = true;
END_PROFILE(SMBsesssetupX);
chain_reply(req);