2 Unix SMB/CIFS implementation.
6 Copyright (C) Gerald (Jerry) Carter 2007
7 Copyright (C) Guenther Deschner 2008
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 3 of the License, or (at your option) any later version.
14 This library 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 GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /* Required Headers */
26 #include "libwbclient.h"
28 /* Authenticate a username/password pair */
29 wbcErr
wbcAuthenticateUser(const char *username
,
32 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
33 struct wbcAuthUserParams params
;
37 params
.account_name
= username
;
38 params
.level
= WBC_AUTH_USER_LEVEL_PLAIN
;
39 params
.password
.plaintext
= password
;
41 wbc_status
= wbcAuthenticateUserEx(¶ms
, NULL
, NULL
);
42 BAIL_ON_WBC_ERROR(wbc_status
);
48 static wbcErr
wbc_create_auth_info(TALLOC_CTX
*mem_ctx
,
49 const struct winbindd_response
*resp
,
50 struct wbcAuthUserInfo
**_i
)
52 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
53 struct wbcAuthUserInfo
*i
;
54 struct wbcDomainSid domain_sid
;
59 i
= talloc(mem_ctx
, struct wbcAuthUserInfo
);
60 BAIL_ON_PTR_ERROR(i
, wbc_status
);
62 i
->user_flags
= resp
->data
.auth
.info3
.user_flgs
;
64 i
->account_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.user_name
);
65 BAIL_ON_PTR_ERROR(i
->account_name
, wbc_status
);
66 i
->user_principal
= NULL
;
67 i
->full_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.full_name
);
68 BAIL_ON_PTR_ERROR(i
->full_name
, wbc_status
);
69 i
->domain_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_dom
);
70 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
71 i
->dns_domain_name
= NULL
;
73 i
->acct_flags
= resp
->data
.auth
.info3
.acct_flags
;
74 memcpy(i
->user_session_key
,
75 resp
->data
.auth
.user_session_key
,
76 sizeof(i
->user_session_key
));
77 memcpy(i
->lm_session_key
,
78 resp
->data
.auth
.first_8_lm_hash
,
79 sizeof(i
->lm_session_key
));
81 i
->logon_count
= resp
->data
.auth
.info3
.logon_count
;
82 i
->bad_password_count
= resp
->data
.auth
.info3
.bad_pw_count
;
84 i
->logon_time
= resp
->data
.auth
.info3
.logon_time
;
85 i
->logoff_time
= resp
->data
.auth
.info3
.logoff_time
;
86 i
->kickoff_time
= resp
->data
.auth
.info3
.kickoff_time
;
87 i
->pass_last_set_time
= resp
->data
.auth
.info3
.pass_last_set_time
;
88 i
->pass_can_change_time
= resp
->data
.auth
.info3
.pass_can_change_time
;
89 i
->pass_must_change_time
= resp
->data
.auth
.info3
.pass_must_change_time
;
91 i
->logon_server
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_srv
);
92 BAIL_ON_PTR_ERROR(i
->logon_server
, wbc_status
);
93 i
->logon_script
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_script
);
94 BAIL_ON_PTR_ERROR(i
->logon_script
, wbc_status
);
95 i
->profile_path
= talloc_strdup(i
, resp
->data
.auth
.info3
.profile_path
);
96 BAIL_ON_PTR_ERROR(i
->profile_path
, wbc_status
);
97 i
->home_directory
= talloc_strdup(i
, resp
->data
.auth
.info3
.home_dir
);
98 BAIL_ON_PTR_ERROR(i
->home_directory
, wbc_status
);
99 i
->home_drive
= talloc_strdup(i
, resp
->data
.auth
.info3
.dir_drive
);
100 BAIL_ON_PTR_ERROR(i
->home_drive
, wbc_status
);
103 i
->num_sids
+= resp
->data
.auth
.info3
.num_groups
;
104 i
->num_sids
+= resp
->data
.auth
.info3
.num_other_sids
;
106 i
->sids
= talloc_array(i
, struct wbcSidWithAttr
, i
->num_sids
);
107 BAIL_ON_PTR_ERROR(i
->sids
, wbc_status
);
109 wbc_status
= wbcStringToSid(resp
->data
.auth
.info3
.dom_sid
,
111 BAIL_ON_WBC_ERROR(wbc_status
);
113 #define _SID_COMPOSE(s, d, r, a) { \
115 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
116 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
118 wbc_status = WBC_ERR_INVALID_SID; \
119 BAIL_ON_WBC_ERROR(wbc_status); \
121 (s).attributes = a; \
125 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
126 resp
->data
.auth
.info3
.user_rid
,
129 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
130 resp
->data
.auth
.info3
.group_rid
,
134 p
= (char *)resp
->extra_data
.data
;
136 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
137 BAIL_ON_WBC_ERROR(wbc_status
);
140 for (j
=0; j
< resp
->data
.auth
.info3
.num_groups
; j
++) {
145 char *e
= strchr(p
, '\n');
147 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
148 BAIL_ON_WBC_ERROR(wbc_status
);
153 ret
= sscanf(s
, "0x%08X:0x%08X", &rid
, &attrs
);
155 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
156 BAIL_ON_WBC_ERROR(wbc_status
);
159 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
164 for (j
=0; j
< resp
->data
.auth
.info3
.num_other_sids
; j
++) {
169 char *e
= strchr(p
, '\n');
171 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
172 BAIL_ON_WBC_ERROR(wbc_status
);
179 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
180 BAIL_ON_WBC_ERROR(wbc_status
);
185 ret
= sscanf(a
, "0x%08X",
188 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
189 BAIL_ON_WBC_ERROR(wbc_status
);
192 wbc_status
= wbcStringToSid(s
, &i
->sids
[sn
].sid
);
193 BAIL_ON_WBC_ERROR(wbc_status
);
195 i
->sids
[sn
].attributes
= attrs
;
208 static wbcErr
wbc_create_error_info(TALLOC_CTX
*mem_ctx
,
209 const struct winbindd_response
*resp
,
210 struct wbcAuthErrorInfo
**_e
)
212 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
213 struct wbcAuthErrorInfo
*e
;
215 e
= talloc(mem_ctx
, struct wbcAuthErrorInfo
);
216 BAIL_ON_PTR_ERROR(e
, wbc_status
);
218 e
->nt_status
= resp
->data
.auth
.nt_status
;
219 e
->pam_error
= resp
->data
.auth
.pam_error
;
220 e
->nt_string
= talloc_strdup(e
, resp
->data
.auth
.nt_status_string
);
221 BAIL_ON_PTR_ERROR(e
->nt_string
, wbc_status
);
223 e
->display_string
= talloc_strdup(e
, resp
->data
.auth
.error_string
);
224 BAIL_ON_PTR_ERROR(e
->display_string
, wbc_status
);
234 static wbcErr
wbc_create_password_policy_info(TALLOC_CTX
*mem_ctx
,
235 const struct winbindd_response
*resp
,
236 struct wbcUserPasswordPolicyInfo
**_i
)
238 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
239 struct wbcUserPasswordPolicyInfo
*i
;
241 i
= talloc(mem_ctx
, 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(TALLOC_CTX
*mem_ctx
,
259 struct winbindd_response
*resp
,
260 struct wbcLogonUserInfo
**_i
)
262 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
263 struct wbcLogonUserInfo
*i
;
265 i
= talloc_zero(mem_ctx
, struct wbcLogonUserInfo
);
266 BAIL_ON_PTR_ERROR(i
, wbc_status
);
268 wbc_status
= wbc_create_auth_info(i
, resp
, &i
->info
);
269 BAIL_ON_WBC_ERROR(wbc_status
);
271 if (resp
->data
.auth
.krb5ccname
&&
272 strlen(resp
->data
.auth
.krb5ccname
)) {
273 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
277 (uint8_t *)resp
->data
.auth
.krb5ccname
,
278 strlen(resp
->data
.auth
.krb5ccname
)+1);
279 BAIL_ON_WBC_ERROR(wbc_status
);
282 if (resp
->data
.auth
.unix_username
&&
283 strlen(resp
->data
.auth
.unix_username
)) {
284 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
288 (uint8_t *)resp
->data
.auth
.unix_username
,
289 strlen(resp
->data
.auth
.unix_username
)+1);
290 BAIL_ON_WBC_ERROR(wbc_status
);
296 if (!WBC_ERROR_IS_OK(wbc_status
) && i
) {
297 wbcFreeMemory(i
->blobs
);
304 /* Authenticate with more detailed information */
305 wbcErr
wbcAuthenticateUserEx(const struct wbcAuthUserParams
*params
,
306 struct wbcAuthUserInfo
**info
,
307 struct wbcAuthErrorInfo
**error
)
309 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
311 struct winbindd_request request
;
312 struct winbindd_response response
;
314 ZERO_STRUCT(request
);
315 ZERO_STRUCT(response
);
322 wbc_status
= WBC_ERR_INVALID_PARAM
;
323 BAIL_ON_WBC_ERROR(wbc_status
);
326 if (!params
->account_name
) {
327 wbc_status
= WBC_ERR_INVALID_PARAM
;
328 BAIL_ON_WBC_ERROR(wbc_status
);
331 /* Initialize request */
333 switch (params
->level
) {
334 case WBC_AUTH_USER_LEVEL_PLAIN
:
335 cmd
= WINBINDD_PAM_AUTH
;
336 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
337 WBFLAG_PAM_USER_SESSION_KEY
|
340 if (!params
->password
.plaintext
) {
341 wbc_status
= WBC_ERR_INVALID_PARAM
;
342 BAIL_ON_WBC_ERROR(wbc_status
);
345 if (params
->domain_name
&& params
->domain_name
[0]) {
346 /* We need to get the winbind separator :-( */
347 struct winbindd_response sep_response
;
349 ZERO_STRUCT(sep_response
);
351 wbc_status
= wbcRequestResponse(WINBINDD_INFO
,
352 NULL
, &sep_response
);
353 BAIL_ON_WBC_ERROR(wbc_status
);
355 snprintf(request
.data
.auth
.user
,
356 sizeof(request
.data
.auth
.user
)-1,
359 sep_response
.data
.info
.winbind_separator
,
360 params
->account_name
);
362 strncpy(request
.data
.auth
.user
,
363 params
->account_name
,
364 sizeof(request
.data
.auth
.user
)-1);
367 strncpy(request
.data
.auth
.pass
,
368 params
->password
.plaintext
,
369 sizeof(request
.data
.auth
.pass
)-1);
372 case WBC_AUTH_USER_LEVEL_HASH
:
373 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
374 BAIL_ON_WBC_ERROR(wbc_status
);
377 case WBC_AUTH_USER_LEVEL_RESPONSE
:
378 cmd
= WINBINDD_PAM_AUTH_CRAP
;
379 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
380 WBFLAG_PAM_USER_SESSION_KEY
|
383 if (params
->password
.response
.lm_length
&&
384 !params
->password
.response
.lm_data
) {
385 wbc_status
= WBC_ERR_INVALID_PARAM
;
386 BAIL_ON_WBC_ERROR(wbc_status
);
388 if (params
->password
.response
.lm_length
== 0 &&
389 params
->password
.response
.lm_data
) {
390 wbc_status
= WBC_ERR_INVALID_PARAM
;
391 BAIL_ON_WBC_ERROR(wbc_status
);
394 if (params
->password
.response
.nt_length
&&
395 !params
->password
.response
.nt_data
) {
396 wbc_status
= WBC_ERR_INVALID_PARAM
;
397 BAIL_ON_WBC_ERROR(wbc_status
);
399 if (params
->password
.response
.nt_length
== 0&&
400 params
->password
.response
.nt_data
) {
401 wbc_status
= WBC_ERR_INVALID_PARAM
;
402 BAIL_ON_WBC_ERROR(wbc_status
);
405 strncpy(request
.data
.auth_crap
.user
,
406 params
->account_name
,
407 sizeof(request
.data
.auth_crap
.user
)-1);
408 if (params
->domain_name
) {
409 strncpy(request
.data
.auth_crap
.domain
,
411 sizeof(request
.data
.auth_crap
.domain
)-1);
413 if (params
->workstation_name
) {
414 strncpy(request
.data
.auth_crap
.workstation
,
415 params
->workstation_name
,
416 sizeof(request
.data
.auth_crap
.workstation
)-1);
419 request
.data
.auth_crap
.logon_parameters
=
420 params
->parameter_control
;
422 memcpy(request
.data
.auth_crap
.chal
,
423 params
->password
.response
.challenge
,
424 sizeof(request
.data
.auth_crap
.chal
));
426 request
.data
.auth_crap
.lm_resp_len
=
427 MIN(params
->password
.response
.lm_length
,
428 sizeof(request
.data
.auth_crap
.lm_resp
));
429 if (params
->password
.response
.lm_data
) {
430 memcpy(request
.data
.auth_crap
.lm_resp
,
431 params
->password
.response
.lm_data
,
432 request
.data
.auth_crap
.lm_resp_len
);
434 request
.data
.auth_crap
.nt_resp_len
= params
->password
.response
.nt_length
;
435 if (params
->password
.response
.nt_length
> sizeof(request
.data
.auth_crap
.nt_resp
)) {
436 request
.flags
|= WBFLAG_BIG_NTLMV2_BLOB
;
437 request
.extra_len
= params
->password
.response
.nt_length
;
438 request
.extra_data
.data
= talloc_zero_array(NULL
, char, request
.extra_len
);
439 if (request
.extra_data
.data
== NULL
) {
440 wbc_status
= WBC_ERR_NO_MEMORY
;
441 BAIL_ON_WBC_ERROR(wbc_status
);
443 memcpy(request
.extra_data
.data
,
444 params
->password
.response
.nt_data
,
445 request
.data
.auth_crap
.nt_resp_len
);
446 } else if (params
->password
.response
.nt_data
) {
447 memcpy(request
.data
.auth_crap
.nt_resp
,
448 params
->password
.response
.nt_data
,
449 request
.data
.auth_crap
.nt_resp_len
);
457 wbc_status
= WBC_ERR_INVALID_PARAM
;
458 BAIL_ON_WBC_ERROR(wbc_status
);
462 request
.flags
|= params
->flags
;
465 wbc_status
= wbcRequestResponse(cmd
,
468 if (response
.data
.auth
.nt_status
!= 0) {
470 wbc_status
= wbc_create_error_info(NULL
,
473 BAIL_ON_WBC_ERROR(wbc_status
);
476 wbc_status
= WBC_ERR_AUTH_ERROR
;
477 BAIL_ON_WBC_ERROR(wbc_status
);
479 BAIL_ON_WBC_ERROR(wbc_status
);
482 wbc_status
= wbc_create_auth_info(NULL
,
485 BAIL_ON_WBC_ERROR(wbc_status
);
489 if (response
.extra_data
.data
)
490 free(response
.extra_data
.data
);
492 talloc_free(request
.extra_data
.data
);
497 /* Trigger a verification of the trust credentials of a specific domain */
498 wbcErr
wbcCheckTrustCredentials(const char *domain
,
499 struct wbcAuthErrorInfo
**error
)
501 struct winbindd_request request
;
502 struct winbindd_response response
;
503 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
505 ZERO_STRUCT(request
);
506 ZERO_STRUCT(response
);
509 strncpy(request
.domain_name
, domain
,
510 sizeof(request
.domain_name
)-1);
515 wbc_status
= wbcRequestResponse(WINBINDD_CHECK_MACHACC
,
518 if (response
.data
.auth
.nt_status
!= 0) {
520 wbc_status
= wbc_create_error_info(NULL
,
523 BAIL_ON_WBC_ERROR(wbc_status
);
526 wbc_status
= WBC_ERR_AUTH_ERROR
;
527 BAIL_ON_WBC_ERROR(wbc_status
);
529 BAIL_ON_WBC_ERROR(wbc_status
);
535 /* Trigger a change of the trust credentials for a specific domain */
536 wbcErr
wbcChangeTrustCredentials(const char *domain
,
537 struct wbcAuthErrorInfo
**error
)
539 struct winbindd_request request
;
540 struct winbindd_response response
;
541 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
543 ZERO_STRUCT(request
);
544 ZERO_STRUCT(response
);
547 strncpy(request
.domain_name
, domain
,
548 sizeof(request
.domain_name
)-1);
553 wbc_status
= wbcRequestResponse(WINBINDD_CHANGE_MACHACC
,
556 if (response
.data
.auth
.nt_status
!= 0) {
558 wbc_status
= wbc_create_error_info(NULL
,
561 BAIL_ON_WBC_ERROR(wbc_status
);
564 wbc_status
= WBC_ERR_AUTH_ERROR
;
565 BAIL_ON_WBC_ERROR(wbc_status
);
567 BAIL_ON_WBC_ERROR(wbc_status
);
573 /* Trigger an extended logoff notification to Winbind for a specific user */
574 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
575 struct wbcAuthErrorInfo
**error
)
577 struct winbindd_request request
;
578 struct winbindd_response response
;
579 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
584 if (!params
|| !params
->username
) {
585 wbc_status
= WBC_ERR_INVALID_PARAM
;
586 BAIL_ON_WBC_ERROR(wbc_status
);
589 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
590 wbc_status
= WBC_ERR_INVALID_PARAM
;
591 BAIL_ON_WBC_ERROR(wbc_status
);
593 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
594 wbc_status
= WBC_ERR_INVALID_PARAM
;
595 BAIL_ON_WBC_ERROR(wbc_status
);
598 ZERO_STRUCT(request
);
599 ZERO_STRUCT(response
);
601 strncpy(request
.data
.logoff
.user
, params
->username
,
602 sizeof(request
.data
.logoff
.user
)-1);
604 for (i
=0; i
<params
->num_blobs
; i
++) {
606 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
607 if (params
->blobs
[i
].blob
.data
) {
608 strncpy(request
.data
.logoff
.krb5ccname
,
609 (const char *)params
->blobs
[i
].blob
.data
,
610 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
615 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
616 if (params
->blobs
[i
].blob
.data
) {
617 memcpy(&request
.data
.logoff
.uid
,
618 params
->blobs
[i
].blob
.data
,
619 MIN(params
->blobs
[i
].blob
.length
,
620 sizeof(request
.data
.logoff
.uid
)));
625 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
626 if (params
->blobs
[i
].blob
.data
) {
627 memcpy(&request
.flags
,
628 params
->blobs
[i
].blob
.data
,
629 MIN(params
->blobs
[i
].blob
.length
,
630 sizeof(request
.flags
)));
638 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
642 /* Take the response above and return it to the caller */
643 if (response
.data
.auth
.nt_status
!= 0) {
645 wbc_status
= wbc_create_error_info(NULL
,
648 BAIL_ON_WBC_ERROR(wbc_status
);
651 wbc_status
= WBC_ERR_AUTH_ERROR
;
652 BAIL_ON_WBC_ERROR(wbc_status
);
654 BAIL_ON_WBC_ERROR(wbc_status
);
660 /* Trigger a logoff notification to Winbind for a specific user */
661 wbcErr
wbcLogoffUser(const char *username
,
663 const char *ccfilename
)
665 struct winbindd_request request
;
666 struct winbindd_response response
;
667 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
672 wbc_status
= WBC_ERR_INVALID_PARAM
;
673 BAIL_ON_WBC_ERROR(wbc_status
);
676 ZERO_STRUCT(request
);
677 ZERO_STRUCT(response
);
679 strncpy(request
.data
.logoff
.user
, username
,
680 sizeof(request
.data
.logoff
.user
)-1);
681 request
.data
.logoff
.uid
= uid
;
684 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
685 sizeof(request
.data
.logoff
.krb5ccname
)-1);
690 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
694 /* Take the response above and return it to the caller */
700 /* Change a password for a user with more detailed information upon failure */
701 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
702 struct wbcAuthErrorInfo
**error
,
703 enum wbcPasswordChangeRejectReason
*reject_reason
,
704 struct wbcUserPasswordPolicyInfo
**policy
)
706 struct winbindd_request request
;
707 struct winbindd_response response
;
708 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
713 if (!params
->account_name
) {
714 wbc_status
= WBC_ERR_INVALID_PARAM
;
715 BAIL_ON_WBC_ERROR(wbc_status
);
730 ZERO_STRUCT(request
);
731 ZERO_STRUCT(response
);
733 switch (params
->level
) {
734 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
735 cmd
= WINBINDD_PAM_CHAUTHTOK
;
737 if (!params
->account_name
) {
738 wbc_status
= WBC_ERR_INVALID_PARAM
;
739 BAIL_ON_WBC_ERROR(wbc_status
);
742 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
743 sizeof(request
.data
.chauthtok
.user
) - 1);
745 if (params
->old_password
.plaintext
) {
746 strncpy(request
.data
.chauthtok
.oldpass
,
747 params
->old_password
.plaintext
,
748 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
751 if (params
->new_password
.plaintext
) {
752 strncpy(request
.data
.chauthtok
.newpass
,
753 params
->new_password
.plaintext
,
754 sizeof(request
.data
.chauthtok
.newpass
) - 1);
758 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
759 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
761 if (!params
->account_name
|| !params
->domain_name
) {
762 wbc_status
= WBC_ERR_INVALID_PARAM
;
763 BAIL_ON_WBC_ERROR(wbc_status
);
766 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
767 !params
->old_password
.response
.old_lm_hash_enc_data
) {
768 wbc_status
= WBC_ERR_INVALID_PARAM
;
769 BAIL_ON_WBC_ERROR(wbc_status
);
772 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
773 params
->old_password
.response
.old_lm_hash_enc_data
) {
774 wbc_status
= WBC_ERR_INVALID_PARAM
;
775 BAIL_ON_WBC_ERROR(wbc_status
);
778 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
779 !params
->old_password
.response
.old_nt_hash_enc_data
) {
780 wbc_status
= WBC_ERR_INVALID_PARAM
;
781 BAIL_ON_WBC_ERROR(wbc_status
);
784 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
785 params
->old_password
.response
.old_nt_hash_enc_data
) {
786 wbc_status
= WBC_ERR_INVALID_PARAM
;
787 BAIL_ON_WBC_ERROR(wbc_status
);
790 if (params
->new_password
.response
.lm_length
&&
791 !params
->new_password
.response
.lm_data
) {
792 wbc_status
= WBC_ERR_INVALID_PARAM
;
793 BAIL_ON_WBC_ERROR(wbc_status
);
796 if (params
->new_password
.response
.lm_length
== 0 &&
797 params
->new_password
.response
.lm_data
) {
798 wbc_status
= WBC_ERR_INVALID_PARAM
;
799 BAIL_ON_WBC_ERROR(wbc_status
);
802 if (params
->new_password
.response
.nt_length
&&
803 !params
->new_password
.response
.nt_data
) {
804 wbc_status
= WBC_ERR_INVALID_PARAM
;
805 BAIL_ON_WBC_ERROR(wbc_status
);
808 if (params
->new_password
.response
.nt_length
== 0 &&
809 params
->new_password
.response
.nt_data
) {
810 wbc_status
= WBC_ERR_INVALID_PARAM
;
811 BAIL_ON_WBC_ERROR(wbc_status
);
814 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
815 params
->account_name
,
816 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
818 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
820 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
822 if (params
->new_password
.response
.nt_data
) {
823 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
824 params
->new_password
.response
.nt_data
,
825 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
826 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
827 params
->new_password
.response
.nt_length
;
830 if (params
->new_password
.response
.lm_data
) {
831 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
832 params
->new_password
.response
.lm_data
,
833 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
834 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
835 params
->new_password
.response
.lm_length
;
838 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
839 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
840 params
->old_password
.response
.old_nt_hash_enc_data
,
841 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
842 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
843 params
->old_password
.response
.old_nt_hash_enc_length
;
846 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
847 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
848 params
->old_password
.response
.old_lm_hash_enc_data
,
849 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
850 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
851 params
->old_password
.response
.old_lm_hash_enc_length
;
856 wbc_status
= WBC_ERR_INVALID_PARAM
;
857 BAIL_ON_WBC_ERROR(wbc_status
);
863 wbc_status
= wbcRequestResponse(cmd
,
866 if (WBC_ERROR_IS_OK(wbc_status
)) {
870 /* Take the response above and return it to the caller */
872 if (response
.data
.auth
.nt_status
!= 0) {
874 wbc_status
= wbc_create_error_info(NULL
,
877 BAIL_ON_WBC_ERROR(wbc_status
);
883 wbc_status
= wbc_create_password_policy_info(NULL
,
886 BAIL_ON_WBC_ERROR(wbc_status
);
890 *reject_reason
= response
.data
.auth
.reject_reason
;
893 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
894 BAIL_ON_WBC_ERROR(wbc_status
);
900 /* Change a password for a user */
901 wbcErr
wbcChangeUserPassword(const char *username
,
902 const char *old_password
,
903 const char *new_password
)
905 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
906 struct wbcChangePasswordParams params
;
910 params
.account_name
= username
;
911 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
912 params
.old_password
.plaintext
= old_password
;
913 params
.new_password
.plaintext
= new_password
;
915 wbc_status
= wbcChangeUserPasswordEx(¶ms
,
919 BAIL_ON_WBC_ERROR(wbc_status
);
926 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
927 struct wbcLogonUserInfo
**info
,
928 struct wbcAuthErrorInfo
**error
,
929 struct wbcUserPasswordPolicyInfo
**policy
)
931 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
933 struct winbindd_request request
;
934 struct winbindd_response response
;
937 ZERO_STRUCT(request
);
938 ZERO_STRUCT(response
);
951 wbc_status
= WBC_ERR_INVALID_PARAM
;
952 BAIL_ON_WBC_ERROR(wbc_status
);
955 if (!params
->username
) {
956 wbc_status
= WBC_ERR_INVALID_PARAM
;
957 BAIL_ON_WBC_ERROR(wbc_status
);
960 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
961 wbc_status
= WBC_ERR_INVALID_PARAM
;
962 BAIL_ON_WBC_ERROR(wbc_status
);
964 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
965 wbc_status
= WBC_ERR_INVALID_PARAM
;
966 BAIL_ON_WBC_ERROR(wbc_status
);
969 /* Initialize request */
971 cmd
= WINBINDD_PAM_AUTH
;
972 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
973 WBFLAG_PAM_USER_SESSION_KEY
|
976 if (!params
->password
) {
977 wbc_status
= WBC_ERR_INVALID_PARAM
;
978 BAIL_ON_WBC_ERROR(wbc_status
);
981 strncpy(request
.data
.auth
.user
,
983 sizeof(request
.data
.auth
.user
)-1);
985 strncpy(request
.data
.auth
.pass
,
987 sizeof(request
.data
.auth
.pass
)-1);
989 for (i
=0; i
<params
->num_blobs
; i
++) {
991 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
992 if (params
->blobs
[i
].blob
.data
) {
993 strncpy(request
.data
.auth
.krb5_cc_type
,
994 (const char *)params
->blobs
[i
].blob
.data
,
995 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
1000 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
1001 if (params
->blobs
[i
].blob
.data
) {
1002 memcpy(&request
.data
.auth
.uid
,
1003 params
->blobs
[i
].blob
.data
,
1004 MIN(sizeof(request
.data
.auth
.uid
),
1005 params
->blobs
[i
].blob
.length
));
1010 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
1011 if (params
->blobs
[i
].blob
.data
) {
1014 params
->blobs
[i
].blob
.data
,
1016 params
->blobs
[i
].blob
.length
));
1017 request
.flags
|= flags
;
1022 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
1023 if (params
->blobs
[i
].blob
.data
&&
1024 params
->blobs
[i
].blob
.data
[0] > 0) {
1025 strncpy(request
.data
.auth
.require_membership_of_sid
,
1026 (const char *)params
->blobs
[i
].blob
.data
,
1027 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
1033 wbc_status
= wbcRequestResponse(cmd
,
1037 if (response
.data
.auth
.nt_status
!= 0) {
1039 wbc_status
= wbc_create_error_info(NULL
,
1042 BAIL_ON_WBC_ERROR(wbc_status
);
1045 wbc_status
= WBC_ERR_AUTH_ERROR
;
1046 BAIL_ON_WBC_ERROR(wbc_status
);
1048 BAIL_ON_WBC_ERROR(wbc_status
);
1051 wbc_status
= wbc_create_logon_info(NULL
,
1054 BAIL_ON_WBC_ERROR(wbc_status
);
1058 wbc_status
= wbc_create_password_policy_info(NULL
,
1061 BAIL_ON_WBC_ERROR(wbc_status
);
1065 if (response
.extra_data
.data
)
1066 free(response
.extra_data
.data
);
1071 /* Authenticate a user with cached credentials */
1072 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1073 struct wbcCredentialCacheInfo
**info
,
1074 struct wbcAuthErrorInfo
**error
)
1076 return WBC_ERR_NOT_IMPLEMENTED
;