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 2 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, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22*/ 23 24#include "includes.h" 25 26#undef DBGC_CLASS 27#define DBGC_CLASS DBGC_AUTH 28 29static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, NET_USER_INFO_3 *info3) 30{ 31 uint8 *info3_ndr; 32 size_t len = response->length - sizeof(struct winbindd_response); 33 prs_struct ps; 34 if (len > 0) { 35 info3_ndr = response->extra_data; 36 if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) { 37 return NT_STATUS_NO_MEMORY; 38 } 39 prs_copy_data_in(&ps, (char *)info3_ndr, len); 40 prs_set_offset(&ps,0); 41 if (!net_io_user_info3("", info3, &ps, 1, 3)) { 42 DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n")); 43 return NT_STATUS_UNSUCCESSFUL; 44 } 45 prs_mem_free(&ps); 46 47 return NT_STATUS_OK; 48 } else { 49 DEBUG(2, ("get_info3_from_ndr: No info3 struct found!\n")); 50 return NT_STATUS_UNSUCCESSFUL; 51 } 52} 53 54/* Authenticate a user with a challenge/response */ 55 56static NTSTATUS check_winbind_security(const struct auth_context *auth_context, 57 void *my_private_data, 58 TALLOC_CTX *mem_ctx, 59 const auth_usersupplied_info *user_info, 60 auth_serversupplied_info **server_info) 61{ 62 struct winbindd_request request; 63 struct winbindd_response response; 64 NSS_STATUS result; 65 NTSTATUS nt_status; 66 NET_USER_INFO_3 info3; 67 68 if (!user_info) { 69 return NT_STATUS_INVALID_PARAMETER; 70 } 71 72 if (!auth_context) { 73 DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", 74 user_info->internal_username.str)); 75 return NT_STATUS_INVALID_PARAMETER; 76 } 77 78 if (strequal(user_info->domain.str, get_global_sam_name())) { 79 DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", 80 user_info->domain.str)); 81 return NT_STATUS_NOT_IMPLEMENTED; 82 } 83 84 /* Send off request */ 85 86 ZERO_STRUCT(request); 87 ZERO_STRUCT(response); 88 89 request.flags = WBFLAG_PAM_INFO3_NDR; 90 91 fstrcpy(request.data.auth_crap.user, 92 user_info->smb_name.str); 93 fstrcpy(request.data.auth_crap.domain, 94 user_info->domain.str); 95 fstrcpy(request.data.auth_crap.workstation, 96 user_info->wksta_name.str); 97 98 memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal)); 99 100 request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length, 101 sizeof(request.data.auth_crap.lm_resp)); 102 request.data.auth_crap.nt_resp_len = MIN(user_info->nt_resp.length, 103 sizeof(request.data.auth_crap.nt_resp)); 104 105 memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data, 106 request.data.auth_crap.lm_resp_len); 107 memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data, 108 request.data.auth_crap.nt_resp_len); 109 110 /* we are contacting the privileged pipe */ 111 become_root(); 112 result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); 113 unbecome_root(); 114 115 if ( result == NSS_STATUS_UNAVAIL ) { 116 struct auth_methods *auth_method = my_private_data; 117 118 if ( auth_method ) 119 return auth_method->auth(auth_context, auth_method->private_data, 120 mem_ctx, user_info, server_info); 121 else 122 /* log an error since this should not happen */ 123 DEBUG(0,("check_winbind_security: ERROR! my_private_data == NULL!\n")); 124 } 125 126 nt_status = NT_STATUS(response.data.auth.nt_status); 127 128 if (result == NSS_STATUS_SUCCESS && response.extra_data) { 129 if (NT_STATUS_IS_OK(nt_status)) { 130 if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) { 131 nt_status = make_server_info_info3(mem_ctx, 132 user_info->internal_username.str, 133 user_info->smb_name.str, user_info->domain.str, 134 server_info, &info3); 135 } 136 137 } 138 } else if (NT_STATUS_IS_OK(nt_status)) { 139 nt_status = NT_STATUS_NO_LOGON_SERVERS; 140 } 141 142 SAFE_FREE(response.extra_data); 143 return nt_status; 144} 145 146/* module initialisation */ 147static NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char *param, auth_methods **auth_method) 148{ 149 if (!make_auth_methods(auth_context, auth_method)) { 150 return NT_STATUS_NO_MEMORY; 151 } 152 153 (*auth_method)->name = "winbind"; 154 (*auth_method)->auth = check_winbind_security; 155 156 if (param && *param) { 157 /* we load the 'fallback' module - if winbind isn't here, call this 158 module */ 159 if (!load_auth_module(auth_context, param, (auth_methods **)&(*auth_method)->private_data)) { 160 return NT_STATUS_UNSUCCESSFUL; 161 } 162 163 } 164 return NT_STATUS_OK; 165} 166 167NTSTATUS auth_winbind_init(void) 168{ 169 return smb_register_auth(AUTH_INTERFACE_VERSION, "winbind", auth_init_winbind); 170} 171