| 1 | /* 
 | 
|---|
| 2 |    Unix SMB/Netbios implementation.
 | 
|---|
| 3 |    Version 3.0
 | 
|---|
| 4 |    handle NLTMSSP, server side
 | 
|---|
| 5 | 
 | 
|---|
| 6 |    Copyright (C) Andrew Tridgell      2001
 | 
|---|
| 7 |    Copyright (C) Andrew Bartlett 2001-2003
 | 
|---|
| 8 | 
 | 
|---|
| 9 |    This program is free software; you can redistribute it and/or modify
 | 
|---|
| 10 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 11 |    the Free Software Foundation; either version 3 of the License, or
 | 
|---|
| 12 |    (at your option) any later version.
 | 
|---|
| 13 |    
 | 
|---|
| 14 |    This program is distributed in the hope that it will be useful,
 | 
|---|
| 15 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 16 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 17 |    GNU General Public License for more details.
 | 
|---|
| 18 |    
 | 
|---|
| 19 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 20 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 21 | */
 | 
|---|
| 22 | 
 | 
|---|
| 23 | #include "includes.h"
 | 
|---|
| 24 | 
 | 
|---|
| 25 | /**
 | 
|---|
| 26 |  * Return the challenge as determined by the authentication subsystem 
 | 
|---|
| 27 |  * @return an 8 byte random challenge
 | 
|---|
| 28 |  */
 | 
|---|
| 29 | 
 | 
|---|
| 30 | static void auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state,
 | 
|---|
| 31 |                                        uint8_t chal[8])
 | 
|---|
| 32 | {
 | 
|---|
| 33 |         AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
 | 
|---|
| 34 |                 (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
 | 
|---|
| 35 |         auth_ntlmssp_state->auth_context->get_ntlm_challenge(
 | 
|---|
| 36 |                 auth_ntlmssp_state->auth_context, chal);
 | 
|---|
| 37 | }
 | 
|---|
| 38 | 
 | 
|---|
| 39 | /**
 | 
|---|
| 40 |  * Some authentication methods 'fix' the challenge, so we may not be able to set it
 | 
|---|
| 41 |  *
 | 
|---|
| 42 |  * @return If the effective challenge used by the auth subsystem may be modified
 | 
|---|
| 43 |  */
 | 
|---|
| 44 | static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state)
 | 
|---|
| 45 | {
 | 
|---|
| 46 |         AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
 | 
|---|
| 47 |                 (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
 | 
|---|
| 48 |         struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
 | 
|---|
| 49 | 
 | 
|---|
| 50 |         return auth_context->challenge_may_be_modified;
 | 
|---|
| 51 | }
 | 
|---|
| 52 | 
 | 
|---|
| 53 | /**
 | 
|---|
| 54 |  * NTLM2 authentication modifies the effective challenge, 
 | 
|---|
| 55 |  * @param challenge The new challenge value
 | 
|---|
| 56 |  */
 | 
|---|
| 57 | static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
 | 
|---|
| 58 | {
 | 
|---|
| 59 |         AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
 | 
|---|
| 60 |                 (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
 | 
|---|
| 61 |         struct auth_context *auth_context = auth_ntlmssp_state->auth_context;
 | 
|---|
| 62 | 
 | 
|---|
| 63 |         SMB_ASSERT(challenge->length == 8);
 | 
|---|
| 64 | 
 | 
|---|
| 65 |         auth_context->challenge = data_blob_talloc(auth_context->mem_ctx, 
 | 
|---|
| 66 |                                                    challenge->data, challenge->length);
 | 
|---|
| 67 | 
 | 
|---|
| 68 |         auth_context->challenge_set_by = "NTLMSSP callback (NTLM2)";
 | 
|---|
| 69 | 
 | 
|---|
| 70 |         DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
 | 
|---|
| 71 |         DEBUG(5, ("challenge is: \n"));
 | 
|---|
| 72 |         dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
 | 
|---|
| 73 |         return NT_STATUS_OK;
 | 
|---|
| 74 | }
 | 
|---|
| 75 | 
 | 
|---|
| 76 | /**
 | 
|---|
| 77 |  * Check the password on an NTLMSSP login.  
 | 
|---|
| 78 |  *
 | 
|---|
| 79 |  * Return the session keys used on the connection.
 | 
|---|
| 80 |  */
 | 
|---|
| 81 | 
 | 
|---|
| 82 | static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
 | 
|---|
| 83 | {
 | 
|---|
| 84 |         AUTH_NTLMSSP_STATE *auth_ntlmssp_state =
 | 
|---|
| 85 |                 (AUTH_NTLMSSP_STATE *)ntlmssp_state->auth_context;
 | 
|---|
| 86 |         auth_usersupplied_info *user_info = NULL;
 | 
|---|
| 87 |         NTSTATUS nt_status;
 | 
|---|
| 88 |         bool username_was_mapped;
 | 
|---|
| 89 | 
 | 
|---|
| 90 |         /* the client has given us its machine name (which we otherwise would not get on port 445).
 | 
|---|
| 91 |            we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
 | 
|---|
| 92 | 
 | 
|---|
| 93 |         set_remote_machine_name(auth_ntlmssp_state->ntlmssp_state->workstation, True);
 | 
|---|
| 94 | 
 | 
|---|
| 95 |         /* setup the string used by %U */
 | 
|---|
| 96 |         /* sub_set_smb_name checks for weird internally */
 | 
|---|
| 97 |         sub_set_smb_name(auth_ntlmssp_state->ntlmssp_state->user);
 | 
|---|
| 98 | 
 | 
|---|
| 99 |         reload_services(True);
 | 
|---|
| 100 | 
 | 
|---|
| 101 |         nt_status = make_user_info_map(&user_info, 
 | 
|---|
| 102 |                                        auth_ntlmssp_state->ntlmssp_state->user, 
 | 
|---|
| 103 |                                        auth_ntlmssp_state->ntlmssp_state->domain, 
 | 
|---|
| 104 |                                        auth_ntlmssp_state->ntlmssp_state->workstation, 
 | 
|---|
| 105 |                                        auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL, 
 | 
|---|
| 106 |                                        auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL, 
 | 
|---|
| 107 |                                        NULL, NULL, NULL,
 | 
|---|
| 108 |                                        True);
 | 
|---|
| 109 | 
 | 
|---|
| 110 |         user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
 | 
|---|
| 111 | 
 | 
|---|
| 112 |         if (!NT_STATUS_IS_OK(nt_status)) {
 | 
|---|
| 113 |                 return nt_status;
 | 
|---|
| 114 |         }
 | 
|---|
| 115 | 
 | 
|---|
| 116 |         nt_status = auth_ntlmssp_state->auth_context->check_ntlm_password(auth_ntlmssp_state->auth_context, 
 | 
|---|
| 117 |                                                                           user_info, &auth_ntlmssp_state->server_info); 
 | 
|---|
| 118 | 
 | 
|---|
| 119 |         username_was_mapped = user_info->was_mapped;
 | 
|---|
| 120 | 
 | 
|---|
| 121 |         free_user_info(&user_info);
 | 
|---|
| 122 | 
 | 
|---|
| 123 |         if (!NT_STATUS_IS_OK(nt_status)) {
 | 
|---|
| 124 |                 return nt_status;
 | 
|---|
| 125 |         }
 | 
|---|
| 126 | 
 | 
|---|
| 127 |         auth_ntlmssp_state->server_info->nss_token |= username_was_mapped;
 | 
|---|
| 128 | 
 | 
|---|
| 129 |         if (auth_ntlmssp_state->server_info->ptok == NULL) {
 | 
|---|
| 130 |                 nt_status = create_local_token(auth_ntlmssp_state->server_info);
 | 
|---|
| 131 |                 if (!NT_STATUS_IS_OK(nt_status)) {
 | 
|---|
| 132 |                         DEBUG(10, ("create_local_token failed: %s\n",
 | 
|---|
| 133 |                                    nt_errstr(nt_status)));
 | 
|---|
| 134 |                         return nt_status;
 | 
|---|
| 135 |                 }
 | 
|---|
| 136 |         }
 | 
|---|
| 137 | 
 | 
|---|
| 138 |         if (auth_ntlmssp_state->server_info->user_session_key.length) {
 | 
|---|
| 139 |                 DEBUG(10, ("Got NT session key of length %u\n",
 | 
|---|
| 140 |                         (unsigned int)auth_ntlmssp_state->server_info->user_session_key.length));
 | 
|---|
| 141 |                 *user_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, 
 | 
|---|
| 142 |                                                    auth_ntlmssp_state->server_info->user_session_key.data,
 | 
|---|
| 143 |                                                    auth_ntlmssp_state->server_info->user_session_key.length);
 | 
|---|
| 144 |         }
 | 
|---|
| 145 |         if (auth_ntlmssp_state->server_info->lm_session_key.length) {
 | 
|---|
| 146 |                 DEBUG(10, ("Got LM session key of length %u\n",
 | 
|---|
| 147 |                         (unsigned int)auth_ntlmssp_state->server_info->lm_session_key.length));
 | 
|---|
| 148 |                 *lm_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, 
 | 
|---|
| 149 |                                                    auth_ntlmssp_state->server_info->lm_session_key.data,
 | 
|---|
| 150 |                                                    auth_ntlmssp_state->server_info->lm_session_key.length);
 | 
|---|
| 151 |         }
 | 
|---|
| 152 |         return nt_status;
 | 
|---|
| 153 | }
 | 
|---|
| 154 | 
 | 
|---|
| 155 | NTSTATUS auth_ntlmssp_start(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
 | 
|---|
| 156 | {
 | 
|---|
| 157 |         NTSTATUS nt_status;
 | 
|---|
| 158 |         TALLOC_CTX *mem_ctx;
 | 
|---|
| 159 | 
 | 
|---|
| 160 |         mem_ctx = talloc_init("AUTH NTLMSSP context");
 | 
|---|
| 161 |         
 | 
|---|
| 162 |         *auth_ntlmssp_state = TALLOC_ZERO_P(mem_ctx, AUTH_NTLMSSP_STATE);
 | 
|---|
| 163 |         if (!*auth_ntlmssp_state) {
 | 
|---|
| 164 |                 DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
 | 
|---|
| 165 |                 talloc_destroy(mem_ctx);
 | 
|---|
| 166 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 167 |         }
 | 
|---|
| 168 | 
 | 
|---|
| 169 |         ZERO_STRUCTP(*auth_ntlmssp_state);
 | 
|---|
| 170 | 
 | 
|---|
| 171 |         (*auth_ntlmssp_state)->mem_ctx = mem_ctx;
 | 
|---|
| 172 | 
 | 
|---|
| 173 |         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_start(&(*auth_ntlmssp_state)->ntlmssp_state))) {
 | 
|---|
| 174 |                 return nt_status;
 | 
|---|
| 175 |         }
 | 
|---|
| 176 | 
 | 
|---|
| 177 |         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&(*auth_ntlmssp_state)->auth_context))) {
 | 
|---|
| 178 |                 return nt_status;
 | 
|---|
| 179 |         }
 | 
|---|
| 180 | 
 | 
|---|
| 181 |         (*auth_ntlmssp_state)->ntlmssp_state->auth_context = (*auth_ntlmssp_state);
 | 
|---|
| 182 |         (*auth_ntlmssp_state)->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
 | 
|---|
| 183 |         (*auth_ntlmssp_state)->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
 | 
|---|
| 184 |         (*auth_ntlmssp_state)->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
 | 
|---|
| 185 |         (*auth_ntlmssp_state)->ntlmssp_state->check_password = auth_ntlmssp_check_password;
 | 
|---|
| 186 |         (*auth_ntlmssp_state)->ntlmssp_state->server_role = (enum server_types)lp_server_role();
 | 
|---|
| 187 | 
 | 
|---|
| 188 |         return NT_STATUS_OK;
 | 
|---|
| 189 | }
 | 
|---|
| 190 | 
 | 
|---|
| 191 | void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
 | 
|---|
| 192 | {
 | 
|---|
| 193 |         TALLOC_CTX *mem_ctx;
 | 
|---|
| 194 | 
 | 
|---|
| 195 |         if (*auth_ntlmssp_state == NULL) {
 | 
|---|
| 196 |                 return;
 | 
|---|
| 197 |         }
 | 
|---|
| 198 | 
 | 
|---|
| 199 |         mem_ctx = (*auth_ntlmssp_state)->mem_ctx;
 | 
|---|
| 200 |         if ((*auth_ntlmssp_state)->ntlmssp_state) {
 | 
|---|
| 201 |                 ntlmssp_end(&(*auth_ntlmssp_state)->ntlmssp_state);
 | 
|---|
| 202 |         }
 | 
|---|
| 203 |         if ((*auth_ntlmssp_state)->auth_context) {
 | 
|---|
| 204 |                 ((*auth_ntlmssp_state)->auth_context->free)(&(*auth_ntlmssp_state)->auth_context);
 | 
|---|
| 205 |         }
 | 
|---|
| 206 |         if ((*auth_ntlmssp_state)->server_info) {
 | 
|---|
| 207 |                 TALLOC_FREE((*auth_ntlmssp_state)->server_info);
 | 
|---|
| 208 |         }
 | 
|---|
| 209 |         talloc_destroy(mem_ctx);
 | 
|---|
| 210 |         *auth_ntlmssp_state = NULL;
 | 
|---|
| 211 | }
 | 
|---|
| 212 | 
 | 
|---|
| 213 | NTSTATUS auth_ntlmssp_update(AUTH_NTLMSSP_STATE *auth_ntlmssp_state, 
 | 
|---|
| 214 |                              const DATA_BLOB request, DATA_BLOB *reply) 
 | 
|---|
| 215 | {
 | 
|---|
| 216 |         return ntlmssp_update(auth_ntlmssp_state->ntlmssp_state, request, reply);
 | 
|---|
| 217 | }
 | 
|---|