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
;
507 * the current protocol doesn't support
508 * specifying a domain
510 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
511 BAIL_ON_WBC_ERROR(wbc_status
);
514 ZERO_STRUCT(request
);
515 ZERO_STRUCT(response
);
519 wbc_status
= wbcRequestResponse(WINBINDD_CHECK_MACHACC
,
522 if (response
.data
.auth
.nt_status
!= 0) {
524 wbc_status
= wbc_create_error_info(NULL
,
527 BAIL_ON_WBC_ERROR(wbc_status
);
530 wbc_status
= WBC_ERR_AUTH_ERROR
;
531 BAIL_ON_WBC_ERROR(wbc_status
);
533 BAIL_ON_WBC_ERROR(wbc_status
);
539 /* Trigger an extended logoff notification to Winbind for a specific user */
540 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
541 struct wbcAuthErrorInfo
**error
)
543 struct winbindd_request request
;
544 struct winbindd_response response
;
545 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
550 if (!params
|| !params
->username
) {
551 wbc_status
= WBC_ERR_INVALID_PARAM
;
552 BAIL_ON_WBC_ERROR(wbc_status
);
555 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
556 wbc_status
= WBC_ERR_INVALID_PARAM
;
557 BAIL_ON_WBC_ERROR(wbc_status
);
559 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
560 wbc_status
= WBC_ERR_INVALID_PARAM
;
561 BAIL_ON_WBC_ERROR(wbc_status
);
564 ZERO_STRUCT(request
);
565 ZERO_STRUCT(response
);
567 strncpy(request
.data
.logoff
.user
, params
->username
,
568 sizeof(request
.data
.logoff
.user
)-1);
570 for (i
=0; i
<params
->num_blobs
; i
++) {
572 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
573 if (params
->blobs
[i
].blob
.data
) {
574 strncpy(request
.data
.logoff
.krb5ccname
,
575 (const char *)params
->blobs
[i
].blob
.data
,
576 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
581 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
582 if (params
->blobs
[i
].blob
.data
) {
583 memcpy(&request
.data
.logoff
.uid
,
584 params
->blobs
[i
].blob
.data
,
585 MIN(params
->blobs
[i
].blob
.length
,
586 sizeof(request
.data
.logoff
.uid
)));
591 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
592 if (params
->blobs
[i
].blob
.data
) {
593 memcpy(&request
.flags
,
594 params
->blobs
[i
].blob
.data
,
595 MIN(params
->blobs
[i
].blob
.length
,
596 sizeof(request
.flags
)));
604 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
608 /* Take the response above and return it to the caller */
609 if (response
.data
.auth
.nt_status
!= 0) {
611 wbc_status
= wbc_create_error_info(NULL
,
614 BAIL_ON_WBC_ERROR(wbc_status
);
617 wbc_status
= WBC_ERR_AUTH_ERROR
;
618 BAIL_ON_WBC_ERROR(wbc_status
);
620 BAIL_ON_WBC_ERROR(wbc_status
);
626 /* Trigger a logoff notification to Winbind for a specific user */
627 wbcErr
wbcLogoffUser(const char *username
,
629 const char *ccfilename
)
631 struct winbindd_request request
;
632 struct winbindd_response response
;
633 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
638 wbc_status
= WBC_ERR_INVALID_PARAM
;
639 BAIL_ON_WBC_ERROR(wbc_status
);
642 ZERO_STRUCT(request
);
643 ZERO_STRUCT(response
);
645 strncpy(request
.data
.logoff
.user
, username
,
646 sizeof(request
.data
.logoff
.user
)-1);
647 request
.data
.logoff
.uid
= uid
;
650 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
651 sizeof(request
.data
.logoff
.krb5ccname
)-1);
656 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
660 /* Take the response above and return it to the caller */
666 /* Change a password for a user with more detailed information upon failure */
667 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
668 struct wbcAuthErrorInfo
**error
,
669 enum wbcPasswordChangeRejectReason
*reject_reason
,
670 struct wbcUserPasswordPolicyInfo
**policy
)
672 struct winbindd_request request
;
673 struct winbindd_response response
;
674 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
679 if (!params
->account_name
) {
680 wbc_status
= WBC_ERR_INVALID_PARAM
;
681 BAIL_ON_WBC_ERROR(wbc_status
);
696 ZERO_STRUCT(request
);
697 ZERO_STRUCT(response
);
699 switch (params
->level
) {
700 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
701 cmd
= WINBINDD_PAM_CHAUTHTOK
;
703 if (!params
->account_name
) {
704 wbc_status
= WBC_ERR_INVALID_PARAM
;
705 BAIL_ON_WBC_ERROR(wbc_status
);
708 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
709 sizeof(request
.data
.chauthtok
.user
) - 1);
711 if (params
->old_password
.plaintext
) {
712 strncpy(request
.data
.chauthtok
.oldpass
,
713 params
->old_password
.plaintext
,
714 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
717 if (params
->new_password
.plaintext
) {
718 strncpy(request
.data
.chauthtok
.newpass
,
719 params
->new_password
.plaintext
,
720 sizeof(request
.data
.chauthtok
.newpass
) - 1);
724 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
725 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
727 if (!params
->account_name
|| !params
->domain_name
) {
728 wbc_status
= WBC_ERR_INVALID_PARAM
;
729 BAIL_ON_WBC_ERROR(wbc_status
);
732 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
733 !params
->old_password
.response
.old_lm_hash_enc_data
) {
734 wbc_status
= WBC_ERR_INVALID_PARAM
;
735 BAIL_ON_WBC_ERROR(wbc_status
);
738 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
739 params
->old_password
.response
.old_lm_hash_enc_data
) {
740 wbc_status
= WBC_ERR_INVALID_PARAM
;
741 BAIL_ON_WBC_ERROR(wbc_status
);
744 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
745 !params
->old_password
.response
.old_nt_hash_enc_data
) {
746 wbc_status
= WBC_ERR_INVALID_PARAM
;
747 BAIL_ON_WBC_ERROR(wbc_status
);
750 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
751 params
->old_password
.response
.old_nt_hash_enc_data
) {
752 wbc_status
= WBC_ERR_INVALID_PARAM
;
753 BAIL_ON_WBC_ERROR(wbc_status
);
756 if (params
->new_password
.response
.lm_length
&&
757 !params
->new_password
.response
.lm_data
) {
758 wbc_status
= WBC_ERR_INVALID_PARAM
;
759 BAIL_ON_WBC_ERROR(wbc_status
);
762 if (params
->new_password
.response
.lm_length
== 0 &&
763 params
->new_password
.response
.lm_data
) {
764 wbc_status
= WBC_ERR_INVALID_PARAM
;
765 BAIL_ON_WBC_ERROR(wbc_status
);
768 if (params
->new_password
.response
.nt_length
&&
769 !params
->new_password
.response
.nt_data
) {
770 wbc_status
= WBC_ERR_INVALID_PARAM
;
771 BAIL_ON_WBC_ERROR(wbc_status
);
774 if (params
->new_password
.response
.nt_length
== 0 &&
775 params
->new_password
.response
.nt_data
) {
776 wbc_status
= WBC_ERR_INVALID_PARAM
;
777 BAIL_ON_WBC_ERROR(wbc_status
);
780 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
781 params
->account_name
,
782 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
784 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
786 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
788 if (params
->new_password
.response
.nt_data
) {
789 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
790 params
->new_password
.response
.nt_data
,
791 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
792 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
793 params
->new_password
.response
.nt_length
;
796 if (params
->new_password
.response
.lm_data
) {
797 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
798 params
->new_password
.response
.lm_data
,
799 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
800 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
801 params
->new_password
.response
.lm_length
;
804 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
805 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
806 params
->old_password
.response
.old_nt_hash_enc_data
,
807 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
808 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
809 params
->old_password
.response
.old_nt_hash_enc_length
;
812 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
813 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
814 params
->old_password
.response
.old_lm_hash_enc_data
,
815 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
816 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
817 params
->old_password
.response
.old_lm_hash_enc_length
;
822 wbc_status
= WBC_ERR_INVALID_PARAM
;
823 BAIL_ON_WBC_ERROR(wbc_status
);
829 wbc_status
= wbcRequestResponse(cmd
,
832 if (WBC_ERROR_IS_OK(wbc_status
)) {
836 /* Take the response above and return it to the caller */
838 if (response
.data
.auth
.nt_status
!= 0) {
840 wbc_status
= wbc_create_error_info(NULL
,
843 BAIL_ON_WBC_ERROR(wbc_status
);
849 wbc_status
= wbc_create_password_policy_info(NULL
,
852 BAIL_ON_WBC_ERROR(wbc_status
);
856 *reject_reason
= response
.data
.auth
.reject_reason
;
859 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
860 BAIL_ON_WBC_ERROR(wbc_status
);
866 /* Change a password for a user */
867 wbcErr
wbcChangeUserPassword(const char *username
,
868 const char *old_password
,
869 const char *new_password
)
871 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
872 struct wbcChangePasswordParams params
;
876 params
.account_name
= username
;
877 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
878 params
.old_password
.plaintext
= old_password
;
879 params
.new_password
.plaintext
= new_password
;
881 wbc_status
= wbcChangeUserPasswordEx(¶ms
,
885 BAIL_ON_WBC_ERROR(wbc_status
);
892 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
893 struct wbcLogonUserInfo
**info
,
894 struct wbcAuthErrorInfo
**error
,
895 struct wbcUserPasswordPolicyInfo
**policy
)
897 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
899 struct winbindd_request request
;
900 struct winbindd_response response
;
903 ZERO_STRUCT(request
);
904 ZERO_STRUCT(response
);
917 wbc_status
= WBC_ERR_INVALID_PARAM
;
918 BAIL_ON_WBC_ERROR(wbc_status
);
921 if (!params
->username
) {
922 wbc_status
= WBC_ERR_INVALID_PARAM
;
923 BAIL_ON_WBC_ERROR(wbc_status
);
926 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
927 wbc_status
= WBC_ERR_INVALID_PARAM
;
928 BAIL_ON_WBC_ERROR(wbc_status
);
930 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
931 wbc_status
= WBC_ERR_INVALID_PARAM
;
932 BAIL_ON_WBC_ERROR(wbc_status
);
935 /* Initialize request */
937 cmd
= WINBINDD_PAM_AUTH
;
938 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
939 WBFLAG_PAM_USER_SESSION_KEY
|
942 if (!params
->password
) {
943 wbc_status
= WBC_ERR_INVALID_PARAM
;
944 BAIL_ON_WBC_ERROR(wbc_status
);
947 strncpy(request
.data
.auth
.user
,
949 sizeof(request
.data
.auth
.user
)-1);
951 strncpy(request
.data
.auth
.pass
,
953 sizeof(request
.data
.auth
.pass
)-1);
955 for (i
=0; i
<params
->num_blobs
; i
++) {
957 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
958 if (params
->blobs
[i
].blob
.data
) {
959 strncpy(request
.data
.auth
.krb5_cc_type
,
960 (const char *)params
->blobs
[i
].blob
.data
,
961 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
966 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
967 if (params
->blobs
[i
].blob
.data
) {
968 memcpy(&request
.data
.auth
.uid
,
969 params
->blobs
[i
].blob
.data
,
970 MIN(sizeof(request
.data
.auth
.uid
),
971 params
->blobs
[i
].blob
.length
));
976 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
977 if (params
->blobs
[i
].blob
.data
) {
980 params
->blobs
[i
].blob
.data
,
982 params
->blobs
[i
].blob
.length
));
983 request
.flags
|= flags
;
988 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
989 if (params
->blobs
[i
].blob
.data
&&
990 params
->blobs
[i
].blob
.data
[0] > 0) {
991 strncpy(request
.data
.auth
.require_membership_of_sid
,
992 (const char *)params
->blobs
[i
].blob
.data
,
993 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
999 wbc_status
= wbcRequestResponse(cmd
,
1003 if (response
.data
.auth
.nt_status
!= 0) {
1005 wbc_status
= wbc_create_error_info(NULL
,
1008 BAIL_ON_WBC_ERROR(wbc_status
);
1011 wbc_status
= WBC_ERR_AUTH_ERROR
;
1012 BAIL_ON_WBC_ERROR(wbc_status
);
1014 BAIL_ON_WBC_ERROR(wbc_status
);
1017 wbc_status
= wbc_create_logon_info(NULL
,
1020 BAIL_ON_WBC_ERROR(wbc_status
);
1024 wbc_status
= wbc_create_password_policy_info(NULL
,
1027 BAIL_ON_WBC_ERROR(wbc_status
);
1031 if (response
.extra_data
.data
)
1032 free(response
.extra_data
.data
);
1037 /* Authenticate a user with cached credentials */
1038 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1039 struct wbcCredentialCacheInfo
**info
,
1040 struct wbcAuthErrorInfo
**error
)
1042 return WBC_ERR_NOT_IMPLEMENTED
;