Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : Winbind authentication mechanism 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 : #include "auth.h" 25 : #include "passdb.h" 26 : #include "nsswitch/libwbclient/wbclient.h" 27 : 28 : #undef DBGC_CLASS 29 : #define DBGC_CLASS DBGC_AUTH 30 : 31 : /* Authenticate a user with a challenge/response */ 32 : 33 2401 : static NTSTATUS check_winbind_security(const struct auth_context *auth_context, 34 : void *my_private_data, 35 : TALLOC_CTX *mem_ctx, 36 : const struct auth_usersupplied_info *user_info, 37 : struct auth_serversupplied_info **server_info) 38 : { 39 0 : NTSTATUS nt_status; 40 0 : wbcErr wbc_status; 41 0 : struct wbcAuthUserParams params; 42 2401 : struct wbcAuthUserInfo *info = NULL; 43 2401 : struct wbcAuthErrorInfo *err = NULL; 44 : 45 2401 : ZERO_STRUCT(params); 46 : 47 2401 : if (!user_info) { 48 0 : return NT_STATUS_INVALID_PARAMETER; 49 : } 50 : 51 2401 : DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); 52 : 53 2401 : if (!auth_context) { 54 0 : DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", 55 : user_info->mapped.account_name)); 56 0 : return NT_STATUS_INVALID_PARAMETER; 57 : } 58 : 59 2401 : if (strequal(user_info->mapped.domain_name, get_global_sam_name())) { 60 6 : DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", 61 : user_info->mapped.domain_name)); 62 6 : return NT_STATUS_NOT_IMPLEMENTED; 63 : } 64 : 65 : /* Send off request */ 66 2395 : params.account_name = user_info->client.account_name; 67 : /* 68 : * We need to send the domain name from the client to the DC. With 69 : * NTLMv2 the domain name is part of the hashed second challenge, 70 : * if we change the domain name, the DC will fail to verify the 71 : * challenge cause we changed the domain name, this is like a 72 : * man in the middle attack. 73 : */ 74 2395 : params.domain_name = user_info->client.domain_name; 75 2395 : params.workstation_name = user_info->workstation_name; 76 : 77 2395 : params.flags = 0; 78 2395 : params.parameter_control= user_info->logon_parameters; 79 : 80 2395 : params.level = WBC_AUTH_USER_LEVEL_RESPONSE; 81 : 82 2395 : memcpy(params.password.response.challenge, 83 2395 : auth_context->challenge.data, 84 : sizeof(params.password.response.challenge)); 85 : 86 2395 : if (user_info->password.response.nt.length != 0) { 87 2379 : params.password.response.nt_length = 88 2379 : user_info->password.response.nt.length; 89 2379 : params.password.response.nt_data = 90 2379 : user_info->password.response.nt.data; 91 : } 92 2395 : if (user_info->password.response.lanman.length != 0) { 93 2347 : params.password.response.lm_length = 94 2347 : user_info->password.response.lanman.length; 95 2347 : params.password.response.lm_data = 96 2347 : user_info->password.response.lanman.data; 97 : } 98 : 99 : /* we are contacting the privileged pipe */ 100 2395 : become_root(); 101 2395 : wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); 102 2395 : unbecome_root(); 103 : 104 2395 : if (!WBC_ERROR_IS_OK(wbc_status)) { 105 2163 : DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n", 106 : wbcErrorString(wbc_status))); 107 : } 108 : 109 2395 : if (wbc_status == WBC_ERR_NO_MEMORY) { 110 0 : return NT_STATUS_NO_MEMORY; 111 : } 112 : 113 2395 : if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) { 114 0 : struct pdb_trusted_domain **domains = NULL; 115 0 : uint32_t num_domains = 0; 116 0 : NTSTATUS status; 117 : 118 0 : if (lp_server_role() == ROLE_DOMAIN_MEMBER) { 119 0 : status = NT_STATUS_NO_LOGON_SERVERS; 120 0 : DBG_ERR("winbindd not running - " 121 : "but required as domain member: %s\n", 122 : nt_errstr(status)); 123 0 : return status; 124 : } 125 : 126 0 : status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains); 127 0 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { 128 0 : DBG_DEBUG("pdb_enum_trusted_domains() not implemented " 129 : "for this passdb backend\n"); 130 0 : return status; 131 0 : } else if (!NT_STATUS_IS_OK(status)) { 132 0 : DBG_ERR("pdb_enum_trusted_domains() failed - %s\n", 133 : nt_errstr(status)); 134 0 : return status; 135 : } 136 0 : TALLOC_FREE(domains); 137 : 138 0 : if (num_domains == 0) { 139 0 : DBG_DEBUG("winbindd not running - ignoring without " 140 : "trusted domains\n"); 141 0 : return NT_STATUS_NOT_IMPLEMENTED; 142 : } 143 : 144 0 : status = NT_STATUS_NO_LOGON_SERVERS; 145 0 : DBG_ERR("winbindd not running - " 146 : "but required as DC with trusts: %s\n", 147 : nt_errstr(status)); 148 0 : return status; 149 : } 150 : 151 2395 : if (wbc_status == WBC_ERR_AUTH_ERROR) { 152 2163 : nt_status = NT_STATUS(err->nt_status); 153 : 154 2163 : if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) && 155 2147 : (err->authoritative == 0)) { 156 : /* 157 : * Trigger a fallback to local SAM 158 : */ 159 2093 : nt_status = NT_STATUS_NOT_IMPLEMENTED; 160 : } 161 : 162 2163 : wbcFreeMemory(err); 163 2163 : return nt_status; 164 : } 165 : 166 232 : if (!WBC_ERROR_IS_OK(wbc_status)) { 167 0 : return NT_STATUS_LOGON_FAILURE; 168 : } 169 : 170 232 : nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, 171 232 : user_info->client.account_name, 172 232 : user_info->mapped.domain_name, 173 : info, server_info); 174 232 : wbcFreeMemory(info); 175 232 : if (!NT_STATUS_IS_OK(nt_status)) { 176 4 : return nt_status; 177 : } 178 : 179 228 : (*server_info)->nss_token |= user_info->was_mapped; 180 : 181 228 : return nt_status; 182 : } 183 : 184 : /* module initialisation */ 185 46112 : static NTSTATUS auth_init_winbind( 186 : struct auth_context *auth_context, 187 : const char *param, 188 : struct auth_methods **auth_method) 189 : { 190 0 : struct auth_methods *result; 191 : 192 46112 : result = talloc_zero(auth_context, struct auth_methods); 193 46112 : if (result == NULL) { 194 0 : return NT_STATUS_NO_MEMORY; 195 : } 196 46112 : result->name = "winbind"; 197 46112 : result->auth = check_winbind_security; 198 : 199 46112 : *auth_method = result; 200 46112 : return NT_STATUS_OK; 201 : } 202 : 203 31355 : NTSTATUS auth_winbind_init(TALLOC_CTX *mem_ctx) 204 : { 205 31355 : return smb_register_auth(AUTH_INTERFACE_VERSION, "winbind", auth_init_winbind); 206 : }