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 request
.data
.auth_crap
.nt_resp_len
=
430 MIN(params
->password
.response
.nt_length
,
431 sizeof(request
.data
.auth_crap
.nt_resp
));
432 if (params
->password
.response
.lm_data
) {
433 memcpy(request
.data
.auth_crap
.lm_resp
,
434 params
->password
.response
.lm_data
,
435 request
.data
.auth_crap
.lm_resp_len
);
437 if (params
->password
.response
.nt_data
) {
438 memcpy(request
.data
.auth_crap
.nt_resp
,
439 params
->password
.response
.nt_data
,
440 request
.data
.auth_crap
.nt_resp_len
);
448 wbc_status
= WBC_ERR_INVALID_PARAM
;
449 BAIL_ON_WBC_ERROR(wbc_status
);
453 request
.flags
|= params
->flags
;
456 wbc_status
= wbcRequestResponse(cmd
,
459 if (response
.data
.auth
.nt_status
!= 0) {
461 wbc_status
= wbc_create_error_info(NULL
,
464 BAIL_ON_WBC_ERROR(wbc_status
);
467 wbc_status
= WBC_ERR_AUTH_ERROR
;
468 BAIL_ON_WBC_ERROR(wbc_status
);
470 BAIL_ON_WBC_ERROR(wbc_status
);
473 wbc_status
= wbc_create_auth_info(NULL
,
476 BAIL_ON_WBC_ERROR(wbc_status
);
480 if (response
.extra_data
.data
)
481 free(response
.extra_data
.data
);
486 /* Trigger a verification of the trust credentials of a specific domain */
487 wbcErr
wbcCheckTrustCredentials(const char *domain
,
488 struct wbcAuthErrorInfo
**error
)
490 struct winbindd_request request
;
491 struct winbindd_response response
;
492 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
496 * the current protocol doesn't support
497 * specifying a domain
499 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
500 BAIL_ON_WBC_ERROR(wbc_status
);
503 ZERO_STRUCT(request
);
504 ZERO_STRUCT(response
);
508 wbc_status
= wbcRequestResponse(WINBINDD_CHECK_MACHACC
,
511 if (response
.data
.auth
.nt_status
!= 0) {
513 wbc_status
= wbc_create_error_info(NULL
,
516 BAIL_ON_WBC_ERROR(wbc_status
);
519 wbc_status
= WBC_ERR_AUTH_ERROR
;
520 BAIL_ON_WBC_ERROR(wbc_status
);
522 BAIL_ON_WBC_ERROR(wbc_status
);
528 /* Trigger an extended logoff notification to Winbind for a specific user */
529 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
530 struct wbcAuthErrorInfo
**error
)
532 struct winbindd_request request
;
533 struct winbindd_response response
;
534 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
539 if (!params
|| !params
->username
) {
540 wbc_status
= WBC_ERR_INVALID_PARAM
;
541 BAIL_ON_WBC_ERROR(wbc_status
);
544 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
545 wbc_status
= WBC_ERR_INVALID_PARAM
;
546 BAIL_ON_WBC_ERROR(wbc_status
);
548 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
549 wbc_status
= WBC_ERR_INVALID_PARAM
;
550 BAIL_ON_WBC_ERROR(wbc_status
);
553 ZERO_STRUCT(request
);
554 ZERO_STRUCT(response
);
556 strncpy(request
.data
.logoff
.user
, params
->username
,
557 sizeof(request
.data
.logoff
.user
)-1);
559 for (i
=0; i
<params
->num_blobs
; i
++) {
561 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
562 if (params
->blobs
[i
].blob
.data
) {
563 strncpy(request
.data
.logoff
.krb5ccname
,
564 (const char *)params
->blobs
[i
].blob
.data
,
565 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
570 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
571 if (params
->blobs
[i
].blob
.data
) {
572 memcpy(&request
.data
.logoff
.uid
,
573 params
->blobs
[i
].blob
.data
,
574 MIN(params
->blobs
[i
].blob
.length
,
575 sizeof(request
.data
.logoff
.uid
)));
580 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
581 if (params
->blobs
[i
].blob
.data
) {
582 memcpy(&request
.flags
,
583 params
->blobs
[i
].blob
.data
,
584 MIN(params
->blobs
[i
].blob
.length
,
585 sizeof(request
.flags
)));
593 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
597 /* Take the response above and return it to the caller */
598 if (response
.data
.auth
.nt_status
!= 0) {
600 wbc_status
= wbc_create_error_info(NULL
,
603 BAIL_ON_WBC_ERROR(wbc_status
);
606 wbc_status
= WBC_ERR_AUTH_ERROR
;
607 BAIL_ON_WBC_ERROR(wbc_status
);
609 BAIL_ON_WBC_ERROR(wbc_status
);
615 /* Trigger a logoff notification to Winbind for a specific user */
616 wbcErr
wbcLogoffUser(const char *username
,
618 const char *ccfilename
)
620 struct winbindd_request request
;
621 struct winbindd_response response
;
622 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
627 wbc_status
= WBC_ERR_INVALID_PARAM
;
628 BAIL_ON_WBC_ERROR(wbc_status
);
631 ZERO_STRUCT(request
);
632 ZERO_STRUCT(response
);
634 strncpy(request
.data
.logoff
.user
, username
,
635 sizeof(request
.data
.logoff
.user
)-1);
636 request
.data
.logoff
.uid
= uid
;
639 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
640 sizeof(request
.data
.logoff
.krb5ccname
)-1);
645 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
649 /* Take the response above and return it to the caller */
655 /* Change a password for a user with more detailed information upon failure */
656 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
657 struct wbcAuthErrorInfo
**error
,
658 enum wbcPasswordChangeRejectReason
*reject_reason
,
659 struct wbcUserPasswordPolicyInfo
**policy
)
661 struct winbindd_request request
;
662 struct winbindd_response response
;
663 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
668 if (!params
->account_name
) {
669 wbc_status
= WBC_ERR_INVALID_PARAM
;
670 BAIL_ON_WBC_ERROR(wbc_status
);
685 ZERO_STRUCT(request
);
686 ZERO_STRUCT(response
);
688 switch (params
->level
) {
689 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
690 cmd
= WINBINDD_PAM_CHAUTHTOK
;
692 if (!params
->account_name
) {
693 wbc_status
= WBC_ERR_INVALID_PARAM
;
694 BAIL_ON_WBC_ERROR(wbc_status
);
697 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
698 sizeof(request
.data
.chauthtok
.user
) - 1);
700 if (params
->old_password
.plaintext
) {
701 strncpy(request
.data
.chauthtok
.oldpass
,
702 params
->old_password
.plaintext
,
703 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
706 if (params
->new_password
.plaintext
) {
707 strncpy(request
.data
.chauthtok
.newpass
,
708 params
->new_password
.plaintext
,
709 sizeof(request
.data
.chauthtok
.newpass
) - 1);
713 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
714 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
716 if (!params
->account_name
|| !params
->domain_name
) {
717 wbc_status
= WBC_ERR_INVALID_PARAM
;
718 BAIL_ON_WBC_ERROR(wbc_status
);
721 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
722 !params
->old_password
.response
.old_lm_hash_enc_data
) {
723 wbc_status
= WBC_ERR_INVALID_PARAM
;
724 BAIL_ON_WBC_ERROR(wbc_status
);
727 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
728 params
->old_password
.response
.old_lm_hash_enc_data
) {
729 wbc_status
= WBC_ERR_INVALID_PARAM
;
730 BAIL_ON_WBC_ERROR(wbc_status
);
733 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
734 !params
->old_password
.response
.old_nt_hash_enc_data
) {
735 wbc_status
= WBC_ERR_INVALID_PARAM
;
736 BAIL_ON_WBC_ERROR(wbc_status
);
739 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
740 params
->old_password
.response
.old_nt_hash_enc_data
) {
741 wbc_status
= WBC_ERR_INVALID_PARAM
;
742 BAIL_ON_WBC_ERROR(wbc_status
);
745 if (params
->new_password
.response
.lm_length
&&
746 !params
->new_password
.response
.lm_data
) {
747 wbc_status
= WBC_ERR_INVALID_PARAM
;
748 BAIL_ON_WBC_ERROR(wbc_status
);
751 if (params
->new_password
.response
.lm_length
== 0 &&
752 params
->new_password
.response
.lm_data
) {
753 wbc_status
= WBC_ERR_INVALID_PARAM
;
754 BAIL_ON_WBC_ERROR(wbc_status
);
757 if (params
->new_password
.response
.nt_length
&&
758 !params
->new_password
.response
.nt_data
) {
759 wbc_status
= WBC_ERR_INVALID_PARAM
;
760 BAIL_ON_WBC_ERROR(wbc_status
);
763 if (params
->new_password
.response
.nt_length
== 0 &&
764 params
->new_password
.response
.nt_data
) {
765 wbc_status
= WBC_ERR_INVALID_PARAM
;
766 BAIL_ON_WBC_ERROR(wbc_status
);
769 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
770 params
->account_name
,
771 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
773 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
775 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
777 if (params
->new_password
.response
.nt_data
) {
778 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
779 params
->new_password
.response
.nt_data
,
780 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
781 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
782 params
->new_password
.response
.nt_length
;
785 if (params
->new_password
.response
.lm_data
) {
786 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
787 params
->new_password
.response
.lm_data
,
788 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
789 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
790 params
->new_password
.response
.lm_length
;
793 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
794 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
795 params
->old_password
.response
.old_nt_hash_enc_data
,
796 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
797 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
798 params
->old_password
.response
.old_nt_hash_enc_length
;
801 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
802 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
803 params
->old_password
.response
.old_lm_hash_enc_data
,
804 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
805 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
806 params
->old_password
.response
.old_lm_hash_enc_length
;
811 wbc_status
= WBC_ERR_INVALID_PARAM
;
812 BAIL_ON_WBC_ERROR(wbc_status
);
818 wbc_status
= wbcRequestResponse(cmd
,
821 if (WBC_ERROR_IS_OK(wbc_status
)) {
825 /* Take the response above and return it to the caller */
827 if (response
.data
.auth
.nt_status
!= 0) {
829 wbc_status
= wbc_create_error_info(NULL
,
832 BAIL_ON_WBC_ERROR(wbc_status
);
838 wbc_status
= wbc_create_password_policy_info(NULL
,
841 BAIL_ON_WBC_ERROR(wbc_status
);
845 *reject_reason
= response
.data
.auth
.reject_reason
;
848 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
849 BAIL_ON_WBC_ERROR(wbc_status
);
855 /* Change a password for a user */
856 wbcErr
wbcChangeUserPassword(const char *username
,
857 const char *old_password
,
858 const char *new_password
)
860 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
861 struct wbcChangePasswordParams params
;
865 params
.account_name
= username
;
866 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
867 params
.old_password
.plaintext
= old_password
;
868 params
.new_password
.plaintext
= new_password
;
870 wbc_status
= wbcChangeUserPasswordEx(¶ms
,
874 BAIL_ON_WBC_ERROR(wbc_status
);
881 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
882 struct wbcLogonUserInfo
**info
,
883 struct wbcAuthErrorInfo
**error
,
884 struct wbcUserPasswordPolicyInfo
**policy
)
886 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
888 struct winbindd_request request
;
889 struct winbindd_response response
;
892 ZERO_STRUCT(request
);
893 ZERO_STRUCT(response
);
906 wbc_status
= WBC_ERR_INVALID_PARAM
;
907 BAIL_ON_WBC_ERROR(wbc_status
);
910 if (!params
->username
) {
911 wbc_status
= WBC_ERR_INVALID_PARAM
;
912 BAIL_ON_WBC_ERROR(wbc_status
);
915 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
916 wbc_status
= WBC_ERR_INVALID_PARAM
;
917 BAIL_ON_WBC_ERROR(wbc_status
);
919 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
920 wbc_status
= WBC_ERR_INVALID_PARAM
;
921 BAIL_ON_WBC_ERROR(wbc_status
);
924 /* Initialize request */
926 cmd
= WINBINDD_PAM_AUTH
;
927 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
928 WBFLAG_PAM_USER_SESSION_KEY
|
931 if (!params
->password
) {
932 wbc_status
= WBC_ERR_INVALID_PARAM
;
933 BAIL_ON_WBC_ERROR(wbc_status
);
936 strncpy(request
.data
.auth
.user
,
938 sizeof(request
.data
.auth
.user
)-1);
940 strncpy(request
.data
.auth
.pass
,
942 sizeof(request
.data
.auth
.pass
)-1);
944 for (i
=0; i
<params
->num_blobs
; i
++) {
946 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
947 if (params
->blobs
[i
].blob
.data
) {
948 strncpy(request
.data
.auth
.krb5_cc_type
,
949 (const char *)params
->blobs
[i
].blob
.data
,
950 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
955 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
956 if (params
->blobs
[i
].blob
.data
) {
957 memcpy(&request
.data
.auth
.uid
,
958 params
->blobs
[i
].blob
.data
,
959 MIN(sizeof(request
.data
.auth
.uid
),
960 params
->blobs
[i
].blob
.length
));
965 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
966 if (params
->blobs
[i
].blob
.data
) {
969 params
->blobs
[i
].blob
.data
,
971 params
->blobs
[i
].blob
.length
));
972 request
.flags
|= flags
;
977 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
978 if (params
->blobs
[i
].blob
.data
&&
979 params
->blobs
[i
].blob
.data
[0] > 0) {
980 strncpy(request
.data
.auth
.require_membership_of_sid
,
981 (const char *)params
->blobs
[i
].blob
.data
,
982 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
988 wbc_status
= wbcRequestResponse(cmd
,
992 if (response
.data
.auth
.nt_status
!= 0) {
994 wbc_status
= wbc_create_error_info(NULL
,
997 BAIL_ON_WBC_ERROR(wbc_status
);
1000 wbc_status
= WBC_ERR_AUTH_ERROR
;
1001 BAIL_ON_WBC_ERROR(wbc_status
);
1003 BAIL_ON_WBC_ERROR(wbc_status
);
1006 wbc_status
= wbc_create_logon_info(NULL
,
1009 BAIL_ON_WBC_ERROR(wbc_status
);
1013 wbc_status
= wbc_create_password_policy_info(NULL
,
1016 BAIL_ON_WBC_ERROR(wbc_status
);
1020 if (response
.extra_data
.data
)
1021 free(response
.extra_data
.data
);
1026 /* Authenticate a user with cached credentials */
1027 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1028 struct wbcCredentialCacheInfo
**info
,
1029 struct wbcAuthErrorInfo
**error
)
1031 return WBC_ERR_NOT_IMPLEMENTED
;