This makes it a little easier for it to writen in terms of GENSEC in future.
Andrew Bartlett
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Günther Deschner <gd@samba.org>
#include "includes.h"
#include "ntlmssp.h"
+struct auth_ntlmssp_state {
+ TALLOC_CTX *mem_ctx;
+ struct auth_context *auth_context;
+ struct auth_serversupplied_info *server_info;
+ struct ntlmssp_state *ntlmssp_state;
+};
+
+NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig)
+{
+ return ntlmssp_sign_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig)
+{
+ return ntlmssp_check_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig)
+{
+ return ntlmssp_seal_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig)
+{
+ return ntlmssp_unseal_packet(auth_ntlmssp_state->ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
+}
+
+bool auth_ntlmssp_negotiated_sign(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return auth_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN;
+}
+
+bool auth_ntlmssp_negotiated_seal(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return auth_ntlmssp_state->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL;
+}
+
+struct auth_serversupplied_info *auth_ntlmssp_server_info(TALLOC_CTX *mem_ctx,
+ struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ struct auth_serversupplied_info *server_info = auth_ntlmssp_state->server_info;
+ 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);
+ if (auth_ntlmssp_state->ntlmssp_state->session_key.length && !server_info->user_session_key.data) {
+ return NULL;
+ }
+ auth_ntlmssp_state->server_info = NULL;
+ return talloc_steal(mem_ctx, server_info);
+}
+
+struct ntlmssp_state *auth_ntlmssp_get_ntlmssp_state(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return auth_ntlmssp_state->ntlmssp_state;
+}
+
+/* Needed for 'map to guest' and 'smb username' processing */
+const char *auth_ntlmssp_get_username(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return auth_ntlmssp_state->ntlmssp_state->user;
+}
+
+const char *auth_ntlmssp_get_domain(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return auth_ntlmssp_state->ntlmssp_state->domain;
+}
+
+const char *auth_ntlmssp_get_client(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return auth_ntlmssp_state->ntlmssp_state->client.netbios_name;
+}
+
/**
* Return the challenge as determined by the authentication subsystem
* @return an 8 byte random challenge
struct auth_init_function_entry *prev, *next;
};
-typedef struct auth_ntlmssp_state {
- TALLOC_CTX *mem_ctx;
- struct auth_context *auth_context;
- struct auth_serversupplied_info *server_info;
- struct ntlmssp_state *ntlmssp_state;
-} AUTH_NTLMSSP_STATE;
+typedef struct auth_ntlmssp_state AUTH_NTLMSSP_STATE;
/* Changed from 1 -> 2 to add the logon_parameters field. */
#define AUTH_INTERFACE_VERSION 2
/* The following definitions come from auth/auth_ntlmssp.c */
-NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state);
-void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state);
-NTSTATUS auth_ntlmssp_update(AUTH_NTLMSSP_STATE *auth_ntlmssp_state,
+struct auth_serversupplied_info *auth_ntlmssp_server_info(TALLOC_CTX *mem_ctx,
+ struct auth_ntlmssp_state *auth_ntlmssp_state);
+struct ntlmssp_state *auth_ntlmssp_get_ntlmssp_state(struct auth_ntlmssp_state *auth_ntlmssp_state);
+const char *auth_ntlmssp_get_username(struct auth_ntlmssp_state *auth_ntlmssp_state);
+const char *auth_ntlmssp_get_domain(struct auth_ntlmssp_state *auth_ntlmssp_state);
+const char *auth_ntlmssp_get_client(struct auth_ntlmssp_state *auth_ntlmssp_state);
+bool auth_ntlmssp_negotiated_sign(struct auth_ntlmssp_state *auth_ntlmssp_state);
+bool auth_ntlmssp_negotiated_seal(struct auth_ntlmssp_state *auth_ntlmssp_state);
+
+NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state);
+void auth_ntlmssp_end(struct auth_ntlmssp_state **auth_ntlmssp_state);
+NTSTATUS auth_ntlmssp_update(struct auth_ntlmssp_state *auth_ntlmssp_state,
const DATA_BLOB request, DATA_BLOB *reply) ;
+NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig);
+NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig) ;
+NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig);
+NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig);
/* The following definitions come from auth/auth_sam.c */
switch (p->auth.auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
/* Data portion is encrypted. */
- status = ntlmssp_seal_packet(
- a->ntlmssp_state,
+ status = auth_ntlmssp_seal_packet(
+ a,
(uint8_t *)prs_data_p(&p->out_data.frag)
+ RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
data_len + ss_padding_len,
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
/* Data is signed. */
- status = ntlmssp_sign_packet(
- a->ntlmssp_state,
+ status = auth_ntlmssp_sign_packet(
+ a,
(unsigned char *)prs_data_p(&p->out_data.frag)
+ RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
data_len + ss_padding_len,
refuse the bind. */
if (p->auth.auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
- if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN)) {
+ if (!auth_ntlmssp_negotiated_sign(a)) {
DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet integrity requested "
"but client declined signing.\n",
get_pipe_name_from_syntax(talloc_tos(),
}
}
if (p->auth.auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
- if (!(a->ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
+ if (!auth_ntlmssp_negotiated_seal(a)) {
DEBUG(0,("pipe_ntlmssp_verify_final: pipe %s : packet privacy requested "
"but client declined sealing.\n",
get_pipe_name_from_syntax(talloc_tos(),
}
DEBUG(5, ("pipe_ntlmssp_verify_final: OK: user: %s domain: %s "
- "workstation: %s\n", a->ntlmssp_state->user,
- a->ntlmssp_state->domain,
- a->ntlmssp_state->client.netbios_name));
-
- if (a->server_info->ptok == NULL) {
- DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
- return False;
- }
+ "workstation: %s\n",
+ auth_ntlmssp_get_username(a),
+ auth_ntlmssp_get_domain(a),
+ auth_ntlmssp_get_client(a)));
TALLOC_FREE(p->server_info);
- p->server_info = copy_serverinfo(p, a->server_info);
+ p->server_info = auth_ntlmssp_server_info(p, a);
if (p->server_info == NULL) {
- DEBUG(0, ("copy_serverinfo failed\n"));
+ DEBUG(0, ("auth_ntlmssp_server_info failed to obtain the server info for authenticated user\n"));
return false;
}
+ if (p->server_info->ptok == NULL) {
+ DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
+ return False;
+ }
+
/*
* We're an authenticated bind over smb, so the session key needs to
* be set to "SystemLibraryDTC". Weird, but this is what Windows
switch (p->auth.auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
/* Data is encrypted. */
- *pstatus = ntlmssp_unseal_packet(a->ntlmssp_state,
- data, data_len,
- full_packet_data,
- full_packet_data_len,
- &auth_blob);
+ *pstatus = auth_ntlmssp_unseal_packet(a,
+ data, data_len,
+ full_packet_data,
+ full_packet_data_len,
+ &auth_blob);
if (!NT_STATUS_IS_OK(*pstatus)) {
return False;
}
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
/* Data is signed. */
- *pstatus = ntlmssp_check_packet(a->ntlmssp_state,
- data, data_len,
- full_packet_data,
- full_packet_data_len,
- &auth_blob);
+ *pstatus = auth_ntlmssp_check_packet(a,
+ data, data_len,
+ full_packet_data,
+ full_packet_data_len,
+ &auth_blob);
if (!NT_STATUS_IS_OK(*pstatus)) {
return False;
}
* We must remember to update the pointer copy for the common
* functions after any auth_ntlmssp_start/auth_ntlmssp_end.
*/
- ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state;
+ ec->es->s.ntlmssp_state = auth_ntlmssp_get_ntlmssp_state(ec->auth_ntlmssp_state);
return status;
}
}
if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
- if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) !=
- (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) {
+ if (!auth_ntlmssp_negotiated_sign((ec->auth_ntlmssp_state))) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!auth_ntlmssp_negotiated_seal((ec->auth_ntlmssp_state))) {
return NT_STATUS_INVALID_PARAMETER;
}
}
struct smbd_server_connection *sconn = smbd_server_conn;
if (NT_STATUS_IS_OK(nt_status)) {
- server_info = (*auth_ntlmssp_state)->server_info;
+ server_info = auth_ntlmssp_server_info(talloc_tos(), (*auth_ntlmssp_state));
} else {
+ /* Note that this server_info won't have a session
+ * key. But for map to guest, that's exactly the right
+ * thing - we can't reasonably guess the key the
+ * client wants, as the password was wrong */
nt_status = do_map_to_guest(nt_status,
- &server_info,
- (*auth_ntlmssp_state)->ntlmssp_state->user,
- (*auth_ntlmssp_state)->ntlmssp_state->domain);
+ &server_info,
+ auth_ntlmssp_get_username(*auth_ntlmssp_state),
+ auth_ntlmssp_get_domain(*auth_ntlmssp_state));
}
reply_outbuf(req, 4, 0);
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(sconn, vuid,
- server_info, nullblob,
- (*auth_ntlmssp_state)->ntlmssp_state->user) !=
- vuid) {
+ server_info, nullblob,
+ auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
+ vuid) {
nt_status = NT_STATUS_LOGON_FAILURE;
goto out;
}
- (*auth_ntlmssp_state)->server_info = NULL;
-
/* current_user_info is changed on new vuid */
reload_services( True );
uint64_t *out_session_id)
{
fstring tmp;
+ session->server_info = auth_ntlmssp_server_info(session, session->auth_ntlmssp_state);
+ if (!session->server_info) {
+ auth_ntlmssp_end(&session->auth_ntlmssp_state);
+ TALLOC_FREE(session);
+ return NT_STATUS_NO_MEMORY;
+ }
if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
lp_server_signing() == Required) {
session->do_signing = true;
}
- if (session->auth_ntlmssp_state->server_info->guest) {
+ if (session->server_info->guest) {
/* we map anonymous to guest internally */
*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
session->do_signing = false;
}
- session->server_info = session->auth_ntlmssp_state->server_info;
- data_blob_free(&session->server_info->user_session_key);
- session->server_info->user_session_key =
- data_blob_talloc(
- session->server_info,
- session->auth_ntlmssp_state->ntlmssp_state->session_key.data,
- session->auth_ntlmssp_state->ntlmssp_state->session_key.length);
- if (session->auth_ntlmssp_state->ntlmssp_state->session_key.length > 0) {
- if (session->server_info->user_session_key.data == NULL) {
- auth_ntlmssp_end(&session->auth_ntlmssp_state);
- TALLOC_FREE(session);
- return NT_STATUS_NO_MEMORY;
- }
- }
session->session_key = session->server_info->user_session_key;
session->compat_vuser = talloc_zero(session, user_struct);
/* This is a potentially untrusted username */
alpha_strcpy(tmp,
- session->auth_ntlmssp_state->ntlmssp_state->user,
- ". _-$",
- sizeof(tmp));
+ auth_ntlmssp_get_username(session->auth_ntlmssp_state),
+ ". _-$",
+ sizeof(tmp));
session->server_info->sanitized_username = talloc_strdup(
- session->server_info, tmp);
+ session->server_info, tmp);
if (!session->compat_vuser->server_info->guest) {
session->compat_vuser->homes_snum =