2 Unix SMB/CIFS implementation.
4 Winbind authentication mechnism
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Bartlett 2001 - 2002
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.
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.
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/>.
25 #include "nsswitch/libwbclient/wbclient.h"
28 #define DBGC_CLASS DBGC_AUTH
30 /* Authenticate a user with a challenge/response */
32 static NTSTATUS
check_winbind_security(const struct auth_context
*auth_context
,
33 void *my_private_data
,
35 const struct auth_usersupplied_info
*user_info
,
36 struct auth_serversupplied_info
**server_info
)
40 struct wbcAuthUserParams params
;
41 struct wbcAuthUserInfo
*info
= NULL
;
42 struct wbcAuthErrorInfo
*err
= NULL
;
47 return NT_STATUS_INVALID_PARAMETER
;
50 DEBUG(10, ("Check auth for: [%s]\n", user_info
->mapped
.account_name
));
53 DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n",
54 user_info
->mapped
.account_name
));
55 return NT_STATUS_INVALID_PARAMETER
;
58 if (strequal(user_info
->mapped
.domain_name
, get_global_sam_name())) {
59 DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n",
60 user_info
->mapped
.domain_name
));
61 return NT_STATUS_NOT_IMPLEMENTED
;
64 /* Send off request */
65 params
.account_name
= user_info
->client
.account_name
;
67 * We need to send the domain name from the client to the DC. With
68 * NTLMv2 the domain name is part of the hashed second challenge,
69 * if we change the domain name, the DC will fail to verify the
70 * challenge cause we changed the domain name, this is like a
71 * man in the middle attack.
73 params
.domain_name
= user_info
->client
.domain_name
;
74 params
.workstation_name
= user_info
->workstation_name
;
77 params
.parameter_control
= user_info
->logon_parameters
;
79 params
.level
= WBC_AUTH_USER_LEVEL_RESPONSE
;
81 memcpy(params
.password
.response
.challenge
,
82 auth_context
->challenge
.data
,
83 sizeof(params
.password
.response
.challenge
));
85 if (user_info
->password
.response
.nt
.length
!= 0) {
86 params
.password
.response
.nt_length
=
87 user_info
->password
.response
.nt
.length
;
88 params
.password
.response
.nt_data
=
89 user_info
->password
.response
.nt
.data
;
91 if (user_info
->password
.response
.lanman
.length
!= 0) {
92 params
.password
.response
.lm_length
=
93 user_info
->password
.response
.lanman
.length
;
94 params
.password
.response
.lm_data
=
95 user_info
->password
.response
.lanman
.data
;
98 /* we are contacting the privileged pipe */
100 wbc_status
= wbcAuthenticateUserEx(¶ms
, &info
, &err
);
103 if (!WBC_ERROR_IS_OK(wbc_status
)) {
104 DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n",
105 wbcErrorString(wbc_status
)));
108 if (wbc_status
== WBC_ERR_NO_MEMORY
) {
109 return NT_STATUS_NO_MEMORY
;
112 if (wbc_status
== WBC_ERR_WINBIND_NOT_AVAILABLE
) {
113 struct auth_methods
*auth_method
=
114 (struct auth_methods
*)my_private_data
;
117 return auth_method
->auth(auth_context
, auth_method
->private_data
,
118 mem_ctx
, user_info
, server_info
);
119 return NT_STATUS_LOGON_FAILURE
;
122 if (wbc_status
== WBC_ERR_AUTH_ERROR
) {
123 nt_status
= NT_STATUS(err
->nt_status
);
128 if (!WBC_ERROR_IS_OK(wbc_status
)) {
129 return NT_STATUS_LOGON_FAILURE
;
132 nt_status
= make_server_info_wbcAuthUserInfo(mem_ctx
,
133 user_info
->client
.account_name
,
134 user_info
->mapped
.domain_name
,
137 if (!NT_STATUS_IS_OK(nt_status
)) {
141 (*server_info
)->nss_token
|= user_info
->was_mapped
;
146 /* module initialisation */
147 static NTSTATUS
auth_init_winbind(struct auth_context
*auth_context
, const char *param
, auth_methods
**auth_method
)
149 struct auth_methods
*result
;
151 result
= talloc_zero(auth_context
, struct auth_methods
);
152 if (result
== NULL
) {
153 return NT_STATUS_NO_MEMORY
;
155 result
->name
= "winbind";
156 result
->auth
= check_winbind_security
;
158 if (param
&& *param
) {
159 /* we load the 'fallback' module - if winbind isn't here, call this
162 if (!load_auth_module(auth_context
, param
, &priv
)) {
163 return NT_STATUS_UNSUCCESSFUL
;
165 result
->private_data
= (void *)priv
;
168 *auth_method
= result
;
172 NTSTATUS
auth_winbind_init(void)
174 return smb_register_auth(AUTH_INTERFACE_VERSION
, "winbind", auth_init_winbind
);