root/source4/auth/ntlm/auth_winbind.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_info3_from_ndr
  2. winbind_want_check
  3. winbind_check_password_samba3
  4. winbind_check_password
  5. auth_winbind_init

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    Winbind authentication mechnism
   5 
   6    Copyright (C) Tim Potter 2000
   7    Copyright (C) Andrew Bartlett 2001 - 2002
   8    Copyright (C) Stefan Metzmacher 2005
   9    
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14    
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "auth/auth.h"
  26 #include "auth/ntlm/auth_proto.h"
  27 #include "auth/auth_sam_reply.h"
  28 #include "nsswitch/winbind_client.h"
  29 #include "librpc/gen_ndr/ndr_netlogon.h"
  30 #include "librpc/gen_ndr/ndr_winbind.h"
  31 #include "lib/messaging/irpc.h"
  32 #include "param/param.h"
  33 
  34 static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, struct winbindd_response *response, struct netr_SamInfo3 *info3)
     /* [<][>][^][v][top][bottom][index][help] */
  35 {
  36         size_t len = response->length - sizeof(struct winbindd_response);
  37         if (len > 4) {
  38                 enum ndr_err_code ndr_err;
  39                 DATA_BLOB blob;
  40                 blob.length = len - 4;
  41                 blob.data = (uint8_t *)(((char *)response->extra_data.data) + 4);
  42 
  43                 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, 
  44                                iconv_convenience, info3,
  45                               (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3);
  46                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  47                         return ndr_map_error2ntstatus(ndr_err);
  48                 }
  49 
  50                 return NT_STATUS_OK;
  51         } else {
  52                 DEBUG(2, ("get_info3_from_ndr: No info3 struct found!\n"));
  53                 return NT_STATUS_UNSUCCESSFUL;
  54         }
  55 }
  56 
  57 static NTSTATUS winbind_want_check(struct auth_method_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  58                                    TALLOC_CTX *mem_ctx,
  59                                    const struct auth_usersupplied_info *user_info)
  60 {
  61         if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
  62                 return NT_STATUS_NOT_IMPLEMENTED;
  63         }
  64 
  65         /* TODO: maybe limit the user scope to remote users only */
  66         return NT_STATUS_OK;
  67 }
  68 
  69 /*
  70  Authenticate a user with a challenge/response
  71  using the samba3 winbind protocol
  72 */
  73 static NTSTATUS winbind_check_password_samba3(struct auth_method_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  74                                               TALLOC_CTX *mem_ctx,
  75                                               const struct auth_usersupplied_info *user_info, 
  76                                               struct auth_serversupplied_info **server_info)
  77 {
  78         struct winbindd_request request;
  79         struct winbindd_response response;
  80         NSS_STATUS result;
  81         NTSTATUS nt_status;
  82         struct netr_SamInfo3 info3;             
  83 
  84         /* Send off request */
  85         const struct auth_usersupplied_info *user_info_temp;    
  86         nt_status = encrypt_user_info(mem_ctx, ctx->auth_ctx, 
  87                                       AUTH_PASSWORD_RESPONSE, 
  88                                       user_info, &user_info_temp);
  89         if (!NT_STATUS_IS_OK(nt_status)) {
  90                 return nt_status;
  91         }
  92         user_info = user_info_temp;
  93 
  94         ZERO_STRUCT(request);
  95         ZERO_STRUCT(response);
  96         request.flags = WBFLAG_PAM_INFO3_NDR;
  97 
  98         request.data.auth_crap.logon_parameters = user_info->logon_parameters;
  99 
 100         safe_strcpy(request.data.auth_crap.user,
 101                        user_info->client.account_name, sizeof(fstring));
 102         safe_strcpy(request.data.auth_crap.domain,
 103                        user_info->client.domain_name, sizeof(fstring));
 104         safe_strcpy(request.data.auth_crap.workstation,
 105                        user_info->workstation_name, sizeof(fstring));
 106 
 107         memcpy(request.data.auth_crap.chal, ctx->auth_ctx->challenge.data.data, sizeof(request.data.auth_crap.chal));
 108 
 109         request.data.auth_crap.lm_resp_len = MIN(user_info->password.response.lanman.length,
 110                                                  sizeof(request.data.auth_crap.lm_resp));
 111         request.data.auth_crap.nt_resp_len = MIN(user_info->password.response.nt.length, 
 112                                                  sizeof(request.data.auth_crap.nt_resp));
 113 
 114         memcpy(request.data.auth_crap.lm_resp, user_info->password.response.lanman.data,
 115                request.data.auth_crap.lm_resp_len);
 116         memcpy(request.data.auth_crap.nt_resp, user_info->password.response.nt.data,
 117                request.data.auth_crap.nt_resp_len);
 118 
 119         result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
 120 
 121         nt_status = NT_STATUS(response.data.auth.nt_status);
 122         NT_STATUS_NOT_OK_RETURN(nt_status);
 123 
 124         if (result == NSS_STATUS_SUCCESS && response.extra_data.data) {
 125                 union netr_Validation validation;
 126 
 127                 nt_status = get_info3_from_ndr(mem_ctx, lp_iconv_convenience(ctx->auth_ctx->lp_ctx), &response, &info3);
 128                 SAFE_FREE(response.extra_data.data);
 129                 NT_STATUS_NOT_OK_RETURN(nt_status); 
 130 
 131                 validation.sam3 = &info3;
 132                 nt_status = make_server_info_netlogon_validation(mem_ctx, 
 133                                                                  user_info->client.account_name, 
 134                                                                  3, &validation,
 135                                                                  server_info);
 136                 return nt_status;
 137         } else if (result == NSS_STATUS_SUCCESS && !response.extra_data.data) {
 138                 DEBUG(0, ("Winbindd authenticated the user [%s]\\[%s], "
 139                           "but did not include the required info3 reply!\n", 
 140                           user_info->client.domain_name, user_info->client.account_name));
 141                 return NT_STATUS_INSUFFICIENT_LOGON_INFO;
 142         } else if (NT_STATUS_IS_OK(nt_status)) {
 143                 DEBUG(1, ("Winbindd authentication for [%s]\\[%s] failed, "
 144                           "but no error code is available!\n", 
 145                           user_info->client.domain_name, user_info->client.account_name));
 146                 return NT_STATUS_NO_LOGON_SERVERS;
 147         }
 148 
 149         return nt_status;
 150 }
 151 
 152 struct winbind_check_password_state {
 153         struct winbind_SamLogon req;
 154 };
 155 
 156 /*
 157  Authenticate a user with a challenge/response
 158  using IRPC to the winbind task
 159 */
 160 static NTSTATUS winbind_check_password(struct auth_method_context *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 161                                        TALLOC_CTX *mem_ctx,
 162                                        const struct auth_usersupplied_info *user_info, 
 163                                        struct auth_serversupplied_info **server_info)
 164 {
 165         NTSTATUS status;
 166         struct server_id *winbind_servers;
 167         struct winbind_check_password_state *s;
 168         const struct auth_usersupplied_info *user_info_new;
 169         struct netr_IdentityInfo *identity_info;
 170 
 171         s = talloc(mem_ctx, struct winbind_check_password_state);
 172         NT_STATUS_HAVE_NO_MEMORY(s);
 173 
 174         winbind_servers = irpc_servers_byname(ctx->auth_ctx->msg_ctx, s, "winbind_server");
 175         if ((winbind_servers == NULL) || (winbind_servers[0].id == 0)) {
 176                 DEBUG(0, ("Winbind authentication for [%s]\\[%s] failed, " 
 177                           "no winbind_server running!\n",
 178                           user_info->client.domain_name, user_info->client.account_name));
 179                 return NT_STATUS_NO_LOGON_SERVERS;
 180         }
 181 
 182         if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) {
 183                 struct netr_PasswordInfo *password_info;
 184 
 185                 status = encrypt_user_info(s, ctx->auth_ctx, AUTH_PASSWORD_HASH,
 186                                            user_info, &user_info_new);
 187                 NT_STATUS_NOT_OK_RETURN(status);
 188                 user_info = user_info_new;
 189 
 190                 password_info = talloc(s, struct netr_PasswordInfo);
 191                 NT_STATUS_HAVE_NO_MEMORY(password_info);
 192 
 193                 password_info->lmpassword = *user_info->password.hash.lanman;
 194                 password_info->ntpassword = *user_info->password.hash.nt;
 195 
 196                 identity_info = &password_info->identity_info;
 197                 s->req.in.logon_level   = 1;
 198                 s->req.in.logon.password= password_info;
 199         } else {
 200                 struct netr_NetworkInfo *network_info;
 201                 const uint8_t *challenge;
 202 
 203                 status = encrypt_user_info(s, ctx->auth_ctx, AUTH_PASSWORD_RESPONSE,
 204                                            user_info, &user_info_new);
 205                 NT_STATUS_NOT_OK_RETURN(status);
 206                 user_info = user_info_new;
 207 
 208                 network_info = talloc(s, struct netr_NetworkInfo);
 209                 NT_STATUS_HAVE_NO_MEMORY(network_info);
 210 
 211                 status = auth_get_challenge(ctx->auth_ctx, &challenge);
 212                 NT_STATUS_NOT_OK_RETURN(status);
 213 
 214                 memcpy(network_info->challenge, challenge, sizeof(network_info->challenge));
 215 
 216                 network_info->nt.length = user_info->password.response.nt.length;
 217                 network_info->nt.data   = user_info->password.response.nt.data;
 218 
 219                 network_info->lm.length = user_info->password.response.lanman.length;
 220                 network_info->lm.data   = user_info->password.response.lanman.data;
 221 
 222                 identity_info = &network_info->identity_info;
 223                 s->req.in.logon_level   = 2;
 224                 s->req.in.logon.network = network_info;
 225         }
 226 
 227         identity_info->domain_name.string       = user_info->client.domain_name;
 228         identity_info->parameter_control        = user_info->logon_parameters; /* see MSV1_0_* */
 229         identity_info->logon_id_low             = 0;
 230         identity_info->logon_id_high            = 0;
 231         identity_info->account_name.string      = user_info->client.account_name;
 232         identity_info->workstation.string       = user_info->workstation_name;
 233 
 234         s->req.in.validation_level      = 3;
 235 
 236         status = IRPC_CALL(ctx->auth_ctx->msg_ctx, winbind_servers[0],
 237                            winbind, WINBIND_SAMLOGON,
 238                            &s->req, s);
 239         NT_STATUS_NOT_OK_RETURN(status);
 240 
 241         status = make_server_info_netlogon_validation(mem_ctx,
 242                                                       user_info->client.account_name,
 243                                                       s->req.in.validation_level,
 244                                                       &s->req.out.validation,
 245                                                       server_info);
 246         NT_STATUS_NOT_OK_RETURN(status);
 247 
 248         return NT_STATUS_OK;
 249 }
 250 
 251 static const struct auth_operations winbind_samba3_ops = {
 252         .name           = "winbind_samba3",
 253         .get_challenge  = auth_get_challenge_not_implemented,
 254         .want_check     = winbind_want_check,
 255         .check_password = winbind_check_password_samba3
 256 };
 257 
 258 static const struct auth_operations winbind_ops = {
 259         .name           = "winbind",
 260         .get_challenge  = auth_get_challenge_not_implemented,
 261         .want_check     = winbind_want_check,
 262         .check_password = winbind_check_password
 263 };
 264 
 265 _PUBLIC_ NTSTATUS auth_winbind_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 266 {
 267         NTSTATUS ret;
 268 
 269         ret = auth_register(&winbind_samba3_ops);
 270         if (!NT_STATUS_IS_OK(ret)) {
 271                 DEBUG(0,("Failed to register 'winbind_samba3' auth backend!\n"));
 272                 return ret;
 273         }
 274 
 275         ret = auth_register(&winbind_ops);
 276         if (!NT_STATUS_IS_OK(ret)) {
 277                 DEBUG(0,("Failed to register 'winbind' auth backend!\n"));
 278                 return ret;
 279         }
 280 
 281         return NT_STATUS_OK;
 282 }

/* [<][>][^][v][top][bottom][index][help] */