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 */
25 #include "libwbclient.h"
27 /* Authenticate a username/password pair */
28 wbcErr
wbcAuthenticateUser(const char *username
,
31 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
32 struct wbcAuthUserParams params
;
36 params
.account_name
= username
;
37 params
.level
= WBC_AUTH_USER_LEVEL_PLAIN
;
38 params
.password
.plaintext
= password
;
40 wbc_status
= wbcAuthenticateUserEx(¶ms
, NULL
, NULL
);
41 BAIL_ON_WBC_ERROR(wbc_status
);
47 static wbcErr
wbc_create_auth_info(TALLOC_CTX
*mem_ctx
,
48 const struct winbindd_response
*resp
,
49 struct wbcAuthUserInfo
**_i
)
51 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
52 struct wbcAuthUserInfo
*i
;
53 struct wbcDomainSid domain_sid
;
58 i
= talloc(mem_ctx
, struct wbcAuthUserInfo
);
59 BAIL_ON_PTR_ERROR(i
, wbc_status
);
61 i
->user_flags
= resp
->data
.auth
.info3
.user_flgs
;
63 i
->account_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.user_name
);
64 BAIL_ON_PTR_ERROR(i
->account_name
, wbc_status
);
65 i
->user_principal
= NULL
;
66 i
->full_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.full_name
);
67 BAIL_ON_PTR_ERROR(i
->full_name
, wbc_status
);
68 i
->domain_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_dom
);
69 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
70 i
->dns_domain_name
= NULL
;
72 i
->acct_flags
= resp
->data
.auth
.info3
.acct_flags
;
73 memcpy(i
->user_session_key
,
74 resp
->data
.auth
.user_session_key
,
75 sizeof(i
->user_session_key
));
76 memcpy(i
->lm_session_key
,
77 resp
->data
.auth
.first_8_lm_hash
,
78 sizeof(i
->lm_session_key
));
80 i
->logon_count
= resp
->data
.auth
.info3
.logon_count
;
81 i
->bad_password_count
= resp
->data
.auth
.info3
.bad_pw_count
;
83 i
->logon_time
= resp
->data
.auth
.info3
.logon_time
;
84 i
->logoff_time
= resp
->data
.auth
.info3
.logoff_time
;
85 i
->kickoff_time
= resp
->data
.auth
.info3
.kickoff_time
;
86 i
->pass_last_set_time
= resp
->data
.auth
.info3
.pass_last_set_time
;
87 i
->pass_can_change_time
= resp
->data
.auth
.info3
.pass_can_change_time
;
88 i
->pass_must_change_time
= resp
->data
.auth
.info3
.pass_must_change_time
;
90 i
->logon_server
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_srv
);
91 BAIL_ON_PTR_ERROR(i
->logon_server
, wbc_status
);
92 i
->logon_script
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_script
);
93 BAIL_ON_PTR_ERROR(i
->logon_script
, wbc_status
);
94 i
->profile_path
= talloc_strdup(i
, resp
->data
.auth
.info3
.profile_path
);
95 BAIL_ON_PTR_ERROR(i
->profile_path
, wbc_status
);
96 i
->home_directory
= talloc_strdup(i
, resp
->data
.auth
.info3
.home_dir
);
97 BAIL_ON_PTR_ERROR(i
->home_directory
, wbc_status
);
98 i
->home_drive
= talloc_strdup(i
, resp
->data
.auth
.info3
.dir_drive
);
99 BAIL_ON_PTR_ERROR(i
->home_drive
, wbc_status
);
102 i
->num_sids
+= resp
->data
.auth
.info3
.num_groups
;
103 i
->num_sids
+= resp
->data
.auth
.info3
.num_other_sids
;
105 i
->sids
= talloc_array(i
, struct wbcSidWithAttr
, i
->num_sids
);
106 BAIL_ON_PTR_ERROR(i
->sids
, wbc_status
);
108 wbc_status
= wbcStringToSid(resp
->data
.auth
.info3
.dom_sid
,
110 BAIL_ON_WBC_ERROR(wbc_status
);
112 #define _SID_COMPOSE(s, d, r, a) { \
114 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
115 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
117 wbc_status = WBC_ERR_INVALID_SID; \
118 BAIL_ON_WBC_ERROR(wbc_status); \
120 (s).attributes = a; \
124 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
125 resp
->data
.auth
.info3
.user_rid
,
128 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
129 resp
->data
.auth
.info3
.group_rid
,
133 p
= (char *)resp
->extra_data
.data
;
135 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
136 BAIL_ON_WBC_ERROR(wbc_status
);
139 for (j
=0; j
< resp
->data
.auth
.info3
.num_groups
; j
++) {
144 char *e
= strchr(p
, '\n');
146 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
147 BAIL_ON_WBC_ERROR(wbc_status
);
152 ret
= sscanf(s
, "0x%08X:0x%08X", &rid
, &attrs
);
154 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
155 BAIL_ON_WBC_ERROR(wbc_status
);
158 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
163 for (j
=0; j
< resp
->data
.auth
.info3
.num_other_sids
; j
++) {
168 char *e
= strchr(p
, '\n');
170 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
171 BAIL_ON_WBC_ERROR(wbc_status
);
178 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
179 BAIL_ON_WBC_ERROR(wbc_status
);
184 ret
= sscanf(a
, "0x%08X",
187 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
188 BAIL_ON_WBC_ERROR(wbc_status
);
191 wbc_status
= wbcStringToSid(s
, &i
->sids
[sn
].sid
);
192 BAIL_ON_WBC_ERROR(wbc_status
);
194 i
->sids
[sn
].attributes
= attrs
;
207 static wbcErr
wbc_create_error_info(TALLOC_CTX
*mem_ctx
,
208 const struct winbindd_response
*resp
,
209 struct wbcAuthErrorInfo
**_e
)
211 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
212 struct wbcAuthErrorInfo
*e
;
214 e
= talloc(mem_ctx
, struct wbcAuthErrorInfo
);
215 BAIL_ON_PTR_ERROR(e
, wbc_status
);
217 e
->nt_status
= resp
->data
.auth
.nt_status
;
218 e
->pam_error
= resp
->data
.auth
.pam_error
;
219 e
->nt_string
= talloc_strdup(e
, resp
->data
.auth
.nt_status_string
);
220 BAIL_ON_PTR_ERROR(e
->nt_string
, wbc_status
);
222 e
->display_string
= talloc_strdup(e
, resp
->data
.auth
.error_string
);
223 BAIL_ON_PTR_ERROR(e
->display_string
, wbc_status
);
233 static wbcErr
wbc_create_password_policy_info(TALLOC_CTX
*mem_ctx
,
234 const struct winbindd_response
*resp
,
235 struct wbcUserPasswordPolicyInfo
**_i
)
237 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
238 struct wbcUserPasswordPolicyInfo
*i
;
240 i
= talloc(mem_ctx
, struct wbcUserPasswordPolicyInfo
);
241 BAIL_ON_PTR_ERROR(i
, wbc_status
);
243 i
->min_passwordage
= resp
->data
.auth
.policy
.min_passwordage
;
244 i
->min_length_password
= resp
->data
.auth
.policy
.min_length_password
;
245 i
->password_history
= resp
->data
.auth
.policy
.password_history
;
246 i
->password_properties
= resp
->data
.auth
.policy
.password_properties
;
247 i
->expire
= resp
->data
.auth
.policy
.expire
;
257 static wbcErr
wbc_create_logon_info(TALLOC_CTX
*mem_ctx
,
258 const struct winbindd_response
*resp
,
259 struct wbcLogonUserInfo
**_i
)
261 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
262 struct wbcLogonUserInfo
*i
;
264 i
= talloc_zero(mem_ctx
, struct wbcLogonUserInfo
);
265 BAIL_ON_PTR_ERROR(i
, wbc_status
);
267 wbc_status
= wbc_create_auth_info(i
, resp
, &i
->info
);
268 BAIL_ON_WBC_ERROR(wbc_status
);
270 if (resp
->data
.auth
.krb5ccname
) {
271 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
275 (uint8_t *)resp
->data
.auth
.krb5ccname
,
276 strlen(resp
->data
.auth
.krb5ccname
)+1);
277 BAIL_ON_WBC_ERROR(wbc_status
);
280 if (resp
->data
.auth
.unix_username
) {
281 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
285 (uint8_t *)resp
->data
.auth
.unix_username
,
286 strlen(resp
->data
.auth
.unix_username
)+1);
287 BAIL_ON_WBC_ERROR(wbc_status
);
293 if (!WBC_ERROR_IS_OK(wbc_status
) && i
) {
294 wbcFreeMemory(i
->blobs
);
301 /* Authenticate with more detailed information */
302 wbcErr
wbcAuthenticateUserEx(const struct wbcAuthUserParams
*params
,
303 struct wbcAuthUserInfo
**info
,
304 struct wbcAuthErrorInfo
**error
)
306 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
308 struct winbindd_request request
;
309 struct winbindd_response response
;
311 ZERO_STRUCT(request
);
312 ZERO_STRUCT(response
);
319 wbc_status
= WBC_ERR_INVALID_PARAM
;
320 BAIL_ON_WBC_ERROR(wbc_status
);
323 if (!params
->account_name
) {
324 wbc_status
= WBC_ERR_INVALID_PARAM
;
325 BAIL_ON_WBC_ERROR(wbc_status
);
328 /* Initialize request */
330 switch (params
->level
) {
331 case WBC_AUTH_USER_LEVEL_PLAIN
:
332 cmd
= WINBINDD_PAM_AUTH
;
333 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
334 WBFLAG_PAM_USER_SESSION_KEY
|
337 if (!params
->password
.plaintext
) {
338 wbc_status
= WBC_ERR_INVALID_PARAM
;
339 BAIL_ON_WBC_ERROR(wbc_status
);
342 if (params
->domain_name
&& params
->domain_name
[0]) {
343 /* We need to get the winbind separator :-( */
344 struct winbindd_response sep_response
;
346 ZERO_STRUCT(sep_response
);
348 wbc_status
= wbcRequestResponse(WINBINDD_INFO
,
349 NULL
, &sep_response
);
350 BAIL_ON_WBC_ERROR(wbc_status
);
352 snprintf(request
.data
.auth
.user
,
353 sizeof(request
.data
.auth
.user
)-1,
356 sep_response
.data
.info
.winbind_separator
,
357 params
->account_name
);
359 strncpy(request
.data
.auth
.user
,
360 params
->account_name
,
361 sizeof(request
.data
.auth
.user
)-1);
364 strncpy(request
.data
.auth
.pass
,
365 params
->password
.plaintext
,
366 sizeof(request
.data
.auth
.pass
)-1);
369 case WBC_AUTH_USER_LEVEL_HASH
:
370 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
371 BAIL_ON_WBC_ERROR(wbc_status
);
374 case WBC_AUTH_USER_LEVEL_RESPONSE
:
375 cmd
= WINBINDD_PAM_AUTH_CRAP
;
376 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
377 WBFLAG_PAM_USER_SESSION_KEY
|
380 if (params
->password
.response
.lm_length
&&
381 !params
->password
.response
.lm_data
) {
382 wbc_status
= WBC_ERR_INVALID_PARAM
;
383 BAIL_ON_WBC_ERROR(wbc_status
);
385 if (params
->password
.response
.lm_length
== 0 &&
386 params
->password
.response
.lm_data
) {
387 wbc_status
= WBC_ERR_INVALID_PARAM
;
388 BAIL_ON_WBC_ERROR(wbc_status
);
391 if (params
->password
.response
.nt_length
&&
392 !params
->password
.response
.nt_data
) {
393 wbc_status
= WBC_ERR_INVALID_PARAM
;
394 BAIL_ON_WBC_ERROR(wbc_status
);
396 if (params
->password
.response
.nt_length
== 0&&
397 params
->password
.response
.nt_data
) {
398 wbc_status
= WBC_ERR_INVALID_PARAM
;
399 BAIL_ON_WBC_ERROR(wbc_status
);
402 strncpy(request
.data
.auth_crap
.user
,
403 params
->account_name
,
404 sizeof(request
.data
.auth_crap
.user
)-1);
405 if (params
->domain_name
) {
406 strncpy(request
.data
.auth_crap
.domain
,
408 sizeof(request
.data
.auth_crap
.domain
)-1);
410 if (params
->workstation_name
) {
411 strncpy(request
.data
.auth_crap
.workstation
,
412 params
->workstation_name
,
413 sizeof(request
.data
.auth_crap
.workstation
)-1);
416 request
.data
.auth_crap
.logon_parameters
=
417 params
->parameter_control
;
419 memcpy(request
.data
.auth_crap
.chal
,
420 params
->password
.response
.challenge
,
421 sizeof(request
.data
.auth_crap
.chal
));
423 request
.data
.auth_crap
.lm_resp_len
=
424 MIN(params
->password
.response
.lm_length
,
425 sizeof(request
.data
.auth_crap
.lm_resp
));
426 request
.data
.auth_crap
.nt_resp_len
=
427 MIN(params
->password
.response
.nt_length
,
428 sizeof(request
.data
.auth_crap
.nt_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 if (params
->password
.response
.nt_data
) {
435 memcpy(request
.data
.auth_crap
.nt_resp
,
436 params
->password
.response
.nt_data
,
437 request
.data
.auth_crap
.nt_resp_len
);
445 wbc_status
= WBC_ERR_INVALID_PARAM
;
446 BAIL_ON_WBC_ERROR(wbc_status
);
450 request
.flags
|= params
->flags
;
453 wbc_status
= wbcRequestResponse(cmd
,
456 if (response
.data
.auth
.nt_status
!= 0) {
458 wbc_status
= wbc_create_error_info(NULL
,
461 BAIL_ON_WBC_ERROR(wbc_status
);
464 wbc_status
= WBC_ERR_AUTH_ERROR
;
465 BAIL_ON_WBC_ERROR(wbc_status
);
467 BAIL_ON_WBC_ERROR(wbc_status
);
470 wbc_status
= wbc_create_auth_info(NULL
,
473 BAIL_ON_WBC_ERROR(wbc_status
);
477 if (response
.extra_data
.data
)
478 free(response
.extra_data
.data
);
483 /* Trigger a verification of the trust credentials of a specific domain */
484 wbcErr
wbcCheckTrustCredentials(const char *domain
,
485 struct wbcAuthErrorInfo
**error
)
487 struct winbindd_request request
;
488 struct winbindd_response response
;
489 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
493 * the current protocol doesn't support
494 * specifying a domain
496 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
497 BAIL_ON_WBC_ERROR(wbc_status
);
500 ZERO_STRUCT(request
);
501 ZERO_STRUCT(response
);
505 wbc_status
= wbcRequestResponse(WINBINDD_CHECK_MACHACC
,
508 if (response
.data
.auth
.nt_status
!= 0) {
510 wbc_status
= wbc_create_error_info(NULL
,
513 BAIL_ON_WBC_ERROR(wbc_status
);
516 wbc_status
= WBC_ERR_AUTH_ERROR
;
517 BAIL_ON_WBC_ERROR(wbc_status
);
519 BAIL_ON_WBC_ERROR(wbc_status
);
525 /* Trigger an extended logoff notification to Winbind for a specific user */
526 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
527 struct wbcAuthErrorInfo
**error
)
529 struct winbindd_request request
;
530 struct winbindd_response response
;
531 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
536 if (!params
|| !params
->username
) {
537 wbc_status
= WBC_ERR_INVALID_PARAM
;
538 BAIL_ON_WBC_ERROR(wbc_status
);
541 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
542 wbc_status
= WBC_ERR_INVALID_PARAM
;
543 BAIL_ON_WBC_ERROR(wbc_status
);
545 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
546 wbc_status
= WBC_ERR_INVALID_PARAM
;
547 BAIL_ON_WBC_ERROR(wbc_status
);
550 ZERO_STRUCT(request
);
551 ZERO_STRUCT(response
);
553 strncpy(request
.data
.logoff
.user
, params
->username
,
554 sizeof(request
.data
.logoff
.user
)-1);
556 for (i
=0; i
<params
->num_blobs
; i
++) {
558 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
559 if (params
->blobs
[i
].blob
.data
) {
560 strncpy(request
.data
.logoff
.krb5ccname
,
561 (const char *)params
->blobs
[i
].blob
.data
,
562 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
567 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
568 if (params
->blobs
[i
].blob
.data
) {
569 memcpy(&request
.data
.logoff
.uid
,
570 params
->blobs
[i
].blob
.data
,
571 MIN(params
->blobs
[i
].blob
.length
,
572 sizeof(request
.data
.logoff
.uid
)));
577 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
578 if (params
->blobs
[i
].blob
.data
) {
579 memcpy(&request
.flags
,
580 params
->blobs
[i
].blob
.data
,
581 MIN(params
->blobs
[i
].blob
.length
,
582 sizeof(request
.flags
)));
590 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
594 /* Take the response above and return it to the caller */
595 if (response
.data
.auth
.nt_status
!= 0) {
597 wbc_status
= wbc_create_error_info(NULL
,
600 BAIL_ON_WBC_ERROR(wbc_status
);
603 wbc_status
= WBC_ERR_AUTH_ERROR
;
604 BAIL_ON_WBC_ERROR(wbc_status
);
606 BAIL_ON_WBC_ERROR(wbc_status
);
612 /* Trigger a logoff notification to Winbind for a specific user */
613 wbcErr
wbcLogoffUser(const char *username
,
615 const char *ccfilename
)
617 struct winbindd_request request
;
618 struct winbindd_response response
;
619 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
624 wbc_status
= WBC_ERR_INVALID_PARAM
;
625 BAIL_ON_WBC_ERROR(wbc_status
);
628 ZERO_STRUCT(request
);
629 ZERO_STRUCT(response
);
631 strncpy(request
.data
.logoff
.user
, username
,
632 sizeof(request
.data
.logoff
.user
)-1);
633 request
.data
.logoff
.uid
= uid
;
636 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
637 sizeof(request
.data
.logoff
.krb5ccname
)-1);
642 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
646 /* Take the response above and return it to the caller */
652 /* Change a password for a user with more detailed information upon failure */
653 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
654 struct wbcAuthErrorInfo
**error
,
655 enum wbcPasswordChangeRejectReason
*reject_reason
,
656 struct wbcUserPasswordPolicyInfo
**policy
)
658 struct winbindd_request request
;
659 struct winbindd_response response
;
660 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
665 if (!params
->account_name
) {
666 wbc_status
= WBC_ERR_INVALID_PARAM
;
667 BAIL_ON_WBC_ERROR(wbc_status
);
682 ZERO_STRUCT(request
);
683 ZERO_STRUCT(response
);
685 switch (params
->level
) {
686 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
687 cmd
= WINBINDD_PAM_CHAUTHTOK
;
689 if (!params
->account_name
) {
690 wbc_status
= WBC_ERR_INVALID_PARAM
;
691 BAIL_ON_WBC_ERROR(wbc_status
);
694 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
695 sizeof(request
.data
.chauthtok
.user
) - 1);
697 if (params
->old_password
.plaintext
) {
698 strncpy(request
.data
.chauthtok
.oldpass
,
699 params
->old_password
.plaintext
,
700 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
703 if (params
->new_password
.plaintext
) {
704 strncpy(request
.data
.chauthtok
.newpass
,
705 params
->new_password
.plaintext
,
706 sizeof(request
.data
.chauthtok
.newpass
) - 1);
710 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
711 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
713 if (!params
->account_name
|| !params
->domain_name
) {
714 wbc_status
= WBC_ERR_INVALID_PARAM
;
715 BAIL_ON_WBC_ERROR(wbc_status
);
718 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
719 !params
->old_password
.response
.old_lm_hash_enc_data
) {
720 wbc_status
= WBC_ERR_INVALID_PARAM
;
721 BAIL_ON_WBC_ERROR(wbc_status
);
724 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
725 params
->old_password
.response
.old_lm_hash_enc_data
) {
726 wbc_status
= WBC_ERR_INVALID_PARAM
;
727 BAIL_ON_WBC_ERROR(wbc_status
);
730 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
731 !params
->old_password
.response
.old_nt_hash_enc_data
) {
732 wbc_status
= WBC_ERR_INVALID_PARAM
;
733 BAIL_ON_WBC_ERROR(wbc_status
);
736 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
737 params
->old_password
.response
.old_nt_hash_enc_data
) {
738 wbc_status
= WBC_ERR_INVALID_PARAM
;
739 BAIL_ON_WBC_ERROR(wbc_status
);
742 if (params
->new_password
.response
.lm_length
&&
743 !params
->new_password
.response
.lm_data
) {
744 wbc_status
= WBC_ERR_INVALID_PARAM
;
745 BAIL_ON_WBC_ERROR(wbc_status
);
748 if (params
->new_password
.response
.lm_length
== 0 &&
749 params
->new_password
.response
.lm_data
) {
750 wbc_status
= WBC_ERR_INVALID_PARAM
;
751 BAIL_ON_WBC_ERROR(wbc_status
);
754 if (params
->new_password
.response
.nt_length
&&
755 !params
->new_password
.response
.nt_data
) {
756 wbc_status
= WBC_ERR_INVALID_PARAM
;
757 BAIL_ON_WBC_ERROR(wbc_status
);
760 if (params
->new_password
.response
.nt_length
== 0 &&
761 params
->new_password
.response
.nt_data
) {
762 wbc_status
= WBC_ERR_INVALID_PARAM
;
763 BAIL_ON_WBC_ERROR(wbc_status
);
766 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
767 params
->account_name
,
768 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
770 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
772 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
774 if (params
->new_password
.response
.nt_data
) {
775 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
776 params
->new_password
.response
.nt_data
,
777 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
778 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
779 params
->new_password
.response
.nt_length
;
782 if (params
->new_password
.response
.lm_data
) {
783 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
784 params
->new_password
.response
.lm_data
,
785 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
786 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
787 params
->new_password
.response
.lm_length
;
790 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
791 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
792 params
->old_password
.response
.old_nt_hash_enc_data
,
793 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
794 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
795 params
->old_password
.response
.old_nt_hash_enc_length
;
798 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
799 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
800 params
->old_password
.response
.old_lm_hash_enc_data
,
801 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
802 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
803 params
->old_password
.response
.old_lm_hash_enc_length
;
808 wbc_status
= WBC_ERR_INVALID_PARAM
;
809 BAIL_ON_WBC_ERROR(wbc_status
);
814 wbc_status
= WBC_ERR_INVALID_PARAM
;
815 BAIL_ON_WBC_ERROR(wbc_status
);
820 wbc_status
= wbcRequestResponse(cmd
,
823 if (WBC_ERROR_IS_OK(wbc_status
)) {
827 /* Take the response above and return it to the caller */
829 if (response
.data
.auth
.nt_status
!= 0) {
831 wbc_status
= wbc_create_error_info(NULL
,
834 BAIL_ON_WBC_ERROR(wbc_status
);
840 wbc_status
= wbc_create_password_policy_info(NULL
,
843 BAIL_ON_WBC_ERROR(wbc_status
);
847 *reject_reason
= response
.data
.auth
.reject_reason
;
850 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
851 BAIL_ON_WBC_ERROR(wbc_status
);
857 /* Change a password for a user */
858 wbcErr
wbcChangeUserPassword(const char *username
,
859 const char *old_password
,
860 const char *new_password
)
862 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
863 struct wbcChangePasswordParams params
;
867 params
.account_name
= username
;
868 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
869 params
.old_password
.plaintext
= old_password
;
870 params
.new_password
.plaintext
= new_password
;
872 wbc_status
= wbcChangeUserPasswordEx(¶ms
,
876 BAIL_ON_WBC_ERROR(wbc_status
);
883 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
884 struct wbcLogonUserInfo
**info
,
885 struct wbcAuthErrorInfo
**error
,
886 struct wbcUserPasswordPolicyInfo
**policy
)
888 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
890 struct winbindd_request request
;
891 struct winbindd_response response
;
894 ZERO_STRUCT(request
);
895 ZERO_STRUCT(response
);
908 wbc_status
= WBC_ERR_INVALID_PARAM
;
909 BAIL_ON_WBC_ERROR(wbc_status
);
912 if (!params
->username
) {
913 wbc_status
= WBC_ERR_INVALID_PARAM
;
914 BAIL_ON_WBC_ERROR(wbc_status
);
917 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
918 wbc_status
= WBC_ERR_INVALID_PARAM
;
919 BAIL_ON_WBC_ERROR(wbc_status
);
921 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
922 wbc_status
= WBC_ERR_INVALID_PARAM
;
923 BAIL_ON_WBC_ERROR(wbc_status
);
926 /* Initialize request */
928 cmd
= WINBINDD_PAM_AUTH
;
929 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
930 WBFLAG_PAM_USER_SESSION_KEY
|
933 if (!params
->password
) {
934 wbc_status
= WBC_ERR_INVALID_PARAM
;
935 BAIL_ON_WBC_ERROR(wbc_status
);
938 strncpy(request
.data
.auth
.user
,
940 sizeof(request
.data
.auth
.user
)-1);
942 strncpy(request
.data
.auth
.pass
,
944 sizeof(request
.data
.auth
.pass
)-1);
946 for (i
=0; i
<params
->num_blobs
; i
++) {
948 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
949 if (params
->blobs
[i
].blob
.data
) {
950 strncpy(request
.data
.auth
.krb5_cc_type
,
951 (const char *)params
->blobs
[i
].blob
.data
,
952 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
957 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
958 if (params
->blobs
[i
].blob
.data
) {
959 memcpy(&request
.data
.auth
.uid
,
960 params
->blobs
[i
].blob
.data
,
961 MIN(sizeof(request
.data
.auth
.uid
),
962 params
->blobs
[i
].blob
.length
));
967 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
968 if (params
->blobs
[i
].blob
.data
) {
971 params
->blobs
[i
].blob
.data
,
973 params
->blobs
[i
].blob
.length
));
974 request
.flags
|= flags
;
979 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
980 if (params
->blobs
[i
].blob
.data
&&
981 params
->blobs
[i
].blob
.data
[0] > 0) {
982 strncpy(request
.data
.auth
.require_membership_of_sid
,
983 (const char *)params
->blobs
[i
].blob
.data
,
984 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
990 wbc_status
= wbcRequestResponse(cmd
,
994 if (response
.data
.auth
.nt_status
!= 0) {
996 wbc_status
= wbc_create_error_info(NULL
,
999 BAIL_ON_WBC_ERROR(wbc_status
);
1002 wbc_status
= WBC_ERR_AUTH_ERROR
;
1003 BAIL_ON_WBC_ERROR(wbc_status
);
1005 BAIL_ON_WBC_ERROR(wbc_status
);
1008 wbc_status
= wbc_create_logon_info(NULL
,
1011 BAIL_ON_WBC_ERROR(wbc_status
);
1015 wbc_status
= wbc_create_password_policy_info(NULL
,
1018 BAIL_ON_WBC_ERROR(wbc_status
);
1022 if (response
.extra_data
.data
)
1023 free(response
.extra_data
.data
);
1028 /* Authenticate a user with cached credentials */
1029 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1030 struct wbcCredentialCacheInfo
**info
,
1031 struct wbcAuthErrorInfo
**error
)
1033 return WBC_ERR_NOT_IMPLEMENTED
;