2 Unix SMB/CIFS implementation.
6 Copyright (C) Gerald (Jerry) Carter 2007
7 Copyright (C) Guenther Deschner 2008
8 Copyright (C) Volker Lendecke 2009
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /* Required Headers */
27 #include "libwbclient.h"
29 /* Authenticate a username/password pair */
30 wbcErr
wbcAuthenticateUser(const char *username
,
33 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
34 struct wbcAuthUserParams params
;
38 params
.account_name
= username
;
39 params
.level
= WBC_AUTH_USER_LEVEL_PLAIN
;
40 params
.password
.plaintext
= password
;
42 wbc_status
= wbcAuthenticateUserEx(¶ms
, NULL
, NULL
);
43 BAIL_ON_WBC_ERROR(wbc_status
);
49 static wbcErr
wbc_create_auth_info(TALLOC_CTX
*mem_ctx
,
50 const struct winbindd_response
*resp
,
51 struct wbcAuthUserInfo
**_i
)
53 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
54 struct wbcAuthUserInfo
*i
;
55 struct wbcDomainSid domain_sid
;
60 i
= talloc(mem_ctx
, struct wbcAuthUserInfo
);
61 BAIL_ON_PTR_ERROR(i
, wbc_status
);
63 i
->user_flags
= resp
->data
.auth
.info3
.user_flgs
;
65 i
->account_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.user_name
);
66 BAIL_ON_PTR_ERROR(i
->account_name
, wbc_status
);
67 i
->user_principal
= NULL
;
68 i
->full_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.full_name
);
69 BAIL_ON_PTR_ERROR(i
->full_name
, wbc_status
);
70 i
->domain_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_dom
);
71 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
72 i
->dns_domain_name
= NULL
;
74 i
->acct_flags
= resp
->data
.auth
.info3
.acct_flags
;
75 memcpy(i
->user_session_key
,
76 resp
->data
.auth
.user_session_key
,
77 sizeof(i
->user_session_key
));
78 memcpy(i
->lm_session_key
,
79 resp
->data
.auth
.first_8_lm_hash
,
80 sizeof(i
->lm_session_key
));
82 i
->logon_count
= resp
->data
.auth
.info3
.logon_count
;
83 i
->bad_password_count
= resp
->data
.auth
.info3
.bad_pw_count
;
85 i
->logon_time
= resp
->data
.auth
.info3
.logon_time
;
86 i
->logoff_time
= resp
->data
.auth
.info3
.logoff_time
;
87 i
->kickoff_time
= resp
->data
.auth
.info3
.kickoff_time
;
88 i
->pass_last_set_time
= resp
->data
.auth
.info3
.pass_last_set_time
;
89 i
->pass_can_change_time
= resp
->data
.auth
.info3
.pass_can_change_time
;
90 i
->pass_must_change_time
= resp
->data
.auth
.info3
.pass_must_change_time
;
92 i
->logon_server
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_srv
);
93 BAIL_ON_PTR_ERROR(i
->logon_server
, wbc_status
);
94 i
->logon_script
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_script
);
95 BAIL_ON_PTR_ERROR(i
->logon_script
, wbc_status
);
96 i
->profile_path
= talloc_strdup(i
, resp
->data
.auth
.info3
.profile_path
);
97 BAIL_ON_PTR_ERROR(i
->profile_path
, wbc_status
);
98 i
->home_directory
= talloc_strdup(i
, resp
->data
.auth
.info3
.home_dir
);
99 BAIL_ON_PTR_ERROR(i
->home_directory
, wbc_status
);
100 i
->home_drive
= talloc_strdup(i
, resp
->data
.auth
.info3
.dir_drive
);
101 BAIL_ON_PTR_ERROR(i
->home_drive
, wbc_status
);
104 i
->num_sids
+= resp
->data
.auth
.info3
.num_groups
;
105 i
->num_sids
+= resp
->data
.auth
.info3
.num_other_sids
;
107 i
->sids
= talloc_array(i
, struct wbcSidWithAttr
, i
->num_sids
);
108 BAIL_ON_PTR_ERROR(i
->sids
, wbc_status
);
110 wbc_status
= wbcStringToSid(resp
->data
.auth
.info3
.dom_sid
,
112 BAIL_ON_WBC_ERROR(wbc_status
);
114 #define _SID_COMPOSE(s, d, r, a) { \
116 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
117 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
119 wbc_status = WBC_ERR_INVALID_SID; \
120 BAIL_ON_WBC_ERROR(wbc_status); \
122 (s).attributes = a; \
126 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
127 resp
->data
.auth
.info3
.user_rid
,
130 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
131 resp
->data
.auth
.info3
.group_rid
,
135 p
= (char *)resp
->extra_data
.data
;
137 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
138 BAIL_ON_WBC_ERROR(wbc_status
);
141 for (j
=0; j
< resp
->data
.auth
.info3
.num_groups
; j
++) {
146 char *e
= strchr(p
, '\n');
148 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
149 BAIL_ON_WBC_ERROR(wbc_status
);
154 ret
= sscanf(s
, "0x%08X:0x%08X", &rid
, &attrs
);
156 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
157 BAIL_ON_WBC_ERROR(wbc_status
);
160 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
165 for (j
=0; j
< resp
->data
.auth
.info3
.num_other_sids
; j
++) {
170 char *e
= strchr(p
, '\n');
172 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
173 BAIL_ON_WBC_ERROR(wbc_status
);
180 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
181 BAIL_ON_WBC_ERROR(wbc_status
);
186 ret
= sscanf(a
, "0x%08X",
189 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
190 BAIL_ON_WBC_ERROR(wbc_status
);
193 wbc_status
= wbcStringToSid(s
, &i
->sids
[sn
].sid
);
194 BAIL_ON_WBC_ERROR(wbc_status
);
196 i
->sids
[sn
].attributes
= attrs
;
209 static wbcErr
wbc_create_error_info(TALLOC_CTX
*mem_ctx
,
210 const struct winbindd_response
*resp
,
211 struct wbcAuthErrorInfo
**_e
)
213 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
214 struct wbcAuthErrorInfo
*e
;
216 e
= talloc(mem_ctx
, struct wbcAuthErrorInfo
);
217 BAIL_ON_PTR_ERROR(e
, wbc_status
);
219 e
->nt_status
= resp
->data
.auth
.nt_status
;
220 e
->pam_error
= resp
->data
.auth
.pam_error
;
221 e
->nt_string
= talloc_strdup(e
, resp
->data
.auth
.nt_status_string
);
222 BAIL_ON_PTR_ERROR(e
->nt_string
, wbc_status
);
224 e
->display_string
= talloc_strdup(e
, resp
->data
.auth
.error_string
);
225 BAIL_ON_PTR_ERROR(e
->display_string
, wbc_status
);
235 static wbcErr
wbc_create_password_policy_info(TALLOC_CTX
*mem_ctx
,
236 const struct winbindd_response
*resp
,
237 struct wbcUserPasswordPolicyInfo
**_i
)
239 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
240 struct wbcUserPasswordPolicyInfo
*i
;
242 i
= talloc(mem_ctx
, struct wbcUserPasswordPolicyInfo
);
243 BAIL_ON_PTR_ERROR(i
, wbc_status
);
245 i
->min_passwordage
= resp
->data
.auth
.policy
.min_passwordage
;
246 i
->min_length_password
= resp
->data
.auth
.policy
.min_length_password
;
247 i
->password_history
= resp
->data
.auth
.policy
.password_history
;
248 i
->password_properties
= resp
->data
.auth
.policy
.password_properties
;
249 i
->expire
= resp
->data
.auth
.policy
.expire
;
259 static wbcErr
wbc_create_logon_info(TALLOC_CTX
*mem_ctx
,
260 struct winbindd_response
*resp
,
261 struct wbcLogonUserInfo
**_i
)
263 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
264 struct wbcLogonUserInfo
*i
;
266 i
= talloc_zero(mem_ctx
, struct wbcLogonUserInfo
);
267 BAIL_ON_PTR_ERROR(i
, wbc_status
);
269 wbc_status
= wbc_create_auth_info(i
, resp
, &i
->info
);
270 BAIL_ON_WBC_ERROR(wbc_status
);
272 if (resp
->data
.auth
.krb5ccname
&&
273 strlen(resp
->data
.auth
.krb5ccname
)) {
274 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
278 (uint8_t *)resp
->data
.auth
.krb5ccname
,
279 strlen(resp
->data
.auth
.krb5ccname
)+1);
280 BAIL_ON_WBC_ERROR(wbc_status
);
283 if (resp
->data
.auth
.unix_username
&&
284 strlen(resp
->data
.auth
.unix_username
)) {
285 wbc_status
= wbcAddNamedBlob(&i
->num_blobs
,
289 (uint8_t *)resp
->data
.auth
.unix_username
,
290 strlen(resp
->data
.auth
.unix_username
)+1);
291 BAIL_ON_WBC_ERROR(wbc_status
);
297 if (!WBC_ERROR_IS_OK(wbc_status
) && i
) {
298 wbcFreeMemory(i
->blobs
);
305 /* Authenticate with more detailed information */
306 wbcErr
wbcAuthenticateUserEx(const struct wbcAuthUserParams
*params
,
307 struct wbcAuthUserInfo
**info
,
308 struct wbcAuthErrorInfo
**error
)
310 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
312 struct winbindd_request request
;
313 struct winbindd_response response
;
315 ZERO_STRUCT(request
);
316 ZERO_STRUCT(response
);
323 wbc_status
= WBC_ERR_INVALID_PARAM
;
324 BAIL_ON_WBC_ERROR(wbc_status
);
327 if (!params
->account_name
) {
328 wbc_status
= WBC_ERR_INVALID_PARAM
;
329 BAIL_ON_WBC_ERROR(wbc_status
);
332 /* Initialize request */
334 switch (params
->level
) {
335 case WBC_AUTH_USER_LEVEL_PLAIN
:
336 cmd
= WINBINDD_PAM_AUTH
;
337 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
338 WBFLAG_PAM_USER_SESSION_KEY
|
341 if (!params
->password
.plaintext
) {
342 wbc_status
= WBC_ERR_INVALID_PARAM
;
343 BAIL_ON_WBC_ERROR(wbc_status
);
346 if (params
->domain_name
&& params
->domain_name
[0]) {
347 /* We need to get the winbind separator :-( */
348 struct winbindd_response sep_response
;
350 ZERO_STRUCT(sep_response
);
352 wbc_status
= wbcRequestResponse(WINBINDD_INFO
,
353 NULL
, &sep_response
);
354 BAIL_ON_WBC_ERROR(wbc_status
);
356 snprintf(request
.data
.auth
.user
,
357 sizeof(request
.data
.auth
.user
)-1,
360 sep_response
.data
.info
.winbind_separator
,
361 params
->account_name
);
363 strncpy(request
.data
.auth
.user
,
364 params
->account_name
,
365 sizeof(request
.data
.auth
.user
)-1);
368 strncpy(request
.data
.auth
.pass
,
369 params
->password
.plaintext
,
370 sizeof(request
.data
.auth
.pass
)-1);
373 case WBC_AUTH_USER_LEVEL_HASH
:
374 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
375 BAIL_ON_WBC_ERROR(wbc_status
);
378 case WBC_AUTH_USER_LEVEL_RESPONSE
:
379 cmd
= WINBINDD_PAM_AUTH_CRAP
;
380 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
381 WBFLAG_PAM_USER_SESSION_KEY
|
384 if (params
->password
.response
.lm_length
&&
385 !params
->password
.response
.lm_data
) {
386 wbc_status
= WBC_ERR_INVALID_PARAM
;
387 BAIL_ON_WBC_ERROR(wbc_status
);
389 if (params
->password
.response
.lm_length
== 0 &&
390 params
->password
.response
.lm_data
) {
391 wbc_status
= WBC_ERR_INVALID_PARAM
;
392 BAIL_ON_WBC_ERROR(wbc_status
);
395 if (params
->password
.response
.nt_length
&&
396 !params
->password
.response
.nt_data
) {
397 wbc_status
= WBC_ERR_INVALID_PARAM
;
398 BAIL_ON_WBC_ERROR(wbc_status
);
400 if (params
->password
.response
.nt_length
== 0&&
401 params
->password
.response
.nt_data
) {
402 wbc_status
= WBC_ERR_INVALID_PARAM
;
403 BAIL_ON_WBC_ERROR(wbc_status
);
406 strncpy(request
.data
.auth_crap
.user
,
407 params
->account_name
,
408 sizeof(request
.data
.auth_crap
.user
)-1);
409 if (params
->domain_name
) {
410 strncpy(request
.data
.auth_crap
.domain
,
412 sizeof(request
.data
.auth_crap
.domain
)-1);
414 if (params
->workstation_name
) {
415 strncpy(request
.data
.auth_crap
.workstation
,
416 params
->workstation_name
,
417 sizeof(request
.data
.auth_crap
.workstation
)-1);
420 request
.data
.auth_crap
.logon_parameters
=
421 params
->parameter_control
;
423 memcpy(request
.data
.auth_crap
.chal
,
424 params
->password
.response
.challenge
,
425 sizeof(request
.data
.auth_crap
.chal
));
427 request
.data
.auth_crap
.lm_resp_len
=
428 MIN(params
->password
.response
.lm_length
,
429 sizeof(request
.data
.auth_crap
.lm_resp
));
430 if (params
->password
.response
.lm_data
) {
431 memcpy(request
.data
.auth_crap
.lm_resp
,
432 params
->password
.response
.lm_data
,
433 request
.data
.auth_crap
.lm_resp_len
);
435 request
.data
.auth_crap
.nt_resp_len
= params
->password
.response
.nt_length
;
436 if (params
->password
.response
.nt_length
> sizeof(request
.data
.auth_crap
.nt_resp
)) {
437 request
.flags
|= WBFLAG_BIG_NTLMV2_BLOB
;
438 request
.extra_len
= params
->password
.response
.nt_length
;
439 request
.extra_data
.data
= talloc_zero_array(NULL
, char, request
.extra_len
);
440 if (request
.extra_data
.data
== NULL
) {
441 wbc_status
= WBC_ERR_NO_MEMORY
;
442 BAIL_ON_WBC_ERROR(wbc_status
);
444 memcpy(request
.extra_data
.data
,
445 params
->password
.response
.nt_data
,
446 request
.data
.auth_crap
.nt_resp_len
);
447 } else if (params
->password
.response
.nt_data
) {
448 memcpy(request
.data
.auth_crap
.nt_resp
,
449 params
->password
.response
.nt_data
,
450 request
.data
.auth_crap
.nt_resp_len
);
458 wbc_status
= WBC_ERR_INVALID_PARAM
;
459 BAIL_ON_WBC_ERROR(wbc_status
);
463 request
.flags
|= params
->flags
;
466 if (cmd
== WINBINDD_PAM_AUTH_CRAP
) {
467 wbc_status
= wbcRequestResponsePriv(cmd
, &request
, &response
);
469 wbc_status
= wbcRequestResponse(cmd
, &request
, &response
);
471 if (response
.data
.auth
.nt_status
!= 0) {
473 wbc_status
= wbc_create_error_info(NULL
,
476 BAIL_ON_WBC_ERROR(wbc_status
);
479 wbc_status
= WBC_ERR_AUTH_ERROR
;
480 BAIL_ON_WBC_ERROR(wbc_status
);
482 BAIL_ON_WBC_ERROR(wbc_status
);
485 wbc_status
= wbc_create_auth_info(NULL
,
488 BAIL_ON_WBC_ERROR(wbc_status
);
492 if (response
.extra_data
.data
)
493 free(response
.extra_data
.data
);
495 talloc_free(request
.extra_data
.data
);
500 /* Trigger a verification of the trust credentials of a specific domain */
501 wbcErr
wbcCheckTrustCredentials(const char *domain
,
502 struct wbcAuthErrorInfo
**error
)
504 struct winbindd_request request
;
505 struct winbindd_response response
;
506 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
508 ZERO_STRUCT(request
);
509 ZERO_STRUCT(response
);
512 strncpy(request
.domain_name
, domain
,
513 sizeof(request
.domain_name
)-1);
518 wbc_status
= wbcRequestResponsePriv(WINBINDD_CHECK_MACHACC
,
519 &request
, &response
);
520 if (response
.data
.auth
.nt_status
!= 0) {
522 wbc_status
= wbc_create_error_info(NULL
,
525 BAIL_ON_WBC_ERROR(wbc_status
);
528 wbc_status
= WBC_ERR_AUTH_ERROR
;
529 BAIL_ON_WBC_ERROR(wbc_status
);
531 BAIL_ON_WBC_ERROR(wbc_status
);
537 /* Trigger a change of the trust credentials for a specific domain */
538 wbcErr
wbcChangeTrustCredentials(const char *domain
,
539 struct wbcAuthErrorInfo
**error
)
541 struct winbindd_request request
;
542 struct winbindd_response response
;
543 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
545 ZERO_STRUCT(request
);
546 ZERO_STRUCT(response
);
549 strncpy(request
.domain_name
, domain
,
550 sizeof(request
.domain_name
)-1);
555 wbc_status
= wbcRequestResponsePriv(WINBINDD_CHANGE_MACHACC
,
556 &request
, &response
);
557 if (response
.data
.auth
.nt_status
!= 0) {
559 wbc_status
= wbc_create_error_info(NULL
,
562 BAIL_ON_WBC_ERROR(wbc_status
);
565 wbc_status
= WBC_ERR_AUTH_ERROR
;
566 BAIL_ON_WBC_ERROR(wbc_status
);
568 BAIL_ON_WBC_ERROR(wbc_status
);
575 * Trigger a no-op NETLOGON call. Lightweight version of
576 * wbcCheckTrustCredentials
578 wbcErr
wbcPingDc(const char *domain
, struct wbcAuthErrorInfo
**error
)
580 struct winbindd_request request
;
581 struct winbindd_response response
;
582 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
586 * the current protocol doesn't support
587 * specifying a domain
589 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
590 BAIL_ON_WBC_ERROR(wbc_status
);
593 ZERO_STRUCT(request
);
594 ZERO_STRUCT(response
);
598 wbc_status
= wbcRequestResponse(WINBINDD_PING_DC
,
601 if (response
.data
.auth
.nt_status
!= 0) {
603 wbc_status
= wbc_create_error_info(NULL
,
606 BAIL_ON_WBC_ERROR(wbc_status
);
609 wbc_status
= WBC_ERR_AUTH_ERROR
;
610 BAIL_ON_WBC_ERROR(wbc_status
);
612 BAIL_ON_WBC_ERROR(wbc_status
);
618 /* Trigger an extended logoff notification to Winbind for a specific user */
619 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
620 struct wbcAuthErrorInfo
**error
)
622 struct winbindd_request request
;
623 struct winbindd_response response
;
624 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
629 if (!params
|| !params
->username
) {
630 wbc_status
= WBC_ERR_INVALID_PARAM
;
631 BAIL_ON_WBC_ERROR(wbc_status
);
634 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
635 wbc_status
= WBC_ERR_INVALID_PARAM
;
636 BAIL_ON_WBC_ERROR(wbc_status
);
638 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
639 wbc_status
= WBC_ERR_INVALID_PARAM
;
640 BAIL_ON_WBC_ERROR(wbc_status
);
643 ZERO_STRUCT(request
);
644 ZERO_STRUCT(response
);
646 strncpy(request
.data
.logoff
.user
, params
->username
,
647 sizeof(request
.data
.logoff
.user
)-1);
649 for (i
=0; i
<params
->num_blobs
; i
++) {
651 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
652 if (params
->blobs
[i
].blob
.data
) {
653 strncpy(request
.data
.logoff
.krb5ccname
,
654 (const char *)params
->blobs
[i
].blob
.data
,
655 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
660 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
661 if (params
->blobs
[i
].blob
.data
) {
662 memcpy(&request
.data
.logoff
.uid
,
663 params
->blobs
[i
].blob
.data
,
664 MIN(params
->blobs
[i
].blob
.length
,
665 sizeof(request
.data
.logoff
.uid
)));
670 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
671 if (params
->blobs
[i
].blob
.data
) {
672 memcpy(&request
.flags
,
673 params
->blobs
[i
].blob
.data
,
674 MIN(params
->blobs
[i
].blob
.length
,
675 sizeof(request
.flags
)));
683 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
687 /* Take the response above and return it to the caller */
688 if (response
.data
.auth
.nt_status
!= 0) {
690 wbc_status
= wbc_create_error_info(NULL
,
693 BAIL_ON_WBC_ERROR(wbc_status
);
696 wbc_status
= WBC_ERR_AUTH_ERROR
;
697 BAIL_ON_WBC_ERROR(wbc_status
);
699 BAIL_ON_WBC_ERROR(wbc_status
);
705 /* Trigger a logoff notification to Winbind for a specific user */
706 wbcErr
wbcLogoffUser(const char *username
,
708 const char *ccfilename
)
710 struct winbindd_request request
;
711 struct winbindd_response response
;
712 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
717 wbc_status
= WBC_ERR_INVALID_PARAM
;
718 BAIL_ON_WBC_ERROR(wbc_status
);
721 ZERO_STRUCT(request
);
722 ZERO_STRUCT(response
);
724 strncpy(request
.data
.logoff
.user
, username
,
725 sizeof(request
.data
.logoff
.user
)-1);
726 request
.data
.logoff
.uid
= uid
;
729 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
730 sizeof(request
.data
.logoff
.krb5ccname
)-1);
735 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
739 /* Take the response above and return it to the caller */
745 /* Change a password for a user with more detailed information upon failure */
746 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
747 struct wbcAuthErrorInfo
**error
,
748 enum wbcPasswordChangeRejectReason
*reject_reason
,
749 struct wbcUserPasswordPolicyInfo
**policy
)
751 struct winbindd_request request
;
752 struct winbindd_response response
;
753 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
758 if (!params
->account_name
) {
759 wbc_status
= WBC_ERR_INVALID_PARAM
;
760 BAIL_ON_WBC_ERROR(wbc_status
);
775 ZERO_STRUCT(request
);
776 ZERO_STRUCT(response
);
778 switch (params
->level
) {
779 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
780 cmd
= WINBINDD_PAM_CHAUTHTOK
;
782 if (!params
->account_name
) {
783 wbc_status
= WBC_ERR_INVALID_PARAM
;
784 BAIL_ON_WBC_ERROR(wbc_status
);
787 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
788 sizeof(request
.data
.chauthtok
.user
) - 1);
790 if (params
->old_password
.plaintext
) {
791 strncpy(request
.data
.chauthtok
.oldpass
,
792 params
->old_password
.plaintext
,
793 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
796 if (params
->new_password
.plaintext
) {
797 strncpy(request
.data
.chauthtok
.newpass
,
798 params
->new_password
.plaintext
,
799 sizeof(request
.data
.chauthtok
.newpass
) - 1);
803 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
804 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
806 if (!params
->account_name
|| !params
->domain_name
) {
807 wbc_status
= WBC_ERR_INVALID_PARAM
;
808 BAIL_ON_WBC_ERROR(wbc_status
);
811 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
812 !params
->old_password
.response
.old_lm_hash_enc_data
) {
813 wbc_status
= WBC_ERR_INVALID_PARAM
;
814 BAIL_ON_WBC_ERROR(wbc_status
);
817 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
818 params
->old_password
.response
.old_lm_hash_enc_data
) {
819 wbc_status
= WBC_ERR_INVALID_PARAM
;
820 BAIL_ON_WBC_ERROR(wbc_status
);
823 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
824 !params
->old_password
.response
.old_nt_hash_enc_data
) {
825 wbc_status
= WBC_ERR_INVALID_PARAM
;
826 BAIL_ON_WBC_ERROR(wbc_status
);
829 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
830 params
->old_password
.response
.old_nt_hash_enc_data
) {
831 wbc_status
= WBC_ERR_INVALID_PARAM
;
832 BAIL_ON_WBC_ERROR(wbc_status
);
835 if (params
->new_password
.response
.lm_length
&&
836 !params
->new_password
.response
.lm_data
) {
837 wbc_status
= WBC_ERR_INVALID_PARAM
;
838 BAIL_ON_WBC_ERROR(wbc_status
);
841 if (params
->new_password
.response
.lm_length
== 0 &&
842 params
->new_password
.response
.lm_data
) {
843 wbc_status
= WBC_ERR_INVALID_PARAM
;
844 BAIL_ON_WBC_ERROR(wbc_status
);
847 if (params
->new_password
.response
.nt_length
&&
848 !params
->new_password
.response
.nt_data
) {
849 wbc_status
= WBC_ERR_INVALID_PARAM
;
850 BAIL_ON_WBC_ERROR(wbc_status
);
853 if (params
->new_password
.response
.nt_length
== 0 &&
854 params
->new_password
.response
.nt_data
) {
855 wbc_status
= WBC_ERR_INVALID_PARAM
;
856 BAIL_ON_WBC_ERROR(wbc_status
);
859 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
860 params
->account_name
,
861 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
863 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
865 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
867 if (params
->new_password
.response
.nt_data
) {
868 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
869 params
->new_password
.response
.nt_data
,
870 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
871 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
872 params
->new_password
.response
.nt_length
;
875 if (params
->new_password
.response
.lm_data
) {
876 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
877 params
->new_password
.response
.lm_data
,
878 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
879 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
880 params
->new_password
.response
.lm_length
;
883 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
884 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
885 params
->old_password
.response
.old_nt_hash_enc_data
,
886 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
887 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
888 params
->old_password
.response
.old_nt_hash_enc_length
;
891 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
892 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
893 params
->old_password
.response
.old_lm_hash_enc_data
,
894 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
895 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
896 params
->old_password
.response
.old_lm_hash_enc_length
;
901 wbc_status
= WBC_ERR_INVALID_PARAM
;
902 BAIL_ON_WBC_ERROR(wbc_status
);
908 wbc_status
= wbcRequestResponse(cmd
,
911 if (WBC_ERROR_IS_OK(wbc_status
)) {
915 /* Take the response above and return it to the caller */
917 if (response
.data
.auth
.nt_status
!= 0) {
919 wbc_status
= wbc_create_error_info(NULL
,
922 BAIL_ON_WBC_ERROR(wbc_status
);
928 wbc_status
= wbc_create_password_policy_info(NULL
,
931 BAIL_ON_WBC_ERROR(wbc_status
);
935 *reject_reason
= response
.data
.auth
.reject_reason
;
938 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
939 BAIL_ON_WBC_ERROR(wbc_status
);
945 /* Change a password for a user */
946 wbcErr
wbcChangeUserPassword(const char *username
,
947 const char *old_password
,
948 const char *new_password
)
950 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
951 struct wbcChangePasswordParams params
;
955 params
.account_name
= username
;
956 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
957 params
.old_password
.plaintext
= old_password
;
958 params
.new_password
.plaintext
= new_password
;
960 wbc_status
= wbcChangeUserPasswordEx(¶ms
,
964 BAIL_ON_WBC_ERROR(wbc_status
);
971 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
972 struct wbcLogonUserInfo
**info
,
973 struct wbcAuthErrorInfo
**error
,
974 struct wbcUserPasswordPolicyInfo
**policy
)
976 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
978 struct winbindd_request request
;
979 struct winbindd_response response
;
982 ZERO_STRUCT(request
);
983 ZERO_STRUCT(response
);
996 wbc_status
= WBC_ERR_INVALID_PARAM
;
997 BAIL_ON_WBC_ERROR(wbc_status
);
1000 if (!params
->username
) {
1001 wbc_status
= WBC_ERR_INVALID_PARAM
;
1002 BAIL_ON_WBC_ERROR(wbc_status
);
1005 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
1006 wbc_status
= WBC_ERR_INVALID_PARAM
;
1007 BAIL_ON_WBC_ERROR(wbc_status
);
1009 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
1010 wbc_status
= WBC_ERR_INVALID_PARAM
;
1011 BAIL_ON_WBC_ERROR(wbc_status
);
1014 /* Initialize request */
1016 cmd
= WINBINDD_PAM_AUTH
;
1017 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
1018 WBFLAG_PAM_USER_SESSION_KEY
|
1021 if (!params
->password
) {
1022 wbc_status
= WBC_ERR_INVALID_PARAM
;
1023 BAIL_ON_WBC_ERROR(wbc_status
);
1026 strncpy(request
.data
.auth
.user
,
1028 sizeof(request
.data
.auth
.user
)-1);
1030 strncpy(request
.data
.auth
.pass
,
1032 sizeof(request
.data
.auth
.pass
)-1);
1034 for (i
=0; i
<params
->num_blobs
; i
++) {
1036 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
1037 if (params
->blobs
[i
].blob
.data
) {
1038 strncpy(request
.data
.auth
.krb5_cc_type
,
1039 (const char *)params
->blobs
[i
].blob
.data
,
1040 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
1045 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
1046 if (params
->blobs
[i
].blob
.data
) {
1047 memcpy(&request
.data
.auth
.uid
,
1048 params
->blobs
[i
].blob
.data
,
1049 MIN(sizeof(request
.data
.auth
.uid
),
1050 params
->blobs
[i
].blob
.length
));
1055 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
1056 if (params
->blobs
[i
].blob
.data
) {
1059 params
->blobs
[i
].blob
.data
,
1061 params
->blobs
[i
].blob
.length
));
1062 request
.flags
|= flags
;
1067 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
1068 if (params
->blobs
[i
].blob
.data
&&
1069 params
->blobs
[i
].blob
.data
[0] > 0) {
1070 strncpy(request
.data
.auth
.require_membership_of_sid
,
1071 (const char *)params
->blobs
[i
].blob
.data
,
1072 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
1078 wbc_status
= wbcRequestResponse(cmd
,
1082 if (response
.data
.auth
.nt_status
!= 0) {
1084 wbc_status
= wbc_create_error_info(NULL
,
1087 BAIL_ON_WBC_ERROR(wbc_status
);
1090 wbc_status
= WBC_ERR_AUTH_ERROR
;
1091 BAIL_ON_WBC_ERROR(wbc_status
);
1093 BAIL_ON_WBC_ERROR(wbc_status
);
1096 wbc_status
= wbc_create_logon_info(NULL
,
1099 BAIL_ON_WBC_ERROR(wbc_status
);
1103 wbc_status
= wbc_create_password_policy_info(NULL
,
1106 BAIL_ON_WBC_ERROR(wbc_status
);
1110 if (response
.extra_data
.data
)
1111 free(response
.extra_data
.data
);
1116 /* Authenticate a user with cached credentials */
1117 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1118 struct wbcCredentialCacheInfo
**info
,
1119 struct wbcAuthErrorInfo
**error
)
1121 wbcErr status
= WBC_ERR_UNKNOWN_FAILURE
;
1122 struct wbcCredentialCacheInfo
*result
= NULL
;
1123 struct winbindd_request request
;
1124 struct winbindd_response response
;
1125 struct wbcNamedBlob
*initial_blob
= NULL
;
1126 struct wbcNamedBlob
*challenge_blob
= NULL
;
1129 ZERO_STRUCT(request
);
1130 ZERO_STRUCT(response
);
1135 if (error
!= NULL
) {
1138 if ((params
== NULL
)
1139 || (params
->account_name
== NULL
)
1140 || (params
->level
!= WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP
)) {
1141 status
= WBC_ERR_INVALID_PARAM
;
1145 if (params
->domain_name
!= NULL
) {
1146 status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
1147 if (!WBC_ERROR_IS_OK(status
)) {
1150 snprintf(request
.data
.ccache_ntlm_auth
.user
,
1151 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1,
1152 "%s%c%s", params
->domain_name
,
1153 response
.data
.info
.winbind_separator
,
1154 params
->account_name
);
1156 strncpy(request
.data
.ccache_ntlm_auth
.user
,
1157 params
->account_name
,
1158 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1);
1160 request
.data
.ccache_ntlm_auth
.uid
= getuid();
1162 for (i
=0; i
<params
->num_blobs
; i
++) {
1163 if (strcasecmp(params
->blobs
[i
].name
, "initial_blob") == 0) {
1164 initial_blob
= ¶ms
->blobs
[i
];
1167 if (strcasecmp(params
->blobs
[i
].name
, "challenge_blob") == 0) {
1168 challenge_blob
= ¶ms
->blobs
[i
];
1173 request
.data
.ccache_ntlm_auth
.initial_blob_len
= 0;
1174 request
.data
.ccache_ntlm_auth
.challenge_blob_len
= 0;
1175 request
.extra_len
= 0;
1177 if (initial_blob
!= NULL
) {
1178 request
.data
.ccache_ntlm_auth
.initial_blob_len
=
1179 initial_blob
->blob
.length
;
1180 request
.extra_len
+= initial_blob
->blob
.length
;
1182 if (challenge_blob
!= NULL
) {
1183 request
.data
.ccache_ntlm_auth
.challenge_blob_len
=
1184 challenge_blob
->blob
.length
;
1185 request
.extra_len
+= challenge_blob
->blob
.length
;
1188 if (request
.extra_len
!= 0) {
1189 request
.extra_data
.data
= talloc_array(
1190 NULL
, char, request
.extra_len
);
1191 if (request
.extra_data
.data
== NULL
) {
1192 status
= WBC_ERR_NO_MEMORY
;
1196 if (initial_blob
!= NULL
) {
1197 memcpy(request
.extra_data
.data
,
1198 initial_blob
->blob
.data
, initial_blob
->blob
.length
);
1200 if (challenge_blob
!= NULL
) {
1201 memcpy(request
.extra_data
.data
1202 + request
.data
.ccache_ntlm_auth
.initial_blob_len
,
1203 challenge_blob
->blob
.data
,
1204 challenge_blob
->blob
.length
);
1207 status
= wbcRequestResponse(WINBINDD_CCACHE_NTLMAUTH
, &request
,
1209 if (!WBC_ERROR_IS_OK(status
)) {
1213 result
= talloc(NULL
, struct wbcCredentialCacheInfo
);
1214 if (result
== NULL
) {
1215 status
= WBC_ERR_NO_MEMORY
;
1218 result
->num_blobs
= 0;
1219 result
->blobs
= talloc(result
, struct wbcNamedBlob
);
1220 if (result
->blobs
== NULL
) {
1221 status
= WBC_ERR_NO_MEMORY
;
1224 status
= wbcAddNamedBlob(&result
->num_blobs
, &result
->blobs
,
1226 (uint8_t *)response
.extra_data
.data
,
1227 response
.data
.ccache_ntlm_auth
.auth_blob_len
);
1228 if (!WBC_ERROR_IS_OK(status
)) {
1231 status
= wbcAddNamedBlob(
1232 &result
->num_blobs
, &result
->blobs
, "session_key", 0,
1233 response
.data
.ccache_ntlm_auth
.session_key
,
1234 sizeof(response
.data
.ccache_ntlm_auth
.session_key
));
1235 if (!WBC_ERROR_IS_OK(status
)) {
1239 if (response
.extra_data
.data
)
1240 free(response
.extra_data
.data
);
1242 return WBC_ERR_SUCCESS
;
1245 TALLOC_FREE(request
.extra_data
.data
);
1246 if (response
.extra_data
.data
)
1247 free(response
.extra_data
.data
);
1248 talloc_free(result
);
1252 /* Authenticate a user with cached credentials */
1253 wbcErr
wbcCredentialSave(const char *user
, const char *password
)
1255 struct winbindd_request request
;
1256 struct winbindd_response response
;
1258 ZERO_STRUCT(request
);
1259 ZERO_STRUCT(response
);
1261 strncpy(request
.data
.ccache_save
.user
, user
,
1262 sizeof(request
.data
.ccache_save
.user
)-1);
1263 strncpy(request
.data
.ccache_save
.pass
, password
,
1264 sizeof(request
.data
.ccache_save
.pass
)-1);
1265 request
.data
.ccache_save
.uid
= getuid();
1267 return wbcRequestResponse(WINBINDD_CCACHE_SAVE
, &request
, &response
);