2 Unix SMB/CIFS implementation.
6 Copyright (C) Gerald (Jerry) Carter 2007
7 Copyright (C) Guenther Deschner 2008
8 Copyright (C) Volker Lendecke 2009
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /* Required Headers */
27 #include "libwbclient.h"
28 #include "../winbind_client.h"
30 /* Authenticate a username/password pair */
31 wbcErr
wbcAuthenticateUser(const char *username
,
34 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
35 struct wbcAuthUserParams params
;
39 params
.account_name
= username
;
40 params
.level
= WBC_AUTH_USER_LEVEL_PLAIN
;
41 params
.password
.plaintext
= password
;
43 wbc_status
= wbcAuthenticateUserEx(¶ms
, NULL
, NULL
);
44 BAIL_ON_WBC_ERROR(wbc_status
);
50 static wbcErr
wbc_create_auth_info(TALLOC_CTX
*mem_ctx
,
51 const struct winbindd_response
*resp
,
52 struct wbcAuthUserInfo
**_i
)
54 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
55 struct wbcAuthUserInfo
*i
;
56 struct wbcDomainSid domain_sid
;
61 i
= talloc(mem_ctx
, struct wbcAuthUserInfo
);
62 BAIL_ON_PTR_ERROR(i
, wbc_status
);
64 i
->user_flags
= resp
->data
.auth
.info3
.user_flgs
;
66 i
->account_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.user_name
);
67 BAIL_ON_PTR_ERROR(i
->account_name
, wbc_status
);
68 i
->user_principal
= NULL
;
69 i
->full_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.full_name
);
70 BAIL_ON_PTR_ERROR(i
->full_name
, wbc_status
);
71 i
->domain_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_dom
);
72 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
73 i
->dns_domain_name
= NULL
;
75 i
->acct_flags
= resp
->data
.auth
.info3
.acct_flags
;
76 memcpy(i
->user_session_key
,
77 resp
->data
.auth
.user_session_key
,
78 sizeof(i
->user_session_key
));
79 memcpy(i
->lm_session_key
,
80 resp
->data
.auth
.first_8_lm_hash
,
81 sizeof(i
->lm_session_key
));
83 i
->logon_count
= resp
->data
.auth
.info3
.logon_count
;
84 i
->bad_password_count
= resp
->data
.auth
.info3
.bad_pw_count
;
86 i
->logon_time
= resp
->data
.auth
.info3
.logon_time
;
87 i
->logoff_time
= resp
->data
.auth
.info3
.logoff_time
;
88 i
->kickoff_time
= resp
->data
.auth
.info3
.kickoff_time
;
89 i
->pass_last_set_time
= resp
->data
.auth
.info3
.pass_last_set_time
;
90 i
->pass_can_change_time
= resp
->data
.auth
.info3
.pass_can_change_time
;
91 i
->pass_must_change_time
= resp
->data
.auth
.info3
.pass_must_change_time
;
93 i
->logon_server
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_srv
);
94 BAIL_ON_PTR_ERROR(i
->logon_server
, wbc_status
);
95 i
->logon_script
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_script
);
96 BAIL_ON_PTR_ERROR(i
->logon_script
, wbc_status
);
97 i
->profile_path
= talloc_strdup(i
, resp
->data
.auth
.info3
.profile_path
);
98 BAIL_ON_PTR_ERROR(i
->profile_path
, wbc_status
);
99 i
->home_directory
= talloc_strdup(i
, resp
->data
.auth
.info3
.home_dir
);
100 BAIL_ON_PTR_ERROR(i
->home_directory
, wbc_status
);
101 i
->home_drive
= talloc_strdup(i
, resp
->data
.auth
.info3
.dir_drive
);
102 BAIL_ON_PTR_ERROR(i
->home_drive
, wbc_status
);
105 i
->num_sids
+= resp
->data
.auth
.info3
.num_groups
;
106 i
->num_sids
+= resp
->data
.auth
.info3
.num_other_sids
;
108 i
->sids
= talloc_array(i
, struct wbcSidWithAttr
, i
->num_sids
);
109 BAIL_ON_PTR_ERROR(i
->sids
, wbc_status
);
111 wbc_status
= wbcStringToSid(resp
->data
.auth
.info3
.dom_sid
,
113 BAIL_ON_WBC_ERROR(wbc_status
);
115 #define _SID_COMPOSE(s, d, r, a) { \
117 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
118 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
120 wbc_status = WBC_ERR_INVALID_SID; \
121 BAIL_ON_WBC_ERROR(wbc_status); \
123 (s).attributes = a; \
127 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
128 resp
->data
.auth
.info3
.user_rid
,
131 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
132 resp
->data
.auth
.info3
.group_rid
,
136 p
= (char *)resp
->extra_data
.data
;
138 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
139 BAIL_ON_WBC_ERROR(wbc_status
);
142 for (j
=0; j
< resp
->data
.auth
.info3
.num_groups
; j
++) {
147 char *e
= strchr(p
, '\n');
149 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
150 BAIL_ON_WBC_ERROR(wbc_status
);
155 ret
= sscanf(s
, "0x%08X:0x%08X", &rid
, &attrs
);
157 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
158 BAIL_ON_WBC_ERROR(wbc_status
);
161 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
166 for (j
=0; j
< resp
->data
.auth
.info3
.num_other_sids
; j
++) {
171 char *e
= strchr(p
, '\n');
173 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
174 BAIL_ON_WBC_ERROR(wbc_status
);
181 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
182 BAIL_ON_WBC_ERROR(wbc_status
);
187 ret
= sscanf(a
, "0x%08X",
190 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
191 BAIL_ON_WBC_ERROR(wbc_status
);
194 wbc_status
= wbcStringToSid(s
, &i
->sids
[sn
].sid
);
195 BAIL_ON_WBC_ERROR(wbc_status
);
197 i
->sids
[sn
].attributes
= attrs
;
210 static wbcErr
wbc_create_error_info(const struct winbindd_response
*resp
,
211 struct wbcAuthErrorInfo
**_e
)
213 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
214 struct wbcAuthErrorInfo
*e
;
216 e
= talloc(NULL
, struct wbcAuthErrorInfo
);
217 BAIL_ON_PTR_ERROR(e
, wbc_status
);
219 e
->nt_status
= resp
->data
.auth
.nt_status
;
220 e
->pam_error
= resp
->data
.auth
.pam_error
;
221 e
->nt_string
= talloc_strdup(e
, resp
->data
.auth
.nt_status_string
);
222 BAIL_ON_PTR_ERROR(e
->nt_string
, wbc_status
);
224 e
->display_string
= talloc_strdup(e
, resp
->data
.auth
.error_string
);
225 BAIL_ON_PTR_ERROR(e
->display_string
, wbc_status
);
235 static wbcErr
wbc_create_password_policy_info(const struct winbindd_response
*resp
,
236 struct wbcUserPasswordPolicyInfo
**_i
)
238 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
239 struct wbcUserPasswordPolicyInfo
*i
;
241 i
= talloc(NULL
, struct wbcUserPasswordPolicyInfo
);
242 BAIL_ON_PTR_ERROR(i
, wbc_status
);
244 i
->min_passwordage
= resp
->data
.auth
.policy
.min_passwordage
;
245 i
->min_length_password
= resp
->data
.auth
.policy
.min_length_password
;
246 i
->password_history
= resp
->data
.auth
.policy
.password_history
;
247 i
->password_properties
= resp
->data
.auth
.policy
.password_properties
;
248 i
->expire
= resp
->data
.auth
.policy
.expire
;
258 static wbcErr
wbc_create_logon_info(struct winbindd_response
*resp
,
259 struct wbcLogonUserInfo
**_i
)
261 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
262 struct wbcLogonUserInfo
*i
;
264 i
= talloc_zero(NULL
, struct wbcLogonUserInfo
);
265 BAIL_ON_PTR_ERROR(i
, wbc_status
);
267 wbc_status
= wbc_create_auth_info(i
, resp
, &i
->info
);
268 BAIL_ON_WBC_ERROR(wbc_status
);
270 if (resp
->data
.auth
.krb5ccname
&&
271 strlen(resp
->data
.auth
.krb5ccname
)) {
272 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
276 (uint8_t *)resp
->data
.auth
.krb5ccname
,
277 strlen(resp
->data
.auth
.krb5ccname
)+1);
278 BAIL_ON_WBC_ERROR(wbc_status
);
281 if (resp
->data
.auth
.unix_username
&&
282 strlen(resp
->data
.auth
.unix_username
)) {
283 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
287 (uint8_t *)resp
->data
.auth
.unix_username
,
288 strlen(resp
->data
.auth
.unix_username
)+1);
289 BAIL_ON_WBC_ERROR(wbc_status
);
295 if (!WBC_ERROR_IS_OK(wbc_status
) && i
) {
296 wbcFreeMemory(i
->blobs
);
303 struct wbc_authenticate_user_ex_state
{
304 struct winbindd_request req
;
305 struct tevent_context
*ev
;
306 struct wb_context
*wb_ctx
;
307 const struct wbcAuthUserParams
*params
;
308 struct wbcAuthUserInfo
*info
;
309 struct wbcAuthErrorInfo
*error
;
312 static void wbcAuthenticateUserEx_got_info(struct tevent_req
*subreq
);
313 static void wbcAuthenticateUserEx_done(struct tevent_req
*subreq
);
315 struct tevent_req
*wbcAuthenticateUserEx_send(TALLOC_CTX
*mem_ctx
,
316 struct tevent_context
*ev
,
317 struct wb_context
*wb_ctx
,
318 const struct wbcAuthUserParams
*params
)
320 struct tevent_req
*req
, *subreq
;
321 struct wbc_authenticate_user_ex_state
*state
;
323 req
= tevent_req_create(mem_ctx
, &state
,
324 struct wbc_authenticate_user_ex_state
);
330 state
->wb_ctx
= wb_ctx
;
331 state
->params
= params
;
334 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
335 return tevent_req_post(req
, ev
);
338 if (!params
->account_name
) {
339 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
340 return tevent_req_post(req
, ev
);
343 ZERO_STRUCT(state
->req
);
346 state
->req
.flags
= params
->flags
;
349 switch (params
->level
) {
350 case WBC_AUTH_USER_LEVEL_PLAIN
:
351 state
->req
.cmd
= WINBINDD_PAM_AUTH
;
352 state
->req
.flags
|= WBFLAG_PAM_INFO3_TEXT
|
353 WBFLAG_PAM_USER_SESSION_KEY
|
356 if (!params
->password
.plaintext
) {
357 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
358 return tevent_req_post(req
, ev
);
361 strncpy(state
->req
.data
.auth
.pass
,
362 params
->password
.plaintext
,
363 sizeof(state
->req
.data
.auth
.pass
)-1);
365 if (params
->domain_name
&& params
->domain_name
[0]) {
366 /* We need to get the winbind separator :-( */
367 subreq
= wbcInfo_send(state
, ev
, wb_ctx
);
368 if (tevent_req_nomem(subreq
, req
)) {
369 return tevent_req_post(req
, ev
);
372 tevent_req_set_callback(subreq
,
373 wbcAuthenticateUserEx_got_info
,
377 strncpy(state
->req
.data
.auth
.user
,
378 params
->account_name
,
379 sizeof(state
->req
.data
.auth
.user
)-1);
384 case WBC_AUTH_USER_LEVEL_HASH
:
385 tevent_req_error(req
, WBC_ERR_NOT_IMPLEMENTED
);
386 return tevent_req_post(req
, ev
);
387 /* Make some static code checkers happy */
390 case WBC_AUTH_USER_LEVEL_RESPONSE
:
391 state
->req
.cmd
= WINBINDD_PAM_AUTH_CRAP
;
392 state
->req
.flags
|= WBFLAG_PAM_INFO3_TEXT
|
393 WBFLAG_PAM_USER_SESSION_KEY
|
396 if (params
->password
.response
.lm_length
&&
397 !params
->password
.response
.lm_data
) {
398 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
399 return tevent_req_post(req
, ev
);
401 if (params
->password
.response
.lm_length
== 0 &&
402 params
->password
.response
.lm_data
) {
403 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
404 return tevent_req_post(req
, ev
);
407 if (params
->password
.response
.nt_length
&&
408 !params
->password
.response
.nt_data
) {
409 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
410 return tevent_req_post(req
, ev
);
412 if (params
->password
.response
.nt_length
== 0&&
413 params
->password
.response
.nt_data
) {
414 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
415 return tevent_req_post(req
, ev
);
418 strncpy(state
->req
.data
.auth_crap
.user
,
419 params
->account_name
,
420 sizeof(state
->req
.data
.auth_crap
.user
)-1);
421 if (params
->domain_name
) {
422 strncpy(state
->req
.data
.auth_crap
.domain
,
424 sizeof(state
->req
.data
.auth_crap
.domain
)-1);
426 if (params
->workstation_name
) {
427 strncpy(state
->req
.data
.auth_crap
.workstation
,
428 params
->workstation_name
,
429 sizeof(state
->req
.data
.auth_crap
.workstation
)-1);
432 state
->req
.data
.auth_crap
.logon_parameters
=
433 params
->parameter_control
;
435 memcpy(state
->req
.data
.auth_crap
.chal
,
436 params
->password
.response
.challenge
,
437 sizeof(state
->req
.data
.auth_crap
.chal
));
439 state
->req
.data
.auth_crap
.lm_resp_len
=
440 MIN(params
->password
.response
.lm_length
,
441 sizeof(state
->req
.data
.auth_crap
.lm_resp
));
442 state
->req
.data
.auth_crap
.nt_resp_len
=
443 MIN(params
->password
.response
.nt_length
,
444 sizeof(state
->req
.data
.auth_crap
.nt_resp
));
445 if (params
->password
.response
.lm_data
) {
446 memcpy(state
->req
.data
.auth_crap
.lm_resp
,
447 params
->password
.response
.lm_data
,
448 state
->req
.data
.auth_crap
.lm_resp_len
);
450 if (params
->password
.response
.nt_data
) {
451 memcpy(state
->req
.data
.auth_crap
.nt_resp
,
452 params
->password
.response
.nt_data
,
453 state
->req
.data
.auth_crap
.nt_resp_len
);
457 tevent_req_error(req
, WBC_ERR_INVALID_PARAM
);
458 return tevent_req_post(req
, ev
);
462 subreq
= wb_trans_send(state
, ev
, wb_ctx
, false, &state
->req
);
463 if (tevent_req_nomem(subreq
, req
)) {
464 return tevent_req_post(req
, ev
);
467 tevent_req_set_callback(subreq
, wbcAuthenticateUserEx_done
, req
);
471 static void wbcAuthenticateUserEx_got_info(struct tevent_req
*subreq
)
473 struct tevent_req
*req
= tevent_req_callback_data(
474 subreq
, struct tevent_req
);
475 struct wbc_authenticate_user_ex_state
*state
= tevent_req_data(
476 req
, struct wbc_authenticate_user_ex_state
);
477 char *version_string
;
481 wbc_status
= wbcInfo_recv(subreq
, state
, &separator
, &version_string
);
483 if (!WBC_ERROR_IS_OK(wbc_status
)) {
484 tevent_req_error(req
, wbc_status
);
488 snprintf(state
->req
.data
.auth
.user
,
489 sizeof(state
->req
.data
.auth
.user
)-1,
491 state
->params
->domain_name
,
493 state
->params
->account_name
);
495 subreq
= wb_trans_send(state
, state
->ev
, state
->wb_ctx
, false,
497 if (tevent_req_nomem(subreq
, req
)) {
501 tevent_req_set_callback(subreq
, wbcAuthenticateUserEx_done
, req
);
505 static void wbcAuthenticateUserEx_done(struct tevent_req
*subreq
)
507 struct tevent_req
*req
= tevent_req_callback_data(
508 subreq
, struct tevent_req
);
509 struct wbc_authenticate_user_ex_state
*state
= tevent_req_data(
510 req
, struct wbc_authenticate_user_ex_state
);
511 struct winbindd_response
*resp
;
516 wbc_status
= wb_trans_recv(subreq
, state
, &resp
);
518 if (!WBC_ERROR_IS_OK(wbc_status
)) {
519 tevent_req_error(req
, wbc_status
);
523 if (resp
->data
.auth
.nt_status
!= 0) {
524 wbc_status
= wbc_create_error_info(resp
, &state
->error
);
525 if (!WBC_ERROR_IS_OK(wbc_status
)) {
526 tevent_req_error(req
, wbc_status
);
530 tevent_req_error(req
, WBC_ERR_AUTH_ERROR
);
534 wbc_status
= wbc_create_auth_info(state
, resp
, &state
->info
);
535 if (!WBC_ERROR_IS_OK(wbc_status
)) {
536 tevent_req_error(req
, wbc_status
);
544 wbcErr
wbcAuthenticateUserEx_recv(struct tevent_req
*req
,
546 struct wbcAuthUserInfo
**info
,
547 struct wbcAuthErrorInfo
**error
)
549 struct wbc_authenticate_user_ex_state
*state
= tevent_req_data(
550 req
, struct wbc_authenticate_user_ex_state
);
557 if (tevent_req_is_wbcerr(req
, &wbc_status
)) {
558 tevent_req_received(req
);
560 *error
= talloc_steal(mem_ctx
, state
->error
);
566 *info
= talloc_steal(mem_ctx
, state
->info
);
569 tevent_req_received(req
);
573 /* Authenticate with more detailed information */
574 wbcErr
wbcAuthenticateUserEx(const struct wbcAuthUserParams
*params
,
575 struct wbcAuthUserInfo
**info
,
576 struct wbcAuthErrorInfo
**error
)
578 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
580 struct winbindd_request request
;
581 struct winbindd_response response
;
583 ZERO_STRUCT(request
);
584 ZERO_STRUCT(response
);
591 wbc_status
= WBC_ERR_INVALID_PARAM
;
592 BAIL_ON_WBC_ERROR(wbc_status
);
595 if (!params
->account_name
) {
596 wbc_status
= WBC_ERR_INVALID_PARAM
;
597 BAIL_ON_WBC_ERROR(wbc_status
);
600 /* Initialize request */
602 switch (params
->level
) {
603 case WBC_AUTH_USER_LEVEL_PLAIN
:
604 cmd
= WINBINDD_PAM_AUTH
;
605 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
606 WBFLAG_PAM_USER_SESSION_KEY
|
609 if (!params
->password
.plaintext
) {
610 wbc_status
= WBC_ERR_INVALID_PARAM
;
611 BAIL_ON_WBC_ERROR(wbc_status
);
614 if (params
->domain_name
&& params
->domain_name
[0]) {
615 /* We need to get the winbind separator :-( */
616 struct winbindd_response sep_response
;
618 ZERO_STRUCT(sep_response
);
620 wbc_status
= wbcRequestResponse(WINBINDD_INFO
,
621 NULL
, &sep_response
);
622 BAIL_ON_WBC_ERROR(wbc_status
);
624 snprintf(request
.data
.auth
.user
,
625 sizeof(request
.data
.auth
.user
)-1,
628 sep_response
.data
.info
.winbind_separator
,
629 params
->account_name
);
631 strncpy(request
.data
.auth
.user
,
632 params
->account_name
,
633 sizeof(request
.data
.auth
.user
)-1);
636 strncpy(request
.data
.auth
.pass
,
637 params
->password
.plaintext
,
638 sizeof(request
.data
.auth
.pass
)-1);
641 case WBC_AUTH_USER_LEVEL_HASH
:
642 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
643 BAIL_ON_WBC_ERROR(wbc_status
);
646 case WBC_AUTH_USER_LEVEL_RESPONSE
:
647 cmd
= WINBINDD_PAM_AUTH_CRAP
;
648 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
649 WBFLAG_PAM_USER_SESSION_KEY
|
652 if (params
->password
.response
.lm_length
&&
653 !params
->password
.response
.lm_data
) {
654 wbc_status
= WBC_ERR_INVALID_PARAM
;
655 BAIL_ON_WBC_ERROR(wbc_status
);
657 if (params
->password
.response
.lm_length
== 0 &&
658 params
->password
.response
.lm_data
) {
659 wbc_status
= WBC_ERR_INVALID_PARAM
;
660 BAIL_ON_WBC_ERROR(wbc_status
);
663 if (params
->password
.response
.nt_length
&&
664 !params
->password
.response
.nt_data
) {
665 wbc_status
= WBC_ERR_INVALID_PARAM
;
666 BAIL_ON_WBC_ERROR(wbc_status
);
668 if (params
->password
.response
.nt_length
== 0&&
669 params
->password
.response
.nt_data
) {
670 wbc_status
= WBC_ERR_INVALID_PARAM
;
671 BAIL_ON_WBC_ERROR(wbc_status
);
674 strncpy(request
.data
.auth_crap
.user
,
675 params
->account_name
,
676 sizeof(request
.data
.auth_crap
.user
)-1);
677 if (params
->domain_name
) {
678 strncpy(request
.data
.auth_crap
.domain
,
680 sizeof(request
.data
.auth_crap
.domain
)-1);
682 if (params
->workstation_name
) {
683 strncpy(request
.data
.auth_crap
.workstation
,
684 params
->workstation_name
,
685 sizeof(request
.data
.auth_crap
.workstation
)-1);
688 request
.data
.auth_crap
.logon_parameters
=
689 params
->parameter_control
;
691 memcpy(request
.data
.auth_crap
.chal
,
692 params
->password
.response
.challenge
,
693 sizeof(request
.data
.auth_crap
.chal
));
695 request
.data
.auth_crap
.lm_resp_len
=
696 MIN(params
->password
.response
.lm_length
,
697 sizeof(request
.data
.auth_crap
.lm_resp
));
698 if (params
->password
.response
.lm_data
) {
699 memcpy(request
.data
.auth_crap
.lm_resp
,
700 params
->password
.response
.lm_data
,
701 request
.data
.auth_crap
.lm_resp_len
);
703 request
.data
.auth_crap
.nt_resp_len
= params
->password
.response
.nt_length
;
704 if (params
->password
.response
.nt_length
> sizeof(request
.data
.auth_crap
.nt_resp
)) {
705 request
.flags
|= WBFLAG_BIG_NTLMV2_BLOB
;
706 request
.extra_len
= params
->password
.response
.nt_length
;
707 request
.extra_data
.data
= talloc_zero_array(NULL
, char, request
.extra_len
);
708 if (request
.extra_data
.data
== NULL
) {
709 wbc_status
= WBC_ERR_NO_MEMORY
;
710 BAIL_ON_WBC_ERROR(wbc_status
);
712 memcpy(request
.extra_data
.data
,
713 params
->password
.response
.nt_data
,
714 request
.data
.auth_crap
.nt_resp_len
);
715 } else if (params
->password
.response
.nt_data
) {
716 memcpy(request
.data
.auth_crap
.nt_resp
,
717 params
->password
.response
.nt_data
,
718 request
.data
.auth_crap
.nt_resp_len
);
726 wbc_status
= WBC_ERR_INVALID_PARAM
;
727 BAIL_ON_WBC_ERROR(wbc_status
);
731 request
.flags
|= params
->flags
;
734 wbc_status
= wbcRequestResponse(cmd
,
737 if (response
.data
.auth
.nt_status
!= 0) {
739 wbc_status
= wbc_create_error_info(&response
,
741 BAIL_ON_WBC_ERROR(wbc_status
);
744 wbc_status
= WBC_ERR_AUTH_ERROR
;
745 BAIL_ON_WBC_ERROR(wbc_status
);
747 BAIL_ON_WBC_ERROR(wbc_status
);
750 wbc_status
= wbc_create_auth_info(NULL
,
753 BAIL_ON_WBC_ERROR(wbc_status
);
757 winbindd_free_response(&response
);
759 talloc_free(request
.extra_data
.data
);
764 /* Trigger a verification of the trust credentials of a specific domain */
765 wbcErr
wbcCheckTrustCredentials(const char *domain
,
766 struct wbcAuthErrorInfo
**error
)
768 struct winbindd_request request
;
769 struct winbindd_response response
;
770 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
772 ZERO_STRUCT(request
);
773 ZERO_STRUCT(response
);
776 strncpy(request
.domain_name
, domain
,
777 sizeof(request
.domain_name
)-1);
782 wbc_status
= wbcRequestResponse(WINBINDD_CHECK_MACHACC
,
785 if (response
.data
.auth
.nt_status
!= 0) {
787 wbc_status
= wbc_create_error_info(&response
,
789 BAIL_ON_WBC_ERROR(wbc_status
);
792 wbc_status
= WBC_ERR_AUTH_ERROR
;
793 BAIL_ON_WBC_ERROR(wbc_status
);
795 BAIL_ON_WBC_ERROR(wbc_status
);
801 /* Trigger a change of the trust credentials for a specific domain */
802 wbcErr
wbcChangeTrustCredentials(const char *domain
,
803 struct wbcAuthErrorInfo
**error
)
805 struct winbindd_request request
;
806 struct winbindd_response response
;
807 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
809 ZERO_STRUCT(request
);
810 ZERO_STRUCT(response
);
813 strncpy(request
.domain_name
, domain
,
814 sizeof(request
.domain_name
)-1);
819 wbc_status
= wbcRequestResponse(WINBINDD_CHANGE_MACHACC
,
822 if (response
.data
.auth
.nt_status
!= 0) {
824 wbc_status
= wbc_create_error_info(&response
,
826 BAIL_ON_WBC_ERROR(wbc_status
);
829 wbc_status
= WBC_ERR_AUTH_ERROR
;
830 BAIL_ON_WBC_ERROR(wbc_status
);
832 BAIL_ON_WBC_ERROR(wbc_status
);
839 * Trigger a no-op NETLOGON call. Lightweight version of
840 * wbcCheckTrustCredentials
842 wbcErr
wbcPingDc(const char *domain
, struct wbcAuthErrorInfo
**error
)
844 struct winbindd_request request
;
845 struct winbindd_response response
;
846 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
850 * the current protocol doesn't support
851 * specifying a domain
853 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
854 BAIL_ON_WBC_ERROR(wbc_status
);
857 ZERO_STRUCT(request
);
858 ZERO_STRUCT(response
);
862 wbc_status
= wbcRequestResponse(WINBINDD_PING_DC
,
865 if (response
.data
.auth
.nt_status
!= 0) {
867 wbc_status
= wbc_create_error_info(&response
,
869 BAIL_ON_WBC_ERROR(wbc_status
);
872 wbc_status
= WBC_ERR_AUTH_ERROR
;
873 BAIL_ON_WBC_ERROR(wbc_status
);
875 BAIL_ON_WBC_ERROR(wbc_status
);
881 /* Trigger an extended logoff notification to Winbind for a specific user */
882 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
883 struct wbcAuthErrorInfo
**error
)
885 struct winbindd_request request
;
886 struct winbindd_response response
;
887 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
892 if (!params
|| !params
->username
) {
893 wbc_status
= WBC_ERR_INVALID_PARAM
;
894 BAIL_ON_WBC_ERROR(wbc_status
);
897 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
898 wbc_status
= WBC_ERR_INVALID_PARAM
;
899 BAIL_ON_WBC_ERROR(wbc_status
);
901 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
902 wbc_status
= WBC_ERR_INVALID_PARAM
;
903 BAIL_ON_WBC_ERROR(wbc_status
);
906 ZERO_STRUCT(request
);
907 ZERO_STRUCT(response
);
909 strncpy(request
.data
.logoff
.user
, params
->username
,
910 sizeof(request
.data
.logoff
.user
)-1);
912 for (i
=0; i
<params
->num_blobs
; i
++) {
914 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
915 if (params
->blobs
[i
].blob
.data
) {
916 strncpy(request
.data
.logoff
.krb5ccname
,
917 (const char *)params
->blobs
[i
].blob
.data
,
918 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
923 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
924 if (params
->blobs
[i
].blob
.data
) {
925 memcpy(&request
.data
.logoff
.uid
,
926 params
->blobs
[i
].blob
.data
,
927 MIN(params
->blobs
[i
].blob
.length
,
928 sizeof(request
.data
.logoff
.uid
)));
933 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
934 if (params
->blobs
[i
].blob
.data
) {
935 memcpy(&request
.flags
,
936 params
->blobs
[i
].blob
.data
,
937 MIN(params
->blobs
[i
].blob
.length
,
938 sizeof(request
.flags
)));
946 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
950 /* Take the response above and return it to the caller */
951 if (response
.data
.auth
.nt_status
!= 0) {
953 wbc_status
= wbc_create_error_info(&response
,
955 BAIL_ON_WBC_ERROR(wbc_status
);
958 wbc_status
= WBC_ERR_AUTH_ERROR
;
959 BAIL_ON_WBC_ERROR(wbc_status
);
961 BAIL_ON_WBC_ERROR(wbc_status
);
967 /* Trigger a logoff notification to Winbind for a specific user */
968 wbcErr
wbcLogoffUser(const char *username
,
970 const char *ccfilename
)
972 struct winbindd_request request
;
973 struct winbindd_response response
;
974 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
979 wbc_status
= WBC_ERR_INVALID_PARAM
;
980 BAIL_ON_WBC_ERROR(wbc_status
);
983 ZERO_STRUCT(request
);
984 ZERO_STRUCT(response
);
986 strncpy(request
.data
.logoff
.user
, username
,
987 sizeof(request
.data
.logoff
.user
)-1);
988 request
.data
.logoff
.uid
= uid
;
991 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
992 sizeof(request
.data
.logoff
.krb5ccname
)-1);
997 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
1001 /* Take the response above and return it to the caller */
1007 /* Change a password for a user with more detailed information upon failure */
1008 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
1009 struct wbcAuthErrorInfo
**error
,
1010 enum wbcPasswordChangeRejectReason
*reject_reason
,
1011 struct wbcUserPasswordPolicyInfo
**policy
)
1013 struct winbindd_request request
;
1014 struct winbindd_response response
;
1015 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
1018 /* validate input */
1020 if (!params
->account_name
) {
1021 wbc_status
= WBC_ERR_INVALID_PARAM
;
1022 BAIL_ON_WBC_ERROR(wbc_status
);
1033 if (reject_reason
) {
1034 *reject_reason
= -1;
1037 ZERO_STRUCT(request
);
1038 ZERO_STRUCT(response
);
1040 switch (params
->level
) {
1041 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
1042 cmd
= WINBINDD_PAM_CHAUTHTOK
;
1044 if (!params
->account_name
) {
1045 wbc_status
= WBC_ERR_INVALID_PARAM
;
1046 BAIL_ON_WBC_ERROR(wbc_status
);
1049 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
1050 sizeof(request
.data
.chauthtok
.user
) - 1);
1052 if (params
->old_password
.plaintext
) {
1053 strncpy(request
.data
.chauthtok
.oldpass
,
1054 params
->old_password
.plaintext
,
1055 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
1058 if (params
->new_password
.plaintext
) {
1059 strncpy(request
.data
.chauthtok
.newpass
,
1060 params
->new_password
.plaintext
,
1061 sizeof(request
.data
.chauthtok
.newpass
) - 1);
1065 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
1066 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
1068 if (!params
->account_name
|| !params
->domain_name
) {
1069 wbc_status
= WBC_ERR_INVALID_PARAM
;
1070 BAIL_ON_WBC_ERROR(wbc_status
);
1073 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
1074 !params
->old_password
.response
.old_lm_hash_enc_data
) {
1075 wbc_status
= WBC_ERR_INVALID_PARAM
;
1076 BAIL_ON_WBC_ERROR(wbc_status
);
1079 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
1080 params
->old_password
.response
.old_lm_hash_enc_data
) {
1081 wbc_status
= WBC_ERR_INVALID_PARAM
;
1082 BAIL_ON_WBC_ERROR(wbc_status
);
1085 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
1086 !params
->old_password
.response
.old_nt_hash_enc_data
) {
1087 wbc_status
= WBC_ERR_INVALID_PARAM
;
1088 BAIL_ON_WBC_ERROR(wbc_status
);
1091 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
1092 params
->old_password
.response
.old_nt_hash_enc_data
) {
1093 wbc_status
= WBC_ERR_INVALID_PARAM
;
1094 BAIL_ON_WBC_ERROR(wbc_status
);
1097 if (params
->new_password
.response
.lm_length
&&
1098 !params
->new_password
.response
.lm_data
) {
1099 wbc_status
= WBC_ERR_INVALID_PARAM
;
1100 BAIL_ON_WBC_ERROR(wbc_status
);
1103 if (params
->new_password
.response
.lm_length
== 0 &&
1104 params
->new_password
.response
.lm_data
) {
1105 wbc_status
= WBC_ERR_INVALID_PARAM
;
1106 BAIL_ON_WBC_ERROR(wbc_status
);
1109 if (params
->new_password
.response
.nt_length
&&
1110 !params
->new_password
.response
.nt_data
) {
1111 wbc_status
= WBC_ERR_INVALID_PARAM
;
1112 BAIL_ON_WBC_ERROR(wbc_status
);
1115 if (params
->new_password
.response
.nt_length
== 0 &&
1116 params
->new_password
.response
.nt_data
) {
1117 wbc_status
= WBC_ERR_INVALID_PARAM
;
1118 BAIL_ON_WBC_ERROR(wbc_status
);
1121 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
1122 params
->account_name
,
1123 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
1125 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
1126 params
->domain_name
,
1127 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
1129 if (params
->new_password
.response
.nt_data
) {
1130 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
1131 params
->new_password
.response
.nt_data
,
1132 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
1133 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
1134 params
->new_password
.response
.nt_length
;
1137 if (params
->new_password
.response
.lm_data
) {
1138 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
1139 params
->new_password
.response
.lm_data
,
1140 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
1141 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
1142 params
->new_password
.response
.lm_length
;
1145 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
1146 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
1147 params
->old_password
.response
.old_nt_hash_enc_data
,
1148 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
1149 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
1150 params
->old_password
.response
.old_nt_hash_enc_length
;
1153 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
1154 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
1155 params
->old_password
.response
.old_lm_hash_enc_data
,
1156 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
1157 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
1158 params
->old_password
.response
.old_lm_hash_enc_length
;
1163 wbc_status
= WBC_ERR_INVALID_PARAM
;
1164 BAIL_ON_WBC_ERROR(wbc_status
);
1170 wbc_status
= wbcRequestResponse(cmd
,
1173 if (WBC_ERROR_IS_OK(wbc_status
)) {
1177 /* Take the response above and return it to the caller */
1179 if (response
.data
.auth
.nt_status
!= 0) {
1181 wbc_status
= wbc_create_error_info(&response
,
1183 BAIL_ON_WBC_ERROR(wbc_status
);
1189 wbc_status
= wbc_create_password_policy_info(&response
,
1191 BAIL_ON_WBC_ERROR(wbc_status
);
1194 if (reject_reason
) {
1195 *reject_reason
= response
.data
.auth
.reject_reason
;
1198 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
1199 BAIL_ON_WBC_ERROR(wbc_status
);
1205 /* Change a password for a user */
1206 wbcErr
wbcChangeUserPassword(const char *username
,
1207 const char *old_password
,
1208 const char *new_password
)
1210 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
1211 struct wbcChangePasswordParams params
;
1213 ZERO_STRUCT(params
);
1215 params
.account_name
= username
;
1216 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
1217 params
.old_password
.plaintext
= old_password
;
1218 params
.new_password
.plaintext
= new_password
;
1220 wbc_status
= wbcChangeUserPasswordEx(¶ms
,
1224 BAIL_ON_WBC_ERROR(wbc_status
);
1231 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
1232 struct wbcLogonUserInfo
**info
,
1233 struct wbcAuthErrorInfo
**error
,
1234 struct wbcUserPasswordPolicyInfo
**policy
)
1236 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
1238 struct winbindd_request request
;
1239 struct winbindd_response response
;
1242 ZERO_STRUCT(request
);
1243 ZERO_STRUCT(response
);
1256 wbc_status
= WBC_ERR_INVALID_PARAM
;
1257 BAIL_ON_WBC_ERROR(wbc_status
);
1260 if (!params
->username
) {
1261 wbc_status
= WBC_ERR_INVALID_PARAM
;
1262 BAIL_ON_WBC_ERROR(wbc_status
);
1265 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
1266 wbc_status
= WBC_ERR_INVALID_PARAM
;
1267 BAIL_ON_WBC_ERROR(wbc_status
);
1269 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
1270 wbc_status
= WBC_ERR_INVALID_PARAM
;
1271 BAIL_ON_WBC_ERROR(wbc_status
);
1274 /* Initialize request */
1276 cmd
= WINBINDD_PAM_AUTH
;
1277 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
1278 WBFLAG_PAM_USER_SESSION_KEY
|
1281 if (!params
->password
) {
1282 wbc_status
= WBC_ERR_INVALID_PARAM
;
1283 BAIL_ON_WBC_ERROR(wbc_status
);
1286 strncpy(request
.data
.auth
.user
,
1288 sizeof(request
.data
.auth
.user
)-1);
1290 strncpy(request
.data
.auth
.pass
,
1292 sizeof(request
.data
.auth
.pass
)-1);
1294 for (i
=0; i
<params
->num_blobs
; i
++) {
1296 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
1297 if (params
->blobs
[i
].blob
.data
) {
1298 strncpy(request
.data
.auth
.krb5_cc_type
,
1299 (const char *)params
->blobs
[i
].blob
.data
,
1300 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
1305 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
1306 if (params
->blobs
[i
].blob
.data
) {
1307 memcpy(&request
.data
.auth
.uid
,
1308 params
->blobs
[i
].blob
.data
,
1309 MIN(sizeof(request
.data
.auth
.uid
),
1310 params
->blobs
[i
].blob
.length
));
1315 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
1316 if (params
->blobs
[i
].blob
.data
) {
1319 params
->blobs
[i
].blob
.data
,
1321 params
->blobs
[i
].blob
.length
));
1322 request
.flags
|= flags
;
1327 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
1328 if (params
->blobs
[i
].blob
.data
&&
1329 params
->blobs
[i
].blob
.data
[0] > 0) {
1330 strncpy(request
.data
.auth
.require_membership_of_sid
,
1331 (const char *)params
->blobs
[i
].blob
.data
,
1332 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
1338 wbc_status
= wbcRequestResponse(cmd
,
1342 if (response
.data
.auth
.nt_status
!= 0) {
1344 wbc_status
= wbc_create_error_info(&response
,
1346 BAIL_ON_WBC_ERROR(wbc_status
);
1349 wbc_status
= WBC_ERR_AUTH_ERROR
;
1350 BAIL_ON_WBC_ERROR(wbc_status
);
1352 BAIL_ON_WBC_ERROR(wbc_status
);
1355 wbc_status
= wbc_create_logon_info(&response
,
1357 BAIL_ON_WBC_ERROR(wbc_status
);
1361 wbc_status
= wbc_create_password_policy_info(&response
,
1363 BAIL_ON_WBC_ERROR(wbc_status
);
1367 winbindd_free_response(&response
);
1372 /* Authenticate a user with cached credentials */
1373 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1374 struct wbcCredentialCacheInfo
**info
,
1375 struct wbcAuthErrorInfo
**error
)
1377 wbcErr status
= WBC_ERR_UNKNOWN_FAILURE
;
1378 struct wbcCredentialCacheInfo
*result
= NULL
;
1379 struct winbindd_request request
;
1380 struct winbindd_response response
;
1381 struct wbcNamedBlob
*initial_blob
= NULL
;
1382 struct wbcNamedBlob
*challenge_blob
= NULL
;
1385 ZERO_STRUCT(request
);
1386 ZERO_STRUCT(response
);
1391 if (error
!= NULL
) {
1394 if ((params
== NULL
)
1395 || (params
->account_name
== NULL
)
1396 || (params
->level
!= WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP
)) {
1397 status
= WBC_ERR_INVALID_PARAM
;
1401 if (params
->domain_name
!= NULL
) {
1402 status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
1403 if (!WBC_ERROR_IS_OK(status
)) {
1406 snprintf(request
.data
.ccache_ntlm_auth
.user
,
1407 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1,
1408 "%s%c%s", params
->domain_name
,
1409 response
.data
.info
.winbind_separator
,
1410 params
->account_name
);
1412 strncpy(request
.data
.ccache_ntlm_auth
.user
,
1413 params
->account_name
,
1414 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1);
1416 request
.data
.ccache_ntlm_auth
.uid
= getuid();
1418 for (i
=0; i
<params
->num_blobs
; i
++) {
1419 if (strcasecmp(params
->blobs
[i
].name
, "initial_blob") == 0) {
1420 initial_blob
= ¶ms
->blobs
[i
];
1423 if (strcasecmp(params
->blobs
[i
].name
, "challenge_blob") == 0) {
1424 challenge_blob
= ¶ms
->blobs
[i
];
1429 request
.data
.ccache_ntlm_auth
.initial_blob_len
= 0;
1430 request
.data
.ccache_ntlm_auth
.challenge_blob_len
= 0;
1431 request
.extra_len
= 0;
1433 if (initial_blob
!= NULL
) {
1434 request
.data
.ccache_ntlm_auth
.initial_blob_len
=
1435 initial_blob
->blob
.length
;
1436 request
.extra_len
+= initial_blob
->blob
.length
;
1438 if (challenge_blob
!= NULL
) {
1439 request
.data
.ccache_ntlm_auth
.challenge_blob_len
=
1440 challenge_blob
->blob
.length
;
1441 request
.extra_len
+= challenge_blob
->blob
.length
;
1444 if (request
.extra_len
!= 0) {
1445 request
.extra_data
.data
= talloc_array(
1446 NULL
, char, request
.extra_len
);
1447 if (request
.extra_data
.data
== NULL
) {
1448 status
= WBC_ERR_NO_MEMORY
;
1452 if (initial_blob
!= NULL
) {
1453 memcpy(request
.extra_data
.data
,
1454 initial_blob
->blob
.data
, initial_blob
->blob
.length
);
1456 if (challenge_blob
!= NULL
) {
1457 memcpy(request
.extra_data
.data
1458 + request
.data
.ccache_ntlm_auth
.initial_blob_len
,
1459 challenge_blob
->blob
.data
,
1460 challenge_blob
->blob
.length
);
1463 status
= wbcRequestResponse(WINBINDD_CCACHE_NTLMAUTH
, &request
,
1465 if (!WBC_ERROR_IS_OK(status
)) {
1469 result
= talloc(NULL
, struct wbcCredentialCacheInfo
);
1470 if (result
== NULL
) {
1471 status
= WBC_ERR_NO_MEMORY
;
1474 result
->num_blobs
= 0;
1475 result
->blobs
= talloc(result
, struct wbcNamedBlob
);
1476 if (result
->blobs
== NULL
) {
1477 status
= WBC_ERR_NO_MEMORY
;
1480 status
= wbcAddNamedBlob(&result
->num_blobs
, &result
->blobs
,
1482 (uint8_t *)response
.extra_data
.data
,
1483 response
.data
.ccache_ntlm_auth
.auth_blob_len
);
1484 if (!WBC_ERROR_IS_OK(status
)) {
1487 status
= wbcAddNamedBlob(
1488 &result
->num_blobs
, &result
->blobs
, "session_key", 0,
1489 response
.data
.ccache_ntlm_auth
.session_key
,
1490 sizeof(response
.data
.ccache_ntlm_auth
.session_key
));
1491 if (!WBC_ERROR_IS_OK(status
)) {
1495 winbindd_free_response(&response
);
1497 return WBC_ERR_SUCCESS
;
1500 TALLOC_FREE(request
.extra_data
.data
);
1501 winbindd_free_response(&response
);
1502 talloc_free(result
);
1506 /* Authenticate a user with cached credentials */
1507 wbcErr
wbcCredentialSave(const char *user
, const char *password
)
1509 struct winbindd_request request
;
1510 struct winbindd_response response
;
1512 ZERO_STRUCT(request
);
1513 ZERO_STRUCT(response
);
1515 strncpy(request
.data
.ccache_save
.user
, user
,
1516 sizeof(request
.data
.ccache_save
.user
)-1);
1517 strncpy(request
.data
.ccache_save
.pass
, password
,
1518 sizeof(request
.data
.ccache_save
.pass
)-1);
1519 request
.data
.ccache_save
.uid
= getuid();
1521 return wbcRequestResponse(WINBINDD_CCACHE_SAVE
, &request
, &response
);