2 Unix SMB/CIFS implementation.
6 Copyright (C) 2009 Kai Blin <kai@samba.org>
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* Required Headers */
25 #include "libwbclient.h"
26 #include "../winbind_client.h"
27 #include "wbc_async.h"
29 /* FIXME: Currently this is still a copy of the same function from wbc_pam.c */
30 static wbcErr
wbc_create_auth_info(TALLOC_CTX
*mem_ctx
,
31 const struct winbindd_response
*resp
,
32 struct wbcAuthUserInfo
**_i
)
34 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
35 struct wbcAuthUserInfo
*i
;
36 struct wbcDomainSid domain_sid
;
41 i
= talloc(mem_ctx
, struct wbcAuthUserInfo
);
42 BAIL_ON_PTR_ERROR(i
, wbc_status
);
44 i
->user_flags
= resp
->data
.auth
.info3
.user_flgs
;
46 i
->account_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.user_name
);
47 BAIL_ON_PTR_ERROR(i
->account_name
, wbc_status
);
48 i
->user_principal
= NULL
;
49 i
->full_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.full_name
);
50 BAIL_ON_PTR_ERROR(i
->full_name
, wbc_status
);
51 i
->domain_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_dom
);
52 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
53 i
->dns_domain_name
= NULL
;
55 i
->acct_flags
= resp
->data
.auth
.info3
.acct_flags
;
56 memcpy(i
->user_session_key
,
57 resp
->data
.auth
.user_session_key
,
58 sizeof(i
->user_session_key
));
59 memcpy(i
->lm_session_key
,
60 resp
->data
.auth
.first_8_lm_hash
,
61 sizeof(i
->lm_session_key
));
63 i
->logon_count
= resp
->data
.auth
.info3
.logon_count
;
64 i
->bad_password_count
= resp
->data
.auth
.info3
.bad_pw_count
;
66 i
->logon_time
= resp
->data
.auth
.info3
.logon_time
;
67 i
->logoff_time
= resp
->data
.auth
.info3
.logoff_time
;
68 i
->kickoff_time
= resp
->data
.auth
.info3
.kickoff_time
;
69 i
->pass_last_set_time
= resp
->data
.auth
.info3
.pass_last_set_time
;
70 i
->pass_can_change_time
= resp
->data
.auth
.info3
.pass_can_change_time
;
71 i
->pass_must_change_time
= resp
->data
.auth
.info3
.pass_must_change_time
;
73 i
->logon_server
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_srv
);
74 BAIL_ON_PTR_ERROR(i
->logon_server
, wbc_status
);
75 i
->logon_script
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_script
);
76 BAIL_ON_PTR_ERROR(i
->logon_script
, wbc_status
);
77 i
->profile_path
= talloc_strdup(i
, resp
->data
.auth
.info3
.profile_path
);
78 BAIL_ON_PTR_ERROR(i
->profile_path
, wbc_status
);
79 i
->home_directory
= talloc_strdup(i
, resp
->data
.auth
.info3
.home_dir
);
80 BAIL_ON_PTR_ERROR(i
->home_directory
, wbc_status
);
81 i
->home_drive
= talloc_strdup(i
, resp
->data
.auth
.info3
.dir_drive
);
82 BAIL_ON_PTR_ERROR(i
->home_drive
, wbc_status
);
85 i
->num_sids
+= resp
->data
.auth
.info3
.num_groups
;
86 i
->num_sids
+= resp
->data
.auth
.info3
.num_other_sids
;
88 i
->sids
= talloc_array(i
, struct wbcSidWithAttr
, i
->num_sids
);
89 BAIL_ON_PTR_ERROR(i
->sids
, wbc_status
);
91 wbc_status
= wbcStringToSid(resp
->data
.auth
.info3
.dom_sid
,
93 BAIL_ON_WBC_ERROR(wbc_status
);
95 #define _SID_COMPOSE(s, d, r, a) { \
97 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
98 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
100 wbc_status = WBC_ERR_INVALID_SID; \
101 BAIL_ON_WBC_ERROR(wbc_status); \
103 (s).attributes = a; \
107 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
108 resp
->data
.auth
.info3
.user_rid
,
111 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
112 resp
->data
.auth
.info3
.group_rid
,
116 p
= (char *)resp
->extra_data
.data
;
118 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
119 BAIL_ON_WBC_ERROR(wbc_status
);
122 for (j
=0; j
< resp
->data
.auth
.info3
.num_groups
; j
++) {
127 char *e
= strchr(p
, '\n');
129 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
130 BAIL_ON_WBC_ERROR(wbc_status
);
135 ret
= sscanf(s
, "0x%08X:0x%08X", &rid
, &attrs
);
137 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
138 BAIL_ON_WBC_ERROR(wbc_status
);
141 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
146 for (j
=0; j
< resp
->data
.auth
.info3
.num_other_sids
; j
++) {
151 char *e
= strchr(p
, '\n');
153 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
154 BAIL_ON_WBC_ERROR(wbc_status
);
161 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
162 BAIL_ON_WBC_ERROR(wbc_status
);
167 ret
= sscanf(a
, "0x%08X",
170 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
171 BAIL_ON_WBC_ERROR(wbc_status
);
174 wbc_status
= wbcStringToSid(s
, &i
->sids
[sn
].sid
);
175 BAIL_ON_WBC_ERROR(wbc_status
);
177 i
->sids
[sn
].attributes
= attrs
;
190 /* FIXME: Currently this is still a copy of the same function from wbc_pam.c */
191 static wbcErr
wbc_create_error_info(const struct winbindd_response
*resp
,
192 struct wbcAuthErrorInfo
**_e
)
194 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
195 struct wbcAuthErrorInfo
*e
;
197 e
= talloc(NULL
, struct wbcAuthErrorInfo
);
198 BAIL_ON_PTR_ERROR(e
, wbc_status
);
200 e
->nt_status
= resp
->data
.auth
.nt_status
;
201 e
->pam_error
= resp
->data
.auth
.pam_error
;
202 e
->nt_string
= talloc_strdup(e
, resp
->data
.auth
.nt_status_string
);
203 BAIL_ON_PTR_ERROR(e
->nt_string
, wbc_status
);
205 e
->display_string
= talloc_strdup(e
, resp
->data
.auth
.error_string
);
206 BAIL_ON_PTR_ERROR(e
->display_string
, wbc_status
);
216 struct wbc_authenticate_user_ex_state
{
217 struct winbindd_request req
;
218 struct tevent_context
*ev
;
219 struct wb_context
*wb_ctx
;
220 const struct wbcAuthUserParams
*params
;
221 struct wbcAuthUserInfo
*info
;
222 struct wbcAuthErrorInfo
*error
;
225 static void wbcAuthenticateUserEx_got_info(struct tevent_req
*subreq
);
226 static void wbcAuthenticateUserEx_done(struct tevent_req
*subreq
);
228 struct tevent_req
*wbcAuthenticateUserEx_send(TALLOC_CTX
*mem_ctx
,
229 struct tevent_context
*ev
,
230 struct wb_context
*wb_ctx
,
231 const struct wbcAuthUserParams
*params
)
233 struct tevent_req
*req
, *subreq
;
234 struct wbc_authenticate_user_ex_state
*state
;
236 req
= tevent_req_create(mem_ctx
, &state
,
237 struct wbc_authenticate_user_ex_state
);
243 state
->wb_ctx
= wb_ctx
;
244 state
->params
= params
;
247 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
248 return tevent_req_post(req
, ev
);
251 if (!params
->account_name
) {
252 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
253 return tevent_req_post(req
, ev
);
256 ZERO_STRUCT(state
->req
);
259 state
->req
.flags
= params
->flags
;
262 switch (params
->level
) {
263 case WBC_AUTH_USER_LEVEL_PLAIN
:
264 state
->req
.cmd
= WINBINDD_PAM_AUTH
;
265 state
->req
.flags
|= WBFLAG_PAM_INFO3_TEXT
|
266 WBFLAG_PAM_USER_SESSION_KEY
|
269 if (!params
->password
.plaintext
) {
270 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
271 return tevent_req_post(req
, ev
);
274 strncpy(state
->req
.data
.auth
.pass
,
275 params
->password
.plaintext
,
276 sizeof(state
->req
.data
.auth
.pass
)-1);
278 if (params
->domain_name
&& params
->domain_name
[0]) {
279 /* We need to get the winbind separator :-( */
280 subreq
= wbcInfo_send(state
, ev
, wb_ctx
);
281 if (tevent_req_nomem(subreq
, req
)) {
282 return tevent_req_post(req
, ev
);
285 tevent_req_set_callback(subreq
,
286 wbcAuthenticateUserEx_got_info
,
290 strncpy(state
->req
.data
.auth
.user
,
291 params
->account_name
,
292 sizeof(state
->req
.data
.auth
.user
)-1);
297 case WBC_AUTH_USER_LEVEL_HASH
:
298 tevent_req_error(req
, WBC_ERR_NOT_IMPLEMENTED
);
299 return tevent_req_post(req
, ev
);
300 /* Make some static code checkers happy */
303 case WBC_AUTH_USER_LEVEL_RESPONSE
:
304 state
->req
.cmd
= WINBINDD_PAM_AUTH_CRAP
;
305 state
->req
.flags
|= WBFLAG_PAM_INFO3_TEXT
|
306 WBFLAG_PAM_USER_SESSION_KEY
|
309 if (params
->password
.response
.lm_length
&&
310 !params
->password
.response
.lm_data
) {
311 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
312 return tevent_req_post(req
, ev
);
314 if (params
->password
.response
.lm_length
== 0 &&
315 params
->password
.response
.lm_data
) {
316 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
317 return tevent_req_post(req
, ev
);
320 if (params
->password
.response
.nt_length
&&
321 !params
->password
.response
.nt_data
) {
322 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
323 return tevent_req_post(req
, ev
);
325 if (params
->password
.response
.nt_length
== 0&&
326 params
->password
.response
.nt_data
) {
327 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
328 return tevent_req_post(req
, ev
);
331 strncpy(state
->req
.data
.auth_crap
.user
,
332 params
->account_name
,
333 sizeof(state
->req
.data
.auth_crap
.user
)-1);
334 if (params
->domain_name
) {
335 strncpy(state
->req
.data
.auth_crap
.domain
,
337 sizeof(state
->req
.data
.auth_crap
.domain
)-1);
339 if (params
->workstation_name
) {
340 strncpy(state
->req
.data
.auth_crap
.workstation
,
341 params
->workstation_name
,
342 sizeof(state
->req
.data
.auth_crap
.workstation
)-1);
345 state
->req
.data
.auth_crap
.logon_parameters
=
346 params
->parameter_control
;
348 memcpy(state
->req
.data
.auth_crap
.chal
,
349 params
->password
.response
.challenge
,
350 sizeof(state
->req
.data
.auth_crap
.chal
));
352 state
->req
.data
.auth_crap
.lm_resp_len
=
353 MIN(params
->password
.response
.lm_length
,
354 sizeof(state
->req
.data
.auth_crap
.lm_resp
));
355 state
->req
.data
.auth_crap
.nt_resp_len
=
356 MIN(params
->password
.response
.nt_length
,
357 sizeof(state
->req
.data
.auth_crap
.nt_resp
));
358 if (params
->password
.response
.lm_data
) {
359 memcpy(state
->req
.data
.auth_crap
.lm_resp
,
360 params
->password
.response
.lm_data
,
361 state
->req
.data
.auth_crap
.lm_resp_len
);
363 if (params
->password
.response
.nt_data
) {
364 memcpy(state
->req
.data
.auth_crap
.nt_resp
,
365 params
->password
.response
.nt_data
,
366 state
->req
.data
.auth_crap
.nt_resp_len
);
370 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
371 return tevent_req_post(req
, ev
);
375 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
376 if (tevent_req_nomem(subreq
, req
)) {
377 return tevent_req_post(req
, ev
);
380 tevent_req_set_callback(subreq
, wbcAuthenticateUserEx_done
, req
);
384 static void wbcAuthenticateUserEx_got_info(struct tevent_req
*subreq
)
386 struct tevent_req
*req
= tevent_req_callback_data(
387 subreq
, struct tevent_req
);
388 struct wbc_authenticate_user_ex_state
*state
= tevent_req_data(
389 req
, struct wbc_authenticate_user_ex_state
);
390 char *version_string
;
394 wbc_status
= wbcInfo_recv(subreq
, state
, &separator
, &version_string
);
396 if (!WBC_ERROR_IS_OK(wbc_status
)) {
397 tevent_req_error(req
, wbc_status
);
401 snprintf(state
->req
.data
.auth
.user
,
402 sizeof(state
->req
.data
.auth
.user
)-1,
404 state
->params
->domain_name
,
406 state
->params
->account_name
);
408 subreq
= wb_trans_send(state
, state
->ev
, state
->wb_ctx
, false,
410 if (tevent_req_nomem(subreq
, req
)) {
414 tevent_req_set_callback(subreq
, wbcAuthenticateUserEx_done
, req
);
418 static void wbcAuthenticateUserEx_done(struct tevent_req
*subreq
)
420 struct tevent_req
*req
= tevent_req_callback_data(
421 subreq
, struct tevent_req
);
422 struct wbc_authenticate_user_ex_state
*state
= tevent_req_data(
423 req
, struct wbc_authenticate_user_ex_state
);
424 struct winbindd_response
*resp
;
429 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
431 if (!WBC_ERROR_IS_OK(wbc_status
)) {
432 tevent_req_error(req
, wbc_status
);
436 if (resp
->data
.auth
.nt_status
!= 0) {
437 wbc_status
= wbc_create_error_info(resp
, &state
->error
);
438 if (!WBC_ERROR_IS_OK(wbc_status
)) {
439 tevent_req_error(req
, wbc_status
);
443 tevent_req_error(req
, WBC_ERR_AUTH_ERROR
);
447 wbc_status
= wbc_create_auth_info(state
, resp
, &state
->info
);
448 if (!WBC_ERROR_IS_OK(wbc_status
)) {
449 tevent_req_error(req
, wbc_status
);
457 wbcErr
wbcAuthenticateUserEx_recv(struct tevent_req
*req
,
459 struct wbcAuthUserInfo
**info
,
460 struct wbcAuthErrorInfo
**error
)
462 struct wbc_authenticate_user_ex_state
*state
= tevent_req_data(
463 req
, struct wbc_authenticate_user_ex_state
);
470 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
471 tevent_req_received(req
);
473 *error
= talloc_steal(mem_ctx
, state
->error
);
479 *info
= talloc_steal(mem_ctx
, state
->info
);
482 tevent_req_received(req
);