*/
#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;
/*
on a logon error possibly map the error to success if "map to guest"
(lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
DEBUG(3,("No such user %s [%s] - using guest account\n",
user, domain));
- status = make_server_info_guest(server_info);
+ status = make_server_info_guest(NULL, server_info);
}
}
if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
DEBUG(3,("Registered username %s for guest access\n",
user));
- status = make_server_info_guest(server_info);
+ status = make_server_info_guest(NULL, server_info);
}
}
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);
}
Send a security blob via a session setup reply.
****************************************************************************/
-static void reply_sesssetup_blob(connection_struct *conn,
- struct smb_request *req,
+static void reply_sesssetup_blob(struct smb_request *req,
DATA_BLOB blob,
NTSTATUS 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 {
- nt_status = nt_status_squash(nt_status);
- 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);
-
- if ((message_push_blob(&req->outbuf, blob) == -1)
- || (push_signature(&req->outbuf) == -1)) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- }
+ return;
}
- show_msg((char *)req->outbuf);
- send_smb(smbd_server_fd(),(char *)req->outbuf);
- TALLOC_FREE(req->outbuf);
+ nt_status = nt_status_squash(nt_status);
+ 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);
+
+ if ((message_push_blob(&req->outbuf, blob) == -1)
+ || (push_signature(&req->outbuf) == -1)) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ }
}
/****************************************************************************
Cerate a clock skew error blob for a Windows client.
****************************************************************************/
-static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
+static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
{
krb5_context context = NULL;
krb5_error_code kerr = 0;
krb5_data reply;
krb5_principal host_princ = NULL;
char *host_princ_s = NULL;
- BOOL ret = False;
+ bool ret = False;
*pblob_out = data_blob_null;
Reply to a session setup spnego negotiate packet for kerberos.
****************************************************************************/
-static void reply_spnego_kerberos(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_kerberos(struct smb_request *req,
DATA_BLOB *secblob,
+ const char *mechOID,
uint16 vuid,
- BOOL *p_invalidate_vuid)
+ bool *p_invalidate_vuid)
{
TALLOC_CTX *mem_ctx;
DATA_BLOB ticket;
fstring user;
int sess_vuid = req->vuid;
NTSTATUS ret = NT_STATUS_OK;
- PAC_DATA *pac_data;
+ struct PAC_DATA *pac_data = NULL;
DATA_BLOB ap_rep, ap_rep_wrapped, response;
auth_serversupplied_info *server_info = NULL;
DATA_BLOB session_key = data_blob_null;
uint8 tok_id[2];
DATA_BLOB nullblob = data_blob_null;
fstring real_username;
- BOOL map_domainuser_to_guest = False;
- BOOL username_was_mapped;
- PAC_LOGON_INFO *logon_info = NULL;
+ bool map_domainuser_to_guest = False;
+ bool username_was_mapped;
+ struct PAC_LOGON_INFO *logon_info = NULL;
ZERO_STRUCT(ticket);
- ZERO_STRUCT(pac_data);
ZERO_STRUCT(ap_rep);
ZERO_STRUCT(ap_rep_wrapped);
ZERO_STRUCT(response);
* -- Looks like this only happens with a KDC. JRA.
*/
- BOOL ok = make_krb5_skew_error(&ap_rep);
+ bool ok = make_krb5_skew_error(&ap_rep);
if (!ok) {
talloc_destroy(mem_ctx);
return ERROR_NT(nt_status_squash(
domain = p+1;
- if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
- unistr2_to_ascii(netbios_domain_name,
- &logon_info->info3.uni_logon_dom,
- sizeof(netbios_domain_name));
+ if (logon_info && logon_info->info3.base.domain.string) {
+ fstrcpy(netbios_domain_name,
+ logon_info->info3.base.domain.string);
domain = netbios_domain_name;
DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
name. And even w2k3 does use ntlmssp if you for example
connect to an ip address. */
- struct winbindd_request wb_request;
- struct winbindd_response wb_response;
- NSS_STATUS wb_result;
-
- ZERO_STRUCT(wb_request);
- ZERO_STRUCT(wb_response);
+ wbcErr wbc_status;
+ struct wbcDomainInfo *info = NULL;
DEBUG(10, ("Mapping [%s] to short name\n", domain));
- fstrcpy(wb_request.domain_name, domain);
+ wbc_status = wbcDomainInfo(domain, &info);
- wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
- &wb_request, &wb_response);
-
- if (wb_result == NSS_STATUS_SUCCESS) {
+ if (WBC_ERROR_IS_OK(wbc_status)) {
fstrcpy(netbios_domain_name,
- wb_response.data.domain_info.name);
- domain = netbios_domain_name;
+ info->short_name);
+ wbcFreeMemory(info);
+ domain = netbios_domain_name;
DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
} else {
- DEBUG(3, ("Could not find short name -- winbind "
- "not running?\n"));
+ DEBUG(3, ("Could not find short name: %s\n",
+ wbcErrorString(wbc_status)));
}
}
if (pw) {
/* if a real user check pam account restrictions */
/* only really perfomed if "obey pam restriction" is true */
- /* do this before an eventual mappign to guest occurs */
+ /* do this before an eventual mapping to guest occurs */
ret = smb_pam_accountcheck(pw->pw_name);
if ( !NT_STATUS_IS_OK(ret)) {
DEBUG(1,("PAM account restriction "
reload_services(True);
if ( map_domainuser_to_guest ) {
- make_server_info_guest(&server_info);
+ make_server_info_guest(NULL, &server_info);
} else if (logon_info) {
/* pass the unmapped username here since map_username()
will be called again from inside make_server_info_info3() */
}
}
- server_info->was_mapped |= username_was_mapped;
+ server_info->nss_token |= username_was_mapped;
/* we need to build the token for the user. make_server_info_guest()
already does this */
if ( !server_info->ptok ) {
ret = create_local_token( server_info );
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);
}
}
+ if (!is_partial_auth_vuid(sess_vuid)) {
+ sess_vuid = register_initial_vuid();
+ }
+
+ data_blob_free(&server_info->user_session_key);
+ server_info->user_session_key = session_key;
+ session_key = data_blob_null;
+
/* register_existing_vuid keeps the server info */
/* register_existing_vuid takes ownership of session_key on success,
* no need to free after this on success. A better interface would copy
* it.... */
- if (!is_partial_auth_vuid(sess_vuid)) {
- sess_vuid = register_initial_vuid();
- }
sess_vuid = register_existing_vuid(sess_vuid,
server_info,
- session_key,
nullblob,
client);
if (sess_vuid == UID_FIELD_INVALID ) {
ret = NT_STATUS_LOGON_FAILURE;
- data_blob_free(&session_key);
} else {
/* current_user_info is changed on new vuid */
reload_services( True );
ap_rep_wrapped = data_blob_null;
}
response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
- OID_KERBEROS5_OLD);
- reply_sesssetup_blob(conn, req, response, ret);
+ mechOID);
+ reply_sesssetup_blob(req, response, ret);
data_blob_free(&ap_rep);
data_blob_free(&ap_rep_wrapped);
leg of the NTLM auth steps.
***************************************************************************/
-static void reply_spnego_ntlmssp(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_ntlmssp(struct smb_request *req,
uint16 vuid,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
- BOOL wrap)
+ const char *OID,
+ bool wrap)
{
DATA_BLOB response;
struct auth_serversupplied_info *server_info = NULL;
if (NT_STATUS_IS_OK(nt_status)) {
DATA_BLOB nullblob = data_blob_null;
- DATA_BLOB session_key =
- data_blob(
- (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
- (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
if (!is_partial_auth_vuid(vuid)) {
- data_blob_free(&session_key);
nt_status = NT_STATUS_LOGON_FAILURE;
goto out;
}
+
+ data_blob_free(&server_info->user_session_key);
+ server_info->user_session_key =
+ data_blob_talloc(
+ server_info,
+ (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
+ (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
+
/* register_existing_vuid keeps the server info */
if (register_existing_vuid(vuid,
- server_info,
- session_key, nullblob,
+ server_info, nullblob,
(*auth_ntlmssp_state)->ntlmssp_state->user) !=
vuid) {
- data_blob_free(&session_key);
nt_status = NT_STATUS_LOGON_FAILURE;
goto out;
}
if (wrap) {
response = spnego_gen_auth_response(ntlmssp_blob,
- nt_status, OID_NTLMSSP);
+ nt_status, OID);
} else {
response = *ntlmssp_blob;
}
- reply_sesssetup_blob(conn, req, response, nt_status);
+ reply_sesssetup_blob(req, response, nt_status);
if (wrap) {
data_blob_free(&response);
}
Is this a krb5 mechanism ?
****************************************************************************/
-NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
- BOOL *p_is_krb5)
+NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
+ DATA_BLOB *pblob_out,
+ char **kerb_mechOID)
{
char *OIDs[ASN1_MAX_OIDS];
int i;
+ NTSTATUS ret = NT_STATUS_OK;
- *p_is_krb5 = False;
+ *kerb_mechOID = NULL;
/* parse out the OIDs and the first sec blob */
if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
#ifdef HAVE_KRB5
if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
- *p_is_krb5 = True;
+ *kerb_mechOID = SMB_STRDUP(OIDs[0]);
+ if (*kerb_mechOID == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ }
}
#endif
for (i=0;OIDs[i];i++) {
DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
- free(OIDs[i]);
+ talloc_free(OIDs[i]);
}
- return NT_STATUS_OK;
+ return ret;
+}
+
+/****************************************************************************
+ Fall back from krb5 to NTLMSSP.
+****************************************************************************/
+
+static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
+ uint16 vuid)
+{
+ DATA_BLOB response;
+
+ reply_outbuf(req, 4, 0);
+ SSVAL(req->outbuf,smb_uid,vuid);
+
+ DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
+ "but set to downgrade to NTLMSSP\n"));
+
+ response = spnego_gen_auth_response(NULL,
+ NT_STATUS_MORE_PROCESSING_REQUIRED,
+ OID_NTLMSSP);
+ reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
+ data_blob_free(&response);
}
/****************************************************************************
Reply to a session setup spnego negotiate packet.
****************************************************************************/
-static void reply_spnego_negotiate(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_negotiate(struct smb_request *req,
uint16 vuid,
DATA_BLOB blob1,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
DATA_BLOB secblob;
DATA_BLOB chal;
- BOOL got_kerberos_mechanism = False;
+ char *kerb_mech = NULL;
NTSTATUS status;
- status = parse_spnego_mechanisms(blob1, &secblob,
- &got_kerberos_mechanism);
+ status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
invalidate_vuid(vuid);
(unsigned long)secblob.length));
#ifdef HAVE_KRB5
- if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
- lp_use_kerberos_keytab()) ) {
- BOOL destroy_vuid = True;
- reply_spnego_kerberos(conn, req, &secblob, vuid,
- &destroy_vuid);
+ if (kerb_mech && ((lp_security()==SEC_ADS) ||
+ 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);
}
+ SAFE_FREE(kerb_mech);
return;
}
#endif
auth_ntlmssp_end(auth_ntlmssp_state);
}
+ if (kerb_mech) {
+ data_blob_free(&secblob);
+ /* The mechtoken is a krb5 ticket, but
+ * we need to fall back to NTLM. */
+ reply_spnego_downgrade_to_ntlmssp(req, vuid);
+ SAFE_FREE(kerb_mech);
+ return;
+ }
+
status = auth_ntlmssp_start(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
data_blob_free(&secblob);
- reply_spnego_ntlmssp(conn, req, vuid, auth_ntlmssp_state,
- &chal, status, True);
+ reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
+ &chal, status, OID_NTLMSSP, true);
data_blob_free(&chal);
Reply to a session setup spnego auth packet.
****************************************************************************/
-static void reply_spnego_auth(connection_struct *conn,
- struct smb_request *req,
+static void reply_spnego_auth(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;
DATA_BLOB secblob = data_blob_null;
- NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+ NTSTATUS status = NT_STATUS_LOGON_FAILURE;
if (!spnego_parse_auth(blob1, &auth)) {
#if 0
invalidate_vuid(vuid);
reply_nterror(req, nt_status_squash(
- NT_STATUS_INVALID_PARAMETER));
+ NT_STATUS_LOGON_FAILURE));
return;
}
if (auth.data[0] == ASN1_APPLICATION(0)) {
/* Might be a second negTokenTarg packet */
+ char *kerb_mech = NULL;
+
+ status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
- BOOL got_krb5_mechanism = False;
- status = parse_spnego_mechanisms(auth, &secblob,
- &got_krb5_mechanism);
- if (NT_STATUS_IS_OK(status)) {
- DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
- (unsigned long)secblob.length));
+ if (!NT_STATUS_IS_OK(status)) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ reply_nterror(req, nt_status_squash(status));
+ return;
+ }
+
+ DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
+ (unsigned long)secblob.length));
#ifdef HAVE_KRB5
- if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
- lp_use_kerberos_keytab()) ) {
- BOOL destroy_vuid = True;
- 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;
+ if (kerb_mech && ((lp_security()==SEC_ADS) ||
+ USE_KERBEROS_KEYTAB)) {
+ bool destroy_vuid = True;
+ reply_spnego_kerberos(req, &secblob, kerb_mech,
+ vuid, &destroy_vuid);
+ data_blob_free(&secblob);
+ data_blob_free(&auth);
+ if (destroy_vuid) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
}
+ SAFE_FREE(kerb_mech);
+ return;
+ }
#endif
+ /* Can't blunder into NTLMSSP auth if we have
+ * a krb5 ticket. */
+
+ if (kerb_mech) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ DEBUG(3,("reply_spnego_auth: network "
+ "misconfiguration, client sent us a "
+ "krb5 ticket and kerberos security "
+ "not enabled\n"));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
+ SAFE_FREE(kerb_mech);
}
}
data_blob_free(&secblob);
if (!*auth_ntlmssp_state) {
- /* Kill the intermediate vuid */
- invalidate_vuid(vuid);
-
- /* auth before negotiatiate? */
- reply_nterror(req, nt_status_squash(
- NT_STATUS_INVALID_PARAMETER));
- return;
+ status = auth_ntlmssp_start(auth_ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
+ reply_nterror(req, nt_status_squash(status));
+ return;
+ }
}
status = auth_ntlmssp_update(*auth_ntlmssp_state,
data_blob_free(&auth);
- reply_spnego_ntlmssp(conn, req, vuid,
+ /* Don't send the mechid as we've already sent this (RFC4178). */
+
+ reply_spnego_ntlmssp(req, vuid,
auth_ntlmssp_state,
- &auth_reply, status, True);
+ &auth_reply, status, NULL, true);
data_blob_free(&auth_reply);
return;
}
-/****************************************************************************
- List to store partial SPNEGO auth fragments.
-****************************************************************************/
-
-static struct pending_auth_data *pd_list;
-
/****************************************************************************
Delete an entry on the list.
****************************************************************************/
DATA_BLOB *pblob)
{
struct pending_auth_data *pad = NULL;
- ASN1_DATA data;
+ ASN1_DATA *data;
size_t needed_len = 0;
pad = get_pending_auth_data(smbpid);
* the data given in this blob is enough.
*/
- asn1_load(&data, *pblob);
- asn1_start_tag(&data, pblob->data[0]);
- if (data.has_error || data.nesting == NULL) {
- asn1_free(&data);
+ data = asn1_init(NULL);
+ if (data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ asn1_load(data, *pblob);
+ asn1_start_tag(data, pblob->data[0]);
+ if (data->has_error || data->nesting == NULL) {
+ asn1_free(data);
/* Let caller catch. */
return NT_STATUS_OK;
}
/* Integer wrap paranoia.... */
- if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
- data.nesting->taglen + data.nesting->start < data.nesting->start) {
+ if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
+ data->nesting->taglen + data->nesting->start < data->nesting->start) {
DEBUG(2,("check_spnego_blob_complete: integer wrap "
"data.nesting->taglen = %u, "
"data.nesting->start = %u\n",
- (unsigned int)data.nesting->taglen,
- (unsigned int)data.nesting->start ));
+ (unsigned int)data->nesting->taglen,
+ (unsigned int)data->nesting->start ));
- asn1_free(&data);
+ asn1_free(data);
return NT_STATUS_INVALID_PARAMETER;
}
/* Total length of the needed asn1 is the tag length
* plus the current offset. */
- needed_len = data.nesting->taglen + data.nesting->start;
- asn1_free(&data);
+ needed_len = data->nesting->taglen + data->nesting->start;
+ asn1_free(data);
DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
"pblob->length = %u\n",
conn POINTER CAN BE NULL HERE !
****************************************************************************/
-static void reply_sesssetup_and_X_spnego(connection_struct *conn,
- struct smb_request *req)
+static void reply_sesssetup_and_X_spnego(struct smb_request *req)
{
- uint8 *p;
+ const uint8 *p;
DATA_BLOB blob1;
size_t bufrem;
- fstring native_os, native_lanman, primary_domain;
+ char *tmp;
+ const char *native_os;
+ const char *native_lanman;
+ const char *primary_domain;
const char *p2;
- uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
+ uint16 data_blob_len = SVAL(req->vwv+7, 0);
enum remote_arch_types ra_type = get_remote_arch();
- int vuid = SVAL(req->inbuf,smb_uid);
+ int vuid = req->vuid;
user_struct *vuser = NULL;
NTSTATUS status = NT_STATUS_OK;
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(req->inbuf,smb_vwv10);
+ global_client_caps = IVAL(req->vwv+10, 0);
if (!(global_client_caps & CAP_STATUS32)) {
remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
}
- p = (uint8 *)smb_buf(req->inbuf);
+ p = req->buf;
if (data_blob_len == 0) {
/* an invalid request */
return;
}
- bufrem = smb_bufrem(req->inbuf, p);
+ bufrem = smbreq_bufrem(req, p);
/* pull the spnego blob */
blob1 = data_blob(p, MIN(bufrem, data_blob_len));
file_save("negotiate.dat", blob1.data, blob1.length);
#endif
- 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(req->inbuf, smb_flag2, native_lanman, p2,
- sizeof(native_lanman), STR_TERMINATE);
- p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
- sizeof(primary_domain), STR_TERMINATE);
+ p2 = (char *)req->buf + data_blob_len;
+
+ p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
+ STR_TERMINATE);
+ native_os = tmp ? tmp : "";
+
+ p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
+ STR_TERMINATE);
+ native_lanman = tmp ? tmp : "";
+
+ p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
+ STR_TERMINATE);
+ primary_domain = tmp ? tmp : "";
+
DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
native_os, native_lanman, primary_domain));
/* its a negTokenTarg packet */
- reply_spnego_negotiate(conn, req, vuid, blob1,
+ reply_spnego_negotiate(req, vuid, blob1,
&vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
return;
/* its a auth packet */
- reply_spnego_auth(conn, req, vuid, blob1,
+ reply_spnego_auth(req, vuid, blob1,
&vuser->auth_ntlmssp_state);
data_blob_free(&blob1);
return;
data_blob_free(&blob1);
- reply_spnego_ntlmssp(conn, req, vuid,
+ reply_spnego_ntlmssp(req, vuid,
&vuser->auth_ntlmssp_state,
- &chal, status, False);
+ &chal, status, OID_NTLMSSP, false);
data_blob_free(&chal);
return;
}
return 0;
}
+ 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);
return 0;
static void setup_new_vc_session(void)
{
+ char addr[INET6_ADDRSTRLEN];
+
DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
"compatible we would close all old resources.\n"));
#if 0
#endif
if (lp_reset_on_zero_vc()) {
connections_forall(shutdown_other_smbds,
- CONST_DISCARD(void *,client_addr()));
+ CONST_DISCARD(void *,
+ client_addr(get_client_fd(),addr,sizeof(addr))));
}
}
Reply to a session setup command.
****************************************************************************/
-void reply_sesssetup_and_X(connection_struct *conn, struct smb_request *req)
+void reply_sesssetup_and_X(struct smb_request *req)
{
int sess_vuid;
int smb_bufsize;
DATA_BLOB lm_resp;
DATA_BLOB nt_resp;
DATA_BLOB plaintext_password;
- fstring user;
+ char *tmp;
+ const char *user;
fstring sub_user; /* Sainitised username for substituion */
- fstring domain;
- fstring native_os;
- fstring native_lanman;
- fstring primary_domain;
- static BOOL done_sesssetup = False;
+ const char *domain;
+ const char *native_os;
+ const char *native_lanman;
+ const char *primary_domain;
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
uint16 smb_flag2 = req->flags2;
NTSTATUS nt_status;
- BOOL doencrypt = global_encrypted_passwords_negotiated;
-
- DATA_BLOB session_key;
+ bool doencrypt = global_encrypted_passwords_negotiated;
START_PROFILE(SMBsesssetupX);
return;
}
- if (SVAL(req->inbuf,smb_vwv4) == 0) {
+ if (SVAL(req->vwv+4, 0) == 0) {
setup_new_vc_session();
}
- reply_sesssetup_and_X_spnego(conn, req);
+ reply_sesssetup_and_X_spnego(req);
END_PROFILE(SMBsesssetupX);
return;
}
- smb_bufsize = SVAL(req->inbuf,smb_vwv2);
+ smb_bufsize = SVAL(req->vwv+2, 0);
if (Protocol < PROTOCOL_NT1) {
- uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
+ uint16 passlen1 = SVAL(req->vwv+7, 0);
/* 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(req->inbuf,
- smb_buf(req->inbuf)))) {
+ if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
reply_nterror(req, nt_status_squash(
NT_STATUS_INVALID_PARAMETER));
END_PROFILE(SMBsesssetupX);
}
if (doencrypt) {
- lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
+ lm_resp = data_blob(req->buf, passlen1);
} else {
- plaintext_password = data_blob(smb_buf(req->inbuf),
- passlen1+1);
+ plaintext_password = data_blob(req->buf, passlen1+1);
/* Ensure null termination */
plaintext_password.data[passlen1] = 0;
}
- srvstr_pull_buf(req->inbuf, req->flags2, user,
- smb_buf(req->inbuf)+passlen1, sizeof(user),
- STR_TERMINATE);
- *domain = 0;
+ srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
+ req->buf + passlen1, STR_TERMINATE);
+ user = tmp ? tmp : "";
+
+ domain = "";
} else {
- uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
- uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
+ uint16 passlen1 = SVAL(req->vwv+7, 0);
+ uint16 passlen2 = SVAL(req->vwv+8, 0);
enum remote_arch_types ra_type = get_remote_arch();
- char *p = smb_buf(req->inbuf);
- char *save_p = smb_buf(req->inbuf);
+ const uint8_t *p = req->buf;
+ const uint8_t *save_p = req->buf;
uint16 byte_count;
if(global_client_caps == 0) {
- global_client_caps = IVAL(req->inbuf,smb_vwv11);
+ global_client_caps = IVAL(req->vwv+11, 0);
if (!(global_client_caps & CAP_STATUS32)) {
remove_from_common_flags2(
/* check for nasty tricks */
if (passlen1 > MAX_PASS_LEN
- || passlen1 > smb_bufrem(req->inbuf, p)) {
+ || passlen1 > smbreq_bufrem(req, p)) {
reply_nterror(req, nt_status_squash(
NT_STATUS_INVALID_PARAMETER));
END_PROFILE(SMBsesssetupX);
}
if (passlen2 > MAX_PASS_LEN
- || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
+ || passlen2 > smbreq_bufrem(req, p+passlen1)) {
reply_nterror(req, nt_status_squash(
NT_STATUS_INVALID_PARAMETER));
END_PROFILE(SMBsesssetupX);
if (doencrypt) {
lm_resp = data_blob(p, passlen1);
nt_resp = data_blob(p+passlen1, passlen2);
- } else {
- pstring pass;
- BOOL unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
-
-#if 0
- /* This was the previous fix. Not sure if it's still
- * valid. JRA. */
- if ((ra_type == RA_WINNT) && (passlen2 == 0)
- && unic && passlen1) {
- /* NT4.0 stuffs up plaintext unicode password
- * lengths... */
- srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
- sizeof(pass), passlen1, STR_TERMINATE);
-#endif
+ } else if (lp_security() != SEC_SHARE) {
+ /*
+ * In share level we should ignore any passwords, so
+ * only read them if we're not.
+ */
+ char *pass = NULL;
+ bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
if (unic && (passlen2 == 0) && passlen1) {
/* Only a ascii plaintext password was sent. */
- srvstr_pull(req->inbuf, req->flags2, pass,
- smb_buf(req->inbuf), sizeof(pass),
- passlen1, STR_TERMINATE|STR_ASCII);
+ (void)srvstr_pull_talloc(talloc_tos(),
+ req->inbuf,
+ req->flags2,
+ &pass,
+ req->buf,
+ passlen1,
+ STR_TERMINATE|STR_ASCII);
} else {
- srvstr_pull(req->inbuf, req->flags2, pass,
- smb_buf(req->inbuf), sizeof(pass),
- unic ? passlen2 : passlen1,
- STR_TERMINATE);
+ (void)srvstr_pull_talloc(talloc_tos(),
+ req->inbuf,
+ req->flags2,
+ &pass,
+ req->buf,
+ unic ? passlen2 : passlen1,
+ STR_TERMINATE);
+ }
+ if (!pass) {
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_INVALID_PARAMETER));
+ END_PROFILE(SMBsesssetupX);
+ return;
}
plaintext_password = data_blob(pass, strlen(pass)+1);
}
p += passlen1 + passlen2;
- p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
- sizeof(user), STR_TERMINATE);
- p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
- sizeof(domain), STR_TERMINATE);
- p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
- p, sizeof(native_os), STR_TERMINATE);
- p += srvstr_pull_buf(req->inbuf, req->flags2,
- native_lanman, p, sizeof(native_lanman),
- STR_TERMINATE);
+
+ p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+ STR_TERMINATE);
+ user = tmp ? tmp : "";
+
+ p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+ STR_TERMINATE);
+ domain = tmp ? tmp : "";
+
+ p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+ STR_TERMINATE);
+ native_os = tmp ? tmp : "";
+
+ p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+ STR_TERMINATE);
+ native_lanman = tmp ? tmp : "";
/* not documented or decoded by Ethereal but there is one more
* string in the extra bytes which is the same as the
* 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(req->inbuf, smb_vwv13);
+ byte_count = SVAL(req->vwv+13, 0);
if ( PTR_DIFF(p, save_p) < byte_count) {
- p += srvstr_pull_buf(req->inbuf, req->flags2,
- primary_domain, p,
- sizeof(primary_domain),
- STR_TERMINATE);
+ p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
+ STR_TERMINATE);
+ primary_domain = tmp ? tmp : "";
} else {
- fstrcpy( primary_domain, "null" );
+ primary_domain = talloc_strdup(talloc_tos(), "null");
}
DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
}
- if (SVAL(req->inbuf,smb_vwv4) == 0) {
+ if (SVAL(req->vwv+4, 0) == 0) {
setup_new_vc_session();
}
reload_services(True);
if (lp_security() == SEC_SHARE) {
- /* in share level we should ignore any passwords */
+ /* In share level we should ignore any passwords */
data_blob_free(&lm_resp);
data_blob_free(&nt_resp);
add_session_user(sub_user);
add_session_workgroup(domain);
/* Then force it to null for the benfit of the code below */
- *user = 0;
+ user = "";
}
if (!*user) {
}
} 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,
return;
}
- nt_status = create_local_token(server_info);
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(10, ("create_local_token failed: %s\n",
- nt_errstr(nt_status)));
- data_blob_free(&nt_resp);
- data_blob_free(&lm_resp);
- data_blob_clear_free(&plaintext_password);
- reply_nterror(req, nt_status_squash(nt_status));
- END_PROFILE(SMBsesssetupX);
- return;
- }
+ if (!server_info->ptok) {
+ nt_status = create_local_token(server_info);
- if (server_info->user_session_key.data) {
- session_key = data_blob(server_info->user_session_key.data,
- server_info->user_session_key.length);
- } else {
- session_key = data_blob_null;
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(10, ("create_local_token failed: %s\n",
+ nt_errstr(nt_status)));
+ data_blob_free(&nt_resp);
+ data_blob_free(&lm_resp);
+ data_blob_clear_free(&plaintext_password);
+ reply_nterror(req, nt_status_squash(nt_status));
+ END_PROFILE(SMBsesssetupX);
+ return;
+ }
}
data_blob_clear_free(&plaintext_password);
if (lp_security() == SEC_SHARE) {
sess_vuid = UID_FIELD_INVALID;
- data_blob_free(&session_key);
TALLOC_FREE(server_info);
} else {
/* Ignore the initial vuid. */
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
- data_blob_free(&session_key);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
END_PROFILE(SMBsesssetupX);
/* register_existing_vuid keeps the server info */
sess_vuid = register_existing_vuid(sess_vuid,
server_info,
- session_key,
nt_resp.data ? nt_resp : lm_resp,
sub_user);
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
- data_blob_free(&session_key);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
END_PROFILE(SMBsesssetupX);