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 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#undef DBGC_CLASS 26#define DBGC_CLASS DBGC_AUTH 27 28/* Authenticate a user with a challenge/response */ 29 30static NTSTATUS check_winbind_security(const struct auth_context *auth_context, 31 void *my_private_data, 32 TALLOC_CTX *mem_ctx, 33 const auth_usersupplied_info *user_info, 34 auth_serversupplied_info **server_info) 35{ 36 NTSTATUS nt_status; 37 wbcErr wbc_status; 38 struct wbcAuthUserParams params; 39 struct wbcAuthUserInfo *info = NULL; 40 struct wbcAuthErrorInfo *err = NULL; 41 42 if (!user_info) { 43 return NT_STATUS_INVALID_PARAMETER; 44 } 45 46 if (!auth_context) { 47 DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", 48 user_info->internal_username)); 49 return NT_STATUS_INVALID_PARAMETER; 50 } 51 52 if (strequal(user_info->domain, get_global_sam_name())) { 53 DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", 54 user_info->domain)); 55 return NT_STATUS_NOT_IMPLEMENTED; 56 } 57 58 /* Send off request */ 59 60 params.account_name = user_info->smb_name; 61 params.domain_name = user_info->domain; 62 params.workstation_name = user_info->wksta_name; 63 64 params.flags = 0; 65 params.parameter_control= user_info->logon_parameters; 66 67 params.level = WBC_AUTH_USER_LEVEL_RESPONSE; 68 69 memcpy(params.password.response.challenge, 70 auth_context->challenge.data, 71 sizeof(params.password.response.challenge)); 72 73 params.password.response.nt_length = user_info->nt_resp.length; 74 params.password.response.nt_data = user_info->nt_resp.data; 75 params.password.response.lm_length = user_info->lm_resp.length; 76 params.password.response.lm_data = user_info->lm_resp.data; 77 78 /* we are contacting the privileged pipe */ 79 become_root(); 80 wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); 81 unbecome_root(); 82 83 if (!WBC_ERROR_IS_OK(wbc_status)) { 84 DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n", 85 wbcErrorString(wbc_status))); 86 } 87 88 if (wbc_status == WBC_ERR_NO_MEMORY) { 89 return NT_STATUS_NO_MEMORY; 90 } 91 92 if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) { 93 struct auth_methods *auth_method = 94 (struct auth_methods *)my_private_data; 95 96 if ( auth_method ) 97 return auth_method->auth(auth_context, auth_method->private_data, 98 mem_ctx, user_info, server_info); 99 else 100 /* log an error since this should not happen */ 101 DEBUG(0,("check_winbind_security: ERROR! my_private_data == NULL!\n")); 102 } 103 104 if (wbc_status == WBC_ERR_AUTH_ERROR) { 105 nt_status = NT_STATUS(err->nt_status); 106 wbcFreeMemory(err); 107 return nt_status; 108 } 109 110 if (!WBC_ERROR_IS_OK(wbc_status)) { 111 return NT_STATUS_LOGON_FAILURE; 112 } 113 114 nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, 115 user_info->smb_name, 116 user_info->domain, 117 info, server_info); 118 wbcFreeMemory(info); 119 if (!NT_STATUS_IS_OK(nt_status)) { 120 return nt_status; 121 } 122 123 (*server_info)->nss_token |= user_info->was_mapped; 124 125 return nt_status; 126} 127 128/* module initialisation */ 129static NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 130{ 131 if (!make_auth_methods(auth_context, auth_method)) { 132 return NT_STATUS_NO_MEMORY; 133 } 134 135 (*auth_method)->name = "winbind"; 136 (*auth_method)->auth = check_winbind_security; 137 138 if (param && *param) { 139 /* we load the 'fallback' module - if winbind isn't here, call this 140 module */ 141 auth_methods *priv; 142 if (!load_auth_module(auth_context, param, &priv)) { 143 return NT_STATUS_UNSUCCESSFUL; 144 } 145 (*auth_method)->private_data = (void *)priv; 146 } 147 return NT_STATUS_OK; 148} 149 150NTSTATUS auth_winbind_init(void) 151{ 152 return smb_register_auth(AUTH_INTERFACE_VERSION, "winbind", auth_init_winbind); 153} 154