#include "includes.h"
extern struct auth_context *negprot_global_auth_context;
-extern BOOL global_encrypted_passwords_negotiated;
-extern BOOL global_spnego_negotiated;
+extern bool global_encrypted_passwords_negotiated;
+extern bool global_spnego_negotiated;
extern enum protocol_types Protocol;
extern int max_send;
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)
{
}
show_msg((char *)req->outbuf);
- send_smb(smbd_server_fd(),(char *)req->outbuf);
+ srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
TALLOC_FREE(req->outbuf);
}
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,
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,
- -1);
+ 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);
-
- wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
- &wb_request, &wb_response);
+ wbc_status = wbcDomainInfo(domain, &info);
- 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)));
}
}
}
}
- server_info->was_mapped |= username_was_mapped;
+ if (username_was_mapped) {
+ server_info->was_mapped = 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);
}
response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
OID_KERBEROS5_OLD);
- reply_sesssetup_blob(conn, req, response, ret);
+ 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 (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);
}
****************************************************************************/
NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
- BOOL *p_is_krb5)
+ bool *p_is_krb5)
{
char *OIDs[ASN1_MAX_OIDS];
int i;
return NT_STATUS_OK;
}
+/****************************************************************************
+ 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;
+ bool got_kerberos_mechanism = False;
NTSTATUS status;
status = parse_spnego_mechanisms(blob1, &secblob,
#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,
+ bool destroy_vuid = True;
+ reply_spnego_kerberos(req, &secblob, vuid,
&destroy_vuid);
data_blob_free(&secblob);
if (destroy_vuid) {
auth_ntlmssp_end(auth_ntlmssp_state);
}
+ if (got_kerberos_mechanism) {
+ 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);
+ 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 */
- BOOL got_krb5_mechanism = False;
+ 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 ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
+ lp_use_kerberos_keytab()) ) {
+ bool destroy_vuid = True;
+ reply_spnego_kerberos(req, &secblob,
+ vuid, &destroy_vuid);
+ data_blob_free(&secblob);
+ data_blob_free(&auth);
+ if (destroy_vuid) {
+ /* Kill the intermediate vuid */
+ invalidate_vuid(vuid);
}
+ return;
+ }
#endif
+ /* Can't blunder into NTLMSSP auth if we have
+ * a krb5 ticket. */
+
+ if (got_krb5_mechanism) {
+ /* 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"));
+ reply_nterror(req, nt_status_squash(
+ NT_STATUS_LOGON_FAILURE));
}
}
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);
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;
DATA_BLOB blob1;
/* 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;
}
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
invalidate_all_vuids();
#endif
if (lp_reset_on_zero_vc()) {
- connections_forall(shutdown_other_smbds, client_addr());
+ connections_forall(shutdown_other_smbds,
+ 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;
fstring native_os;
fstring native_lanman;
fstring primary_domain;
- static BOOL done_sesssetup = False;
+ 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;
- BOOL doencrypt = global_encrypted_passwords_negotiated;
+ bool doencrypt = global_encrypted_passwords_negotiated;
DATA_BLOB session_key;
setup_new_vc_session();
}
- reply_sesssetup_and_X_spnego(conn, req);
+ reply_sesssetup_and_X_spnego(req);
END_PROFILE(SMBsesssetupX);
return;
}
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) {
+ 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,
+ smb_buf(req->inbuf),
+ 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,
+ smb_buf(req->inbuf),
+ 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);
}
done_sesssetup = True;
END_PROFILE(SMBsesssetupX);
- chain_reply_new(req);
+ chain_reply(req);
return;
}