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 */
32 wbcErr
wbcCtxAuthenticateUser(struct wbcContext
*ctx
,
33 const char *username
, const char *password
)
35 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
36 struct wbcAuthUserParams params
;
40 params
.account_name
= username
;
41 params
.level
= WBC_AUTH_USER_LEVEL_PLAIN
;
42 params
.password
.plaintext
= password
;
44 wbc_status
= wbcCtxAuthenticateUserEx(ctx
, ¶ms
, NULL
, NULL
);
45 BAIL_ON_WBC_ERROR(wbc_status
);
52 wbcErr
wbcAuthenticateUser(const char *username
, const char *password
)
54 return wbcCtxAuthenticateUser(NULL
, username
, password
);
57 static bool sid_attr_compose(struct wbcSidWithAttr
*s
,
58 const struct wbcDomainSid
*d
,
59 uint32_t rid
, uint32_t attr
)
61 if (d
->num_auths
>= WBC_MAXSUBAUTHS
) {
65 s
->sid
.sub_auths
[s
->sid
.num_auths
++] = rid
;
70 static void wbcAuthUserInfoDestructor(void *ptr
)
72 struct wbcAuthUserInfo
*i
= (struct wbcAuthUserInfo
*)ptr
;
73 free(i
->account_name
);
74 free(i
->user_principal
);
77 free(i
->dns_domain_name
);
78 free(i
->logon_server
);
79 free(i
->logon_script
);
80 free(i
->profile_path
);
81 free(i
->home_directory
);
86 static wbcErr
wbc_create_auth_info(const struct winbindd_response
*resp
,
87 struct wbcAuthUserInfo
**_i
)
89 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
90 struct wbcAuthUserInfo
*i
;
91 struct wbcDomainSid domain_sid
;
96 i
= (struct wbcAuthUserInfo
*)wbcAllocateMemory(
97 1, sizeof(struct wbcAuthUserInfo
),
98 wbcAuthUserInfoDestructor
);
99 BAIL_ON_PTR_ERROR(i
, wbc_status
);
101 i
->user_flags
= resp
->data
.auth
.info3
.user_flgs
;
103 i
->account_name
= strdup(resp
->data
.auth
.info3
.user_name
);
104 BAIL_ON_PTR_ERROR(i
->account_name
, wbc_status
);
105 if (resp
->data
.auth
.validation_level
== 6) {
106 i
->user_principal
= strdup(resp
->data
.auth
.info6
.principal_name
);
107 BAIL_ON_PTR_ERROR(i
->user_principal
, wbc_status
);
109 i
->user_principal
= NULL
;
111 i
->full_name
= strdup(resp
->data
.auth
.info3
.full_name
);
112 BAIL_ON_PTR_ERROR(i
->full_name
, wbc_status
);
113 i
->domain_name
= strdup(resp
->data
.auth
.info3
.logon_dom
);
114 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
115 if (resp
->data
.auth
.validation_level
== 6) {
116 i
->dns_domain_name
= strdup(resp
->data
.auth
.info6
.dns_domainname
);
117 BAIL_ON_PTR_ERROR(i
->dns_domain_name
, wbc_status
);
119 i
->dns_domain_name
= NULL
;
122 i
->acct_flags
= resp
->data
.auth
.info3
.acct_flags
;
123 memcpy(i
->user_session_key
,
124 resp
->data
.auth
.user_session_key
,
125 sizeof(i
->user_session_key
));
126 memcpy(i
->lm_session_key
,
127 resp
->data
.auth
.first_8_lm_hash
,
128 sizeof(i
->lm_session_key
));
130 i
->logon_count
= resp
->data
.auth
.info3
.logon_count
;
131 i
->bad_password_count
= resp
->data
.auth
.info3
.bad_pw_count
;
133 i
->logon_time
= resp
->data
.auth
.info3
.logon_time
;
134 i
->logoff_time
= resp
->data
.auth
.info3
.logoff_time
;
135 i
->kickoff_time
= resp
->data
.auth
.info3
.kickoff_time
;
136 i
->pass_last_set_time
= resp
->data
.auth
.info3
.pass_last_set_time
;
137 i
->pass_can_change_time
= resp
->data
.auth
.info3
.pass_can_change_time
;
138 i
->pass_must_change_time
= resp
->data
.auth
.info3
.pass_must_change_time
;
140 i
->logon_server
= strdup(resp
->data
.auth
.info3
.logon_srv
);
141 BAIL_ON_PTR_ERROR(i
->logon_server
, wbc_status
);
142 i
->logon_script
= strdup(resp
->data
.auth
.info3
.logon_script
);
143 BAIL_ON_PTR_ERROR(i
->logon_script
, wbc_status
);
144 i
->profile_path
= strdup(resp
->data
.auth
.info3
.profile_path
);
145 BAIL_ON_PTR_ERROR(i
->profile_path
, wbc_status
);
146 i
->home_directory
= strdup(resp
->data
.auth
.info3
.home_dir
);
147 BAIL_ON_PTR_ERROR(i
->home_directory
, wbc_status
);
148 i
->home_drive
= strdup(resp
->data
.auth
.info3
.dir_drive
);
149 BAIL_ON_PTR_ERROR(i
->home_drive
, wbc_status
);
152 i
->num_sids
+= resp
->data
.auth
.info3
.num_groups
;
153 i
->num_sids
+= resp
->data
.auth
.info3
.num_other_sids
;
155 i
->sids
= (struct wbcSidWithAttr
*)calloc(
156 sizeof(struct wbcSidWithAttr
), i
->num_sids
);
157 BAIL_ON_PTR_ERROR(i
->sids
, wbc_status
);
159 wbc_status
= wbcStringToSid(resp
->data
.auth
.info3
.dom_sid
,
161 BAIL_ON_WBC_ERROR(wbc_status
);
164 if (!sid_attr_compose(&i
->sids
[sn
], &domain_sid
,
165 resp
->data
.auth
.info3
.user_rid
, 0)) {
166 wbc_status
= WBC_ERR_INVALID_SID
;
170 if (!sid_attr_compose(&i
->sids
[sn
], &domain_sid
,
171 resp
->data
.auth
.info3
.group_rid
, 0)) {
172 wbc_status
= WBC_ERR_INVALID_SID
;
177 p
= (char *)resp
->extra_data
.data
;
179 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
180 BAIL_ON_WBC_ERROR(wbc_status
);
183 for (j
=0; j
< resp
->data
.auth
.info3
.num_groups
; j
++) {
188 char *e
= strchr(p
, '\n');
190 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
191 BAIL_ON_WBC_ERROR(wbc_status
);
196 ret
= sscanf(s
, "0x%08X:0x%08X", &rid
, &attrs
);
198 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
199 BAIL_ON_WBC_ERROR(wbc_status
);
202 if (!sid_attr_compose(&i
->sids
[sn
], &domain_sid
,
204 wbc_status
= WBC_ERR_INVALID_SID
;
210 for (j
=0; j
< resp
->data
.auth
.info3
.num_other_sids
; j
++) {
215 char *e
= strchr(p
, '\n');
217 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
218 BAIL_ON_WBC_ERROR(wbc_status
);
225 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
226 BAIL_ON_WBC_ERROR(wbc_status
);
231 ret
= sscanf(a
, "0x%08X",
234 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
235 BAIL_ON_WBC_ERROR(wbc_status
);
238 wbc_status
= wbcStringToSid(s
, &i
->sids
[sn
].sid
);
239 BAIL_ON_WBC_ERROR(wbc_status
);
241 i
->sids
[sn
].attributes
= attrs
;
254 static void wbcAuthErrorInfoDestructor(void *ptr
)
256 struct wbcAuthErrorInfo
*e
= (struct wbcAuthErrorInfo
*)ptr
;
258 free(e
->display_string
);
261 static wbcErr
wbc_create_error_info(const struct winbindd_response
*resp
,
262 struct wbcAuthErrorInfo
**_e
)
264 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
265 struct wbcAuthErrorInfo
*e
;
267 e
= (struct wbcAuthErrorInfo
*)wbcAllocateMemory(
268 1, sizeof(struct wbcAuthErrorInfo
),
269 wbcAuthErrorInfoDestructor
);
270 BAIL_ON_PTR_ERROR(e
, wbc_status
);
272 e
->nt_status
= resp
->data
.auth
.nt_status
;
273 e
->pam_error
= resp
->data
.auth
.pam_error
;
274 e
->authoritative
= resp
->data
.auth
.authoritative
;
275 e
->nt_string
= strdup(resp
->data
.auth
.nt_status_string
);
276 BAIL_ON_PTR_ERROR(e
->nt_string
, wbc_status
);
278 e
->display_string
= strdup(resp
->data
.auth
.error_string
);
279 BAIL_ON_PTR_ERROR(e
->display_string
, wbc_status
);
289 static wbcErr
wbc_create_password_policy_info(const struct winbindd_response
*resp
,
290 struct wbcUserPasswordPolicyInfo
**_i
)
292 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
293 struct wbcUserPasswordPolicyInfo
*i
;
295 i
= (struct wbcUserPasswordPolicyInfo
*)wbcAllocateMemory(
296 1, sizeof(struct wbcUserPasswordPolicyInfo
), NULL
);
297 BAIL_ON_PTR_ERROR(i
, wbc_status
);
299 i
->min_passwordage
= resp
->data
.auth
.policy
.min_passwordage
;
300 i
->min_length_password
= resp
->data
.auth
.policy
.min_length_password
;
301 i
->password_history
= resp
->data
.auth
.policy
.password_history
;
302 i
->password_properties
= resp
->data
.auth
.policy
.password_properties
;
303 i
->expire
= resp
->data
.auth
.policy
.expire
;
313 static void wbcLogonUserInfoDestructor(void *ptr
)
315 struct wbcLogonUserInfo
*i
= (struct wbcLogonUserInfo
*)ptr
;
316 wbcFreeMemory(i
->info
);
317 wbcFreeMemory(i
->blobs
);
320 static wbcErr
wbc_create_logon_info(struct winbindd_response
*resp
,
321 struct wbcLogonUserInfo
**_i
)
323 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
324 struct wbcLogonUserInfo
*i
;
326 i
= (struct wbcLogonUserInfo
*)wbcAllocateMemory(
327 1, sizeof(struct wbcLogonUserInfo
),
328 wbcLogonUserInfoDestructor
);
329 BAIL_ON_PTR_ERROR(i
, wbc_status
);
331 wbc_status
= wbc_create_auth_info(resp
, &i
->info
);
332 BAIL_ON_WBC_ERROR(wbc_status
);
334 if (resp
->data
.auth
.krb5ccname
[0] != '\0') {
335 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
339 (uint8_t *)resp
->data
.auth
.krb5ccname
,
340 strlen(resp
->data
.auth
.krb5ccname
)+1);
341 BAIL_ON_WBC_ERROR(wbc_status
);
344 if (resp
->data
.auth
.unix_username
[0] != '\0') {
345 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
349 (uint8_t *)resp
->data
.auth
.unix_username
,
350 strlen(resp
->data
.auth
.unix_username
)+1);
351 BAIL_ON_WBC_ERROR(wbc_status
);
362 /* Authenticate with more detailed information */
364 wbcErr
wbcCtxAuthenticateUserEx(struct wbcContext
*ctx
,
365 const struct wbcAuthUserParams
*params
,
366 struct wbcAuthUserInfo
**info
,
367 struct wbcAuthErrorInfo
**error
)
369 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
371 struct winbindd_request request
;
372 struct winbindd_response response
;
374 ZERO_STRUCT(request
);
375 ZERO_STRUCT(response
);
382 wbc_status
= WBC_ERR_INVALID_PARAM
;
383 BAIL_ON_WBC_ERROR(wbc_status
);
386 if (params
->level
!= WBC_AUTH_USER_LEVEL_PAC
&& !params
->account_name
) {
387 wbc_status
= WBC_ERR_INVALID_PARAM
;
388 BAIL_ON_WBC_ERROR(wbc_status
);
391 /* Initialize request */
393 switch (params
->level
) {
394 case WBC_AUTH_USER_LEVEL_PLAIN
:
395 cmd
= WINBINDD_PAM_AUTH
;
396 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
397 WBFLAG_PAM_USER_SESSION_KEY
|
400 if (!params
->password
.plaintext
) {
401 wbc_status
= WBC_ERR_INVALID_PARAM
;
402 BAIL_ON_WBC_ERROR(wbc_status
);
405 if (params
->domain_name
&& params
->domain_name
[0]) {
406 /* We need to get the winbind separator :-( */
407 struct winbindd_response sep_response
;
409 ZERO_STRUCT(sep_response
);
411 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_INFO
,
412 NULL
, &sep_response
);
413 BAIL_ON_WBC_ERROR(wbc_status
);
415 snprintf(request
.data
.auth
.user
,
416 sizeof(request
.data
.auth
.user
)-1,
419 sep_response
.data
.info
.winbind_separator
,
420 params
->account_name
);
421 winbindd_free_response(&sep_response
);
423 strncpy(request
.data
.auth
.user
,
424 params
->account_name
,
425 sizeof(request
.data
.auth
.user
)-1);
428 strncpy(request
.data
.auth
.pass
,
429 params
->password
.plaintext
,
430 sizeof(request
.data
.auth
.pass
)-1);
433 case WBC_AUTH_USER_LEVEL_HASH
:
434 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
435 BAIL_ON_WBC_ERROR(wbc_status
);
438 case WBC_AUTH_USER_LEVEL_RESPONSE
:
439 cmd
= WINBINDD_PAM_AUTH_CRAP
;
440 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
441 WBFLAG_PAM_USER_SESSION_KEY
|
444 if (params
->password
.response
.lm_length
&&
445 !params
->password
.response
.lm_data
) {
446 wbc_status
= WBC_ERR_INVALID_PARAM
;
447 BAIL_ON_WBC_ERROR(wbc_status
);
449 if (params
->password
.response
.lm_length
== 0 &&
450 params
->password
.response
.lm_data
) {
451 wbc_status
= WBC_ERR_INVALID_PARAM
;
452 BAIL_ON_WBC_ERROR(wbc_status
);
455 if (params
->password
.response
.nt_length
&&
456 !params
->password
.response
.nt_data
) {
457 wbc_status
= WBC_ERR_INVALID_PARAM
;
458 BAIL_ON_WBC_ERROR(wbc_status
);
460 if (params
->password
.response
.nt_length
== 0&&
461 params
->password
.response
.nt_data
) {
462 wbc_status
= WBC_ERR_INVALID_PARAM
;
463 BAIL_ON_WBC_ERROR(wbc_status
);
466 strncpy(request
.data
.auth_crap
.user
,
467 params
->account_name
,
468 sizeof(request
.data
.auth_crap
.user
)-1);
469 if (params
->domain_name
) {
470 strncpy(request
.data
.auth_crap
.domain
,
472 sizeof(request
.data
.auth_crap
.domain
)-1);
474 if (params
->workstation_name
) {
475 strncpy(request
.data
.auth_crap
.workstation
,
476 params
->workstation_name
,
477 sizeof(request
.data
.auth_crap
.workstation
)-1);
480 request
.data
.auth_crap
.logon_parameters
=
481 params
->parameter_control
;
483 memcpy(request
.data
.auth_crap
.chal
,
484 params
->password
.response
.challenge
,
485 sizeof(request
.data
.auth_crap
.chal
));
487 request
.data
.auth_crap
.lm_resp_len
=
488 MIN(params
->password
.response
.lm_length
,
489 sizeof(request
.data
.auth_crap
.lm_resp
));
490 if (params
->password
.response
.lm_data
) {
491 memcpy(request
.data
.auth_crap
.lm_resp
,
492 params
->password
.response
.lm_data
,
493 request
.data
.auth_crap
.lm_resp_len
);
495 request
.data
.auth_crap
.nt_resp_len
= params
->password
.response
.nt_length
;
496 if (params
->password
.response
.nt_length
> sizeof(request
.data
.auth_crap
.nt_resp
)) {
497 request
.flags
|= WBFLAG_BIG_NTLMV2_BLOB
;
498 request
.extra_len
= params
->password
.response
.nt_length
;
499 request
.extra_data
.data
= (char *)malloc(
501 if (request
.extra_data
.data
== NULL
) {
502 wbc_status
= WBC_ERR_NO_MEMORY
;
503 BAIL_ON_WBC_ERROR(wbc_status
);
505 memcpy(request
.extra_data
.data
,
506 params
->password
.response
.nt_data
,
507 request
.data
.auth_crap
.nt_resp_len
);
508 } else if (params
->password
.response
.nt_data
) {
509 memcpy(request
.data
.auth_crap
.nt_resp
,
510 params
->password
.response
.nt_data
,
511 request
.data
.auth_crap
.nt_resp_len
);
515 case WBC_AUTH_USER_LEVEL_PAC
:
516 cmd
= WINBINDD_PAM_AUTH_CRAP
;
517 request
.flags
= WBFLAG_PAM_AUTH_PAC
| WBFLAG_PAM_INFO3_TEXT
;
518 request
.extra_data
.data
= malloc(params
->password
.pac
.length
);
519 if (request
.extra_data
.data
== NULL
) {
520 wbc_status
= WBC_ERR_NO_MEMORY
;
521 BAIL_ON_WBC_ERROR(wbc_status
);
523 memcpy(request
.extra_data
.data
, params
->password
.pac
.data
,
524 params
->password
.pac
.length
);
525 request
.extra_len
= params
->password
.pac
.length
;
533 wbc_status
= WBC_ERR_INVALID_PARAM
;
534 BAIL_ON_WBC_ERROR(wbc_status
);
538 request
.flags
|= params
->flags
;
541 if (cmd
== WINBINDD_PAM_AUTH_CRAP
) {
542 wbc_status
= wbcRequestResponsePriv(ctx
, cmd
,
543 &request
, &response
);
545 wbc_status
= wbcRequestResponse(ctx
, cmd
,
546 &request
, &response
);
548 if (response
.data
.auth
.nt_status
!= 0) {
550 wbc_status
= wbc_create_error_info(&response
,
552 BAIL_ON_WBC_ERROR(wbc_status
);
555 wbc_status
= WBC_ERR_AUTH_ERROR
;
556 BAIL_ON_WBC_ERROR(wbc_status
);
558 BAIL_ON_WBC_ERROR(wbc_status
);
561 wbc_status
= wbc_create_auth_info(&response
, info
);
562 BAIL_ON_WBC_ERROR(wbc_status
);
566 winbindd_free_response(&response
);
568 free(request
.extra_data
.data
);
574 wbcErr
wbcAuthenticateUserEx(const struct wbcAuthUserParams
*params
,
575 struct wbcAuthUserInfo
**info
,
576 struct wbcAuthErrorInfo
**error
)
578 return wbcCtxAuthenticateUserEx(NULL
, params
, info
, error
);
581 /* Trigger a verification of the trust credentials of a specific domain */
583 wbcErr
wbcCtxCheckTrustCredentials(struct wbcContext
*ctx
, const char *domain
,
584 struct wbcAuthErrorInfo
**error
)
586 struct winbindd_request request
;
587 struct winbindd_response response
;
588 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
590 ZERO_STRUCT(request
);
591 ZERO_STRUCT(response
);
594 strncpy(request
.domain_name
, domain
,
595 sizeof(request
.domain_name
)-1);
600 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_CHECK_MACHACC
,
601 &request
, &response
);
602 if (response
.data
.auth
.nt_status
!= 0) {
604 wbc_status
= wbc_create_error_info(&response
,
606 BAIL_ON_WBC_ERROR(wbc_status
);
609 wbc_status
= WBC_ERR_AUTH_ERROR
;
610 BAIL_ON_WBC_ERROR(wbc_status
);
612 BAIL_ON_WBC_ERROR(wbc_status
);
619 wbcErr
wbcCheckTrustCredentials(const char *domain
,
620 struct wbcAuthErrorInfo
**error
)
622 return wbcCtxCheckTrustCredentials(NULL
, domain
, error
);
625 /* Trigger a change of the trust credentials for a specific domain */
627 wbcErr
wbcCtxChangeTrustCredentialsAt(struct wbcContext
*ctx
,
630 struct wbcAuthErrorInfo
**error
)
632 struct winbindd_request request
;
633 struct winbindd_response response
;
634 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
636 ZERO_STRUCT(request
);
637 ZERO_STRUCT(response
);
640 strncpy(request
.domain_name
, domain
,
641 sizeof(request
.domain_name
)-1);
644 if (dcname
!= NULL
) {
645 strncpy(request
.data
.init_conn
.dcname
, dcname
,
646 sizeof(request
.data
.init_conn
.dcname
)-1);
651 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_CHANGE_MACHACC
,
652 &request
, &response
);
653 if (response
.data
.auth
.nt_status
!= 0) {
655 wbc_status
= wbc_create_error_info(&response
,
657 BAIL_ON_WBC_ERROR(wbc_status
);
660 wbc_status
= WBC_ERR_AUTH_ERROR
;
661 BAIL_ON_WBC_ERROR(wbc_status
);
663 BAIL_ON_WBC_ERROR(wbc_status
);
670 wbcErr
wbcChangeTrustCredentialsAt(const char *domain
,
672 struct wbcAuthErrorInfo
**error
)
674 return wbcCtxChangeTrustCredentialsAt(NULL
, domain
, dcname
, error
);
678 wbcErr
wbcCtxChangeTrustCredentials(struct wbcContext
*ctx
,
680 struct wbcAuthErrorInfo
**error
)
682 return wbcCtxChangeTrustCredentialsAt(ctx
, domain
, NULL
, error
);
686 wbcErr
wbcChangeTrustCredentials(const char *domain
,
687 struct wbcAuthErrorInfo
**error
)
689 return wbcCtxChangeTrustCredentials(NULL
, domain
, error
);
693 * Trigger a no-op NETLOGON call. Lightweight version of
694 * wbcCheckTrustCredentials
697 wbcErr
wbcCtxPingDc(struct wbcContext
*ctx
, const char *domain
,
698 struct wbcAuthErrorInfo
**error
)
700 return wbcCtxPingDc2(ctx
, domain
, error
, NULL
);
704 wbcErr
wbcPingDc(const char *domain
, struct wbcAuthErrorInfo
**error
)
706 return wbcPingDc2(domain
, error
, NULL
);
710 * Trigger a no-op NETLOGON call. Lightweight version of
711 * wbcCheckTrustCredentials, optionally return attempted DC
714 wbcErr
wbcCtxPingDc2(struct wbcContext
*ctx
, const char *domain
,
715 struct wbcAuthErrorInfo
**error
, char **dcname
)
717 struct winbindd_request request
;
718 struct winbindd_response response
;
719 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
721 ZERO_STRUCT(request
);
722 ZERO_STRUCT(response
);
725 strncpy(request
.domain_name
, domain
,
726 sizeof(request
.domain_name
)-1);
731 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_PING_DC
,
735 if (dcname
&& response
.extra_data
.data
) {
738 len
= response
.length
- sizeof(struct winbindd_response
);
739 *dcname
= wbcAllocateMemory(1, len
, NULL
);
740 BAIL_ON_PTR_ERROR(*dcname
, wbc_status
);
742 strlcpy(*dcname
, response
.extra_data
.data
, len
);
745 if (response
.data
.auth
.nt_status
!= 0) {
747 wbc_status
= wbc_create_error_info(&response
,
749 BAIL_ON_WBC_ERROR(wbc_status
);
752 wbc_status
= WBC_ERR_AUTH_ERROR
;
753 BAIL_ON_WBC_ERROR(wbc_status
);
755 BAIL_ON_WBC_ERROR(wbc_status
);
758 winbindd_free_response(&response
);
763 wbcErr
wbcPingDc2(const char *domain
, struct wbcAuthErrorInfo
**error
,
766 return wbcCtxPingDc2(NULL
, domain
, error
, dcname
);
769 /* Trigger an extended logoff notification to Winbind for a specific user */
771 wbcErr
wbcCtxLogoffUserEx(struct wbcContext
*ctx
,
772 const struct wbcLogoffUserParams
*params
,
773 struct wbcAuthErrorInfo
**error
)
775 struct winbindd_request request
;
776 struct winbindd_response response
;
777 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
782 if (!params
|| !params
->username
) {
783 wbc_status
= WBC_ERR_INVALID_PARAM
;
784 BAIL_ON_WBC_ERROR(wbc_status
);
787 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
788 wbc_status
= WBC_ERR_INVALID_PARAM
;
789 BAIL_ON_WBC_ERROR(wbc_status
);
791 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
792 wbc_status
= WBC_ERR_INVALID_PARAM
;
793 BAIL_ON_WBC_ERROR(wbc_status
);
796 ZERO_STRUCT(request
);
797 ZERO_STRUCT(response
);
799 strncpy(request
.data
.logoff
.user
, params
->username
,
800 sizeof(request
.data
.logoff
.user
)-1);
802 for (i
=0; i
<params
->num_blobs
; i
++) {
804 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
805 if (params
->blobs
[i
].blob
.data
) {
806 strncpy(request
.data
.logoff
.krb5ccname
,
807 (const char *)params
->blobs
[i
].blob
.data
,
808 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
813 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
814 if (params
->blobs
[i
].blob
.data
) {
815 memcpy(&request
.data
.logoff
.uid
,
816 params
->blobs
[i
].blob
.data
,
817 MIN(params
->blobs
[i
].blob
.length
,
818 sizeof(request
.data
.logoff
.uid
)));
823 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
824 if (params
->blobs
[i
].blob
.data
) {
825 memcpy(&request
.flags
,
826 params
->blobs
[i
].blob
.data
,
827 MIN(params
->blobs
[i
].blob
.length
,
828 sizeof(request
.flags
)));
836 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_PAM_LOGOFF
,
840 /* Take the response above and return it to the caller */
841 if (response
.data
.auth
.nt_status
!= 0) {
843 wbc_status
= wbc_create_error_info(&response
,
845 BAIL_ON_WBC_ERROR(wbc_status
);
848 wbc_status
= WBC_ERR_AUTH_ERROR
;
849 BAIL_ON_WBC_ERROR(wbc_status
);
851 BAIL_ON_WBC_ERROR(wbc_status
);
858 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
859 struct wbcAuthErrorInfo
**error
)
861 return wbcCtxLogoffUserEx(NULL
, params
, error
);
864 /* Trigger a logoff notification to Winbind for a specific user */
866 wbcErr
wbcCtxLogoffUser(struct wbcContext
*ctx
,
867 const char *username
, uid_t uid
,
868 const char *ccfilename
)
870 struct winbindd_request request
;
871 struct winbindd_response response
;
872 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
877 wbc_status
= WBC_ERR_INVALID_PARAM
;
878 BAIL_ON_WBC_ERROR(wbc_status
);
881 ZERO_STRUCT(request
);
882 ZERO_STRUCT(response
);
884 strncpy(request
.data
.logoff
.user
, username
,
885 sizeof(request
.data
.logoff
.user
)-1);
886 request
.data
.logoff
.uid
= uid
;
889 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
890 sizeof(request
.data
.logoff
.krb5ccname
)-1);
895 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_PAM_LOGOFF
,
899 /* Take the response above and return it to the caller */
906 wbcErr
wbcLogoffUser(const char *username
,
908 const char *ccfilename
)
910 return wbcCtxLogoffUser(NULL
, username
, uid
, ccfilename
);
913 /* Change a password for a user with more detailed information upon failure */
915 wbcErr
wbcCtxChangeUserPasswordEx(struct wbcContext
*ctx
,
916 const struct wbcChangePasswordParams
*params
,
917 struct wbcAuthErrorInfo
**error
,
918 enum wbcPasswordChangeRejectReason
*reject_reason
,
919 struct wbcUserPasswordPolicyInfo
**policy
)
921 struct winbindd_request request
;
922 struct winbindd_response response
;
923 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
928 if (!params
->account_name
) {
929 wbc_status
= WBC_ERR_INVALID_PARAM
;
945 ZERO_STRUCT(request
);
946 ZERO_STRUCT(response
);
948 switch (params
->level
) {
949 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
950 cmd
= WINBINDD_PAM_CHAUTHTOK
;
952 if (!params
->account_name
) {
953 wbc_status
= WBC_ERR_INVALID_PARAM
;
957 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
958 sizeof(request
.data
.chauthtok
.user
) - 1);
960 if (params
->old_password
.plaintext
) {
961 strncpy(request
.data
.chauthtok
.oldpass
,
962 params
->old_password
.plaintext
,
963 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
966 if (params
->new_password
.plaintext
) {
967 strncpy(request
.data
.chauthtok
.newpass
,
968 params
->new_password
.plaintext
,
969 sizeof(request
.data
.chauthtok
.newpass
) - 1);
973 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
974 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
976 if (!params
->account_name
|| !params
->domain_name
) {
977 wbc_status
= WBC_ERR_INVALID_PARAM
;
981 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
982 !params
->old_password
.response
.old_lm_hash_enc_data
) {
983 wbc_status
= WBC_ERR_INVALID_PARAM
;
987 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
988 params
->old_password
.response
.old_lm_hash_enc_data
) {
989 wbc_status
= WBC_ERR_INVALID_PARAM
;
993 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
994 !params
->old_password
.response
.old_nt_hash_enc_data
) {
995 wbc_status
= WBC_ERR_INVALID_PARAM
;
999 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
1000 params
->old_password
.response
.old_nt_hash_enc_data
) {
1001 wbc_status
= WBC_ERR_INVALID_PARAM
;
1005 if (params
->new_password
.response
.lm_length
&&
1006 !params
->new_password
.response
.lm_data
) {
1007 wbc_status
= WBC_ERR_INVALID_PARAM
;
1011 if (params
->new_password
.response
.lm_length
== 0 &&
1012 params
->new_password
.response
.lm_data
) {
1013 wbc_status
= WBC_ERR_INVALID_PARAM
;
1017 if (params
->new_password
.response
.nt_length
&&
1018 !params
->new_password
.response
.nt_data
) {
1019 wbc_status
= WBC_ERR_INVALID_PARAM
;
1023 if (params
->new_password
.response
.nt_length
== 0 &&
1024 params
->new_password
.response
.nt_data
) {
1025 wbc_status
= WBC_ERR_INVALID_PARAM
;
1029 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
1030 params
->account_name
,
1031 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
1033 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
1034 params
->domain_name
,
1035 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
1037 if (params
->new_password
.response
.nt_data
) {
1038 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
1039 params
->new_password
.response
.nt_length
;
1040 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
1041 params
->new_password
.response
.nt_data
,
1042 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
1045 if (params
->new_password
.response
.lm_data
) {
1046 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
1047 params
->new_password
.response
.lm_length
;
1048 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
1049 params
->new_password
.response
.lm_data
,
1050 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
1053 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
1054 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
1055 params
->old_password
.response
.old_nt_hash_enc_length
;
1056 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
1057 params
->old_password
.response
.old_nt_hash_enc_data
,
1058 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
1061 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
1062 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
1063 params
->old_password
.response
.old_lm_hash_enc_length
;
1064 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
1065 params
->old_password
.response
.old_lm_hash_enc_data
,
1066 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
1071 wbc_status
= WBC_ERR_INVALID_PARAM
;
1078 wbc_status
= wbcRequestResponse(ctx
, cmd
,
1081 if (WBC_ERROR_IS_OK(wbc_status
)) {
1085 /* Take the response above and return it to the caller */
1087 if (response
.data
.auth
.nt_status
!= 0) {
1089 wbc_status
= wbc_create_error_info(&response
,
1091 BAIL_ON_WBC_ERROR(wbc_status
);
1097 wbc_status
= wbc_create_password_policy_info(&response
,
1099 BAIL_ON_WBC_ERROR(wbc_status
);
1102 if (reject_reason
) {
1103 *reject_reason
= response
.data
.auth
.reject_reason
;
1106 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
1107 BAIL_ON_WBC_ERROR(wbc_status
);
1114 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
1115 struct wbcAuthErrorInfo
**error
,
1116 enum wbcPasswordChangeRejectReason
*reject_reason
,
1117 struct wbcUserPasswordPolicyInfo
**policy
)
1119 return wbcCtxChangeUserPasswordEx(NULL
, params
, error
,
1120 reject_reason
, policy
);
1123 /* Change a password for a user */
1125 wbcErr
wbcCtxChangeUserPassword(struct wbcContext
*ctx
,
1126 const char *username
,
1127 const char *old_password
,
1128 const char *new_password
)
1130 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
1131 struct wbcChangePasswordParams params
;
1133 ZERO_STRUCT(params
);
1135 params
.account_name
= username
;
1136 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
1137 params
.old_password
.plaintext
= old_password
;
1138 params
.new_password
.plaintext
= new_password
;
1140 wbc_status
= wbcCtxChangeUserPasswordEx(ctx
, ¶ms
,
1144 BAIL_ON_WBC_ERROR(wbc_status
);
1151 wbcErr
wbcChangeUserPassword(const char *username
,
1152 const char *old_password
,
1153 const char *new_password
)
1155 return wbcCtxChangeUserPassword(NULL
, username
,
1156 old_password
, new_password
);
1161 wbcErr
wbcCtxLogonUser(struct wbcContext
*ctx
,
1162 const struct wbcLogonUserParams
*params
,
1163 struct wbcLogonUserInfo
**info
,
1164 struct wbcAuthErrorInfo
**error
,
1165 struct wbcUserPasswordPolicyInfo
**policy
)
1167 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
1168 struct winbindd_request request
;
1169 struct winbindd_response response
;
1172 ZERO_STRUCT(request
);
1173 ZERO_STRUCT(response
);
1186 wbc_status
= WBC_ERR_INVALID_PARAM
;
1187 BAIL_ON_WBC_ERROR(wbc_status
);
1190 if (!params
->username
) {
1191 wbc_status
= WBC_ERR_INVALID_PARAM
;
1192 BAIL_ON_WBC_ERROR(wbc_status
);
1195 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
1196 wbc_status
= WBC_ERR_INVALID_PARAM
;
1197 BAIL_ON_WBC_ERROR(wbc_status
);
1199 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
1200 wbc_status
= WBC_ERR_INVALID_PARAM
;
1201 BAIL_ON_WBC_ERROR(wbc_status
);
1204 /* Initialize request */
1206 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
1207 WBFLAG_PAM_USER_SESSION_KEY
|
1210 if (!params
->password
) {
1211 wbc_status
= WBC_ERR_INVALID_PARAM
;
1212 BAIL_ON_WBC_ERROR(wbc_status
);
1215 strncpy(request
.data
.auth
.user
,
1217 sizeof(request
.data
.auth
.user
)-1);
1219 strncpy(request
.data
.auth
.pass
,
1221 sizeof(request
.data
.auth
.pass
)-1);
1223 for (i
=0; i
<params
->num_blobs
; i
++) {
1225 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
1226 if (params
->blobs
[i
].blob
.data
) {
1227 strncpy(request
.data
.auth
.krb5_cc_type
,
1228 (const char *)params
->blobs
[i
].blob
.data
,
1229 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
1234 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
1235 if (params
->blobs
[i
].blob
.data
) {
1236 memcpy(&request
.data
.auth
.uid
,
1237 params
->blobs
[i
].blob
.data
,
1238 MIN(sizeof(request
.data
.auth
.uid
),
1239 params
->blobs
[i
].blob
.length
));
1244 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
1245 if (params
->blobs
[i
].blob
.data
) {
1248 params
->blobs
[i
].blob
.data
,
1250 params
->blobs
[i
].blob
.length
));
1251 request
.flags
|= flags
;
1256 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
1257 if (params
->blobs
[i
].blob
.data
&&
1258 params
->blobs
[i
].blob
.data
[0] > 0) {
1259 strncpy(request
.data
.auth
.require_membership_of_sid
,
1260 (const char *)params
->blobs
[i
].blob
.data
,
1261 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
1267 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_PAM_AUTH
,
1271 if (response
.data
.auth
.nt_status
!= 0) {
1273 wbc_status
= wbc_create_error_info(&response
,
1275 BAIL_ON_WBC_ERROR(wbc_status
);
1278 wbc_status
= WBC_ERR_AUTH_ERROR
;
1279 BAIL_ON_WBC_ERROR(wbc_status
);
1281 BAIL_ON_WBC_ERROR(wbc_status
);
1284 wbc_status
= wbc_create_logon_info(&response
,
1286 BAIL_ON_WBC_ERROR(wbc_status
);
1290 wbc_status
= wbc_create_password_policy_info(&response
,
1292 BAIL_ON_WBC_ERROR(wbc_status
);
1296 winbindd_free_response(&response
);
1302 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
1303 struct wbcLogonUserInfo
**info
,
1304 struct wbcAuthErrorInfo
**error
,
1305 struct wbcUserPasswordPolicyInfo
**policy
)
1307 return wbcCtxLogonUser(NULL
, params
, info
, error
, policy
);
1310 static void wbcCredentialCacheInfoDestructor(void *ptr
)
1312 struct wbcCredentialCacheInfo
*i
=
1313 (struct wbcCredentialCacheInfo
*)ptr
;
1314 wbcFreeMemory(i
->blobs
);
1317 /* Authenticate a user with cached credentials */
1319 wbcErr
wbcCtxCredentialCache(struct wbcContext
*ctx
,
1320 struct wbcCredentialCacheParams
*params
,
1321 struct wbcCredentialCacheInfo
**info
,
1322 struct wbcAuthErrorInfo
**error
)
1324 wbcErr status
= WBC_ERR_UNKNOWN_FAILURE
;
1325 struct wbcCredentialCacheInfo
*result
= NULL
;
1326 struct winbindd_request request
;
1327 struct winbindd_response response
;
1328 struct wbcNamedBlob
*initial_blob
= NULL
;
1329 struct wbcNamedBlob
*challenge_blob
= NULL
;
1332 ZERO_STRUCT(request
);
1333 ZERO_STRUCT(response
);
1337 if (error
!= NULL
) {
1340 if ((params
== NULL
)
1341 || (params
->account_name
== NULL
)
1342 || (params
->level
!= WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP
)) {
1343 status
= WBC_ERR_INVALID_PARAM
;
1347 for (i
=0; i
<params
->num_blobs
; i
++) {
1349 * Older callers used to provide the NEGOTIATE request
1350 * as "initial_blob", but it was completely ignored by winbindd.
1352 * So we keep ignoring it.
1354 * A new callers that is capable to support "new_spnego",
1355 * will provide the NEGOTIATE request as "negotiate_blob"
1358 if (strcasecmp(params
->blobs
[i
].name
, "negotiate_blob") == 0) {
1359 if (initial_blob
!= NULL
) {
1360 status
= WBC_ERR_INVALID_PARAM
;
1363 initial_blob
= ¶ms
->blobs
[i
];
1366 if (strcasecmp(params
->blobs
[i
].name
, "challenge_blob") == 0) {
1367 if (challenge_blob
!= NULL
) {
1368 status
= WBC_ERR_INVALID_PARAM
;
1371 challenge_blob
= ¶ms
->blobs
[i
];
1376 if (params
->domain_name
!= NULL
) {
1377 status
= wbcRequestResponse(ctx
, WINBINDD_INFO
,
1379 if (!WBC_ERROR_IS_OK(status
)) {
1382 snprintf(request
.data
.ccache_ntlm_auth
.user
,
1383 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1,
1384 "%s%c%s", params
->domain_name
,
1385 response
.data
.info
.winbind_separator
,
1386 params
->account_name
);
1388 strncpy(request
.data
.ccache_ntlm_auth
.user
,
1389 params
->account_name
,
1390 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1);
1392 request
.data
.ccache_ntlm_auth
.uid
= getuid();
1394 request
.data
.ccache_ntlm_auth
.initial_blob_len
= 0;
1395 request
.data
.ccache_ntlm_auth
.challenge_blob_len
= 0;
1396 request
.extra_len
= 0;
1398 if (initial_blob
!= NULL
) {
1399 request
.data
.ccache_ntlm_auth
.initial_blob_len
=
1400 initial_blob
->blob
.length
;
1401 request
.extra_len
+= initial_blob
->blob
.length
;
1403 if (challenge_blob
!= NULL
) {
1404 request
.data
.ccache_ntlm_auth
.challenge_blob_len
=
1405 challenge_blob
->blob
.length
;
1406 request
.extra_len
+= challenge_blob
->blob
.length
;
1409 if (request
.extra_len
!= 0) {
1410 request
.extra_data
.data
= (char *)malloc(request
.extra_len
);
1411 if (request
.extra_data
.data
== NULL
) {
1412 status
= WBC_ERR_NO_MEMORY
;
1416 if (initial_blob
!= NULL
) {
1417 memcpy(request
.extra_data
.data
,
1418 initial_blob
->blob
.data
, initial_blob
->blob
.length
);
1420 if (challenge_blob
!= NULL
) {
1421 memcpy(request
.extra_data
.data
1422 + request
.data
.ccache_ntlm_auth
.initial_blob_len
,
1423 challenge_blob
->blob
.data
,
1424 challenge_blob
->blob
.length
);
1427 status
= wbcRequestResponse(ctx
, WINBINDD_CCACHE_NTLMAUTH
,
1428 &request
, &response
);
1429 if (!WBC_ERROR_IS_OK(status
)) {
1433 result
= (struct wbcCredentialCacheInfo
*)wbcAllocateMemory(
1434 1, sizeof(struct wbcCredentialCacheInfo
),
1435 wbcCredentialCacheInfoDestructor
);
1436 if (result
== NULL
) {
1437 status
= WBC_ERR_NO_MEMORY
;
1440 result
->num_blobs
= 0;
1441 result
->blobs
= NULL
;
1442 status
= wbcAddNamedBlob(&result
->num_blobs
, &result
->blobs
,
1444 (uint8_t *)response
.extra_data
.data
,
1445 response
.data
.ccache_ntlm_auth
.auth_blob_len
);
1446 if (!WBC_ERROR_IS_OK(status
)) {
1449 status
= wbcAddNamedBlob(
1450 &result
->num_blobs
, &result
->blobs
, "session_key", 0,
1451 response
.data
.ccache_ntlm_auth
.session_key
,
1452 sizeof(response
.data
.ccache_ntlm_auth
.session_key
));
1453 if (!WBC_ERROR_IS_OK(status
)) {
1456 if (response
.data
.ccache_ntlm_auth
.new_spnego
) {
1457 status
= wbcAddNamedBlob(
1458 &result
->num_blobs
, &result
->blobs
, "new_spnego", 0,
1459 &response
.data
.ccache_ntlm_auth
.new_spnego
,
1460 sizeof(response
.data
.ccache_ntlm_auth
.new_spnego
));
1461 if (!WBC_ERROR_IS_OK(status
)) {
1468 status
= WBC_ERR_SUCCESS
;
1470 free(request
.extra_data
.data
);
1471 winbindd_free_response(&response
);
1472 wbcFreeMemory(result
);
1477 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1478 struct wbcCredentialCacheInfo
**info
,
1479 struct wbcAuthErrorInfo
**error
)
1481 return wbcCtxCredentialCache(NULL
, params
, info
, error
);
1484 /* Authenticate a user with cached credentials */
1486 wbcErr
wbcCtxCredentialSave(struct wbcContext
*ctx
,
1487 const char *user
, const char *password
)
1489 struct winbindd_request request
;
1490 struct winbindd_response response
;
1492 ZERO_STRUCT(request
);
1493 ZERO_STRUCT(response
);
1495 strncpy(request
.data
.ccache_save
.user
, user
,
1496 sizeof(request
.data
.ccache_save
.user
)-1);
1497 strncpy(request
.data
.ccache_save
.pass
, password
,
1498 sizeof(request
.data
.ccache_save
.pass
)-1);
1499 request
.data
.ccache_save
.uid
= getuid();
1501 return wbcRequestResponse(ctx
, WINBINDD_CCACHE_SAVE
, &request
, &response
);
1505 wbcErr
wbcCredentialSave(const char *user
, const char *password
)
1507 return wbcCtxCredentialSave(NULL
, user
, password
);