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"
28 #include "../winbind_client.h"
30 /* Authenticate a username/password pair */
31 wbcErr
wbcAuthenticateUser(const char *username
,
34 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
35 struct wbcAuthUserParams params
;
39 params
.account_name
= username
;
40 params
.level
= WBC_AUTH_USER_LEVEL_PLAIN
;
41 params
.password
.plaintext
= password
;
43 wbc_status
= wbcAuthenticateUserEx(¶ms
, NULL
, NULL
);
44 BAIL_ON_WBC_ERROR(wbc_status
);
50 static wbcErr
wbc_create_auth_info(TALLOC_CTX
*mem_ctx
,
51 const struct winbindd_response
*resp
,
52 struct wbcAuthUserInfo
**_i
)
54 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
55 struct wbcAuthUserInfo
*i
;
56 struct wbcDomainSid domain_sid
;
61 i
= talloc(mem_ctx
, struct wbcAuthUserInfo
);
62 BAIL_ON_PTR_ERROR(i
, wbc_status
);
64 i
->user_flags
= resp
->data
.auth
.info3
.user_flgs
;
66 i
->account_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.user_name
);
67 BAIL_ON_PTR_ERROR(i
->account_name
, wbc_status
);
68 i
->user_principal
= NULL
;
69 i
->full_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.full_name
);
70 BAIL_ON_PTR_ERROR(i
->full_name
, wbc_status
);
71 i
->domain_name
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_dom
);
72 BAIL_ON_PTR_ERROR(i
->domain_name
, wbc_status
);
73 i
->dns_domain_name
= NULL
;
75 i
->acct_flags
= resp
->data
.auth
.info3
.acct_flags
;
76 memcpy(i
->user_session_key
,
77 resp
->data
.auth
.user_session_key
,
78 sizeof(i
->user_session_key
));
79 memcpy(i
->lm_session_key
,
80 resp
->data
.auth
.first_8_lm_hash
,
81 sizeof(i
->lm_session_key
));
83 i
->logon_count
= resp
->data
.auth
.info3
.logon_count
;
84 i
->bad_password_count
= resp
->data
.auth
.info3
.bad_pw_count
;
86 i
->logon_time
= resp
->data
.auth
.info3
.logon_time
;
87 i
->logoff_time
= resp
->data
.auth
.info3
.logoff_time
;
88 i
->kickoff_time
= resp
->data
.auth
.info3
.kickoff_time
;
89 i
->pass_last_set_time
= resp
->data
.auth
.info3
.pass_last_set_time
;
90 i
->pass_can_change_time
= resp
->data
.auth
.info3
.pass_can_change_time
;
91 i
->pass_must_change_time
= resp
->data
.auth
.info3
.pass_must_change_time
;
93 i
->logon_server
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_srv
);
94 BAIL_ON_PTR_ERROR(i
->logon_server
, wbc_status
);
95 i
->logon_script
= talloc_strdup(i
, resp
->data
.auth
.info3
.logon_script
);
96 BAIL_ON_PTR_ERROR(i
->logon_script
, wbc_status
);
97 i
->profile_path
= talloc_strdup(i
, resp
->data
.auth
.info3
.profile_path
);
98 BAIL_ON_PTR_ERROR(i
->profile_path
, wbc_status
);
99 i
->home_directory
= talloc_strdup(i
, resp
->data
.auth
.info3
.home_dir
);
100 BAIL_ON_PTR_ERROR(i
->home_directory
, wbc_status
);
101 i
->home_drive
= talloc_strdup(i
, resp
->data
.auth
.info3
.dir_drive
);
102 BAIL_ON_PTR_ERROR(i
->home_drive
, wbc_status
);
105 i
->num_sids
+= resp
->data
.auth
.info3
.num_groups
;
106 i
->num_sids
+= resp
->data
.auth
.info3
.num_other_sids
;
108 i
->sids
= talloc_array(i
, struct wbcSidWithAttr
, i
->num_sids
);
109 BAIL_ON_PTR_ERROR(i
->sids
, wbc_status
);
111 wbc_status
= wbcStringToSid(resp
->data
.auth
.info3
.dom_sid
,
113 BAIL_ON_WBC_ERROR(wbc_status
);
115 #define _SID_COMPOSE(s, d, r, a) { \
117 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
118 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
120 wbc_status = WBC_ERR_INVALID_SID; \
121 BAIL_ON_WBC_ERROR(wbc_status); \
123 (s).attributes = a; \
127 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
128 resp
->data
.auth
.info3
.user_rid
,
131 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
132 resp
->data
.auth
.info3
.group_rid
,
136 p
= (char *)resp
->extra_data
.data
;
138 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
139 BAIL_ON_WBC_ERROR(wbc_status
);
142 for (j
=0; j
< resp
->data
.auth
.info3
.num_groups
; j
++) {
147 char *e
= strchr(p
, '\n');
149 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
150 BAIL_ON_WBC_ERROR(wbc_status
);
155 ret
= sscanf(s
, "0x%08X:0x%08X", &rid
, &attrs
);
157 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
158 BAIL_ON_WBC_ERROR(wbc_status
);
161 _SID_COMPOSE(i
->sids
[sn
], domain_sid
,
166 for (j
=0; j
< resp
->data
.auth
.info3
.num_other_sids
; j
++) {
171 char *e
= strchr(p
, '\n');
173 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
174 BAIL_ON_WBC_ERROR(wbc_status
);
181 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
182 BAIL_ON_WBC_ERROR(wbc_status
);
187 ret
= sscanf(a
, "0x%08X",
190 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
191 BAIL_ON_WBC_ERROR(wbc_status
);
194 wbc_status
= wbcStringToSid(s
, &i
->sids
[sn
].sid
);
195 BAIL_ON_WBC_ERROR(wbc_status
);
197 i
->sids
[sn
].attributes
= attrs
;
210 static wbcErr
wbc_create_error_info(const struct winbindd_response
*resp
,
211 struct wbcAuthErrorInfo
**_e
)
213 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
214 struct wbcAuthErrorInfo
*e
;
216 e
= talloc(NULL
, 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(const struct winbindd_response
*resp
,
236 struct wbcUserPasswordPolicyInfo
**_i
)
238 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
239 struct wbcUserPasswordPolicyInfo
*i
;
241 i
= talloc(NULL
, 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(&response
,
472 BAIL_ON_WBC_ERROR(wbc_status
);
475 wbc_status
= WBC_ERR_AUTH_ERROR
;
476 BAIL_ON_WBC_ERROR(wbc_status
);
478 BAIL_ON_WBC_ERROR(wbc_status
);
481 wbc_status
= wbc_create_auth_info(NULL
,
484 BAIL_ON_WBC_ERROR(wbc_status
);
488 winbindd_free_response(&response
);
490 talloc_free(request
.extra_data
.data
);
495 /* Trigger a verification of the trust credentials of a specific domain */
496 wbcErr
wbcCheckTrustCredentials(const char *domain
,
497 struct wbcAuthErrorInfo
**error
)
499 struct winbindd_request request
;
500 struct winbindd_response response
;
501 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
503 ZERO_STRUCT(request
);
504 ZERO_STRUCT(response
);
507 strncpy(request
.domain_name
, domain
,
508 sizeof(request
.domain_name
)-1);
513 wbc_status
= wbcRequestResponse(WINBINDD_CHECK_MACHACC
,
516 if (response
.data
.auth
.nt_status
!= 0) {
518 wbc_status
= wbc_create_error_info(&response
,
520 BAIL_ON_WBC_ERROR(wbc_status
);
523 wbc_status
= WBC_ERR_AUTH_ERROR
;
524 BAIL_ON_WBC_ERROR(wbc_status
);
526 BAIL_ON_WBC_ERROR(wbc_status
);
532 /* Trigger a change of the trust credentials for a specific domain */
533 wbcErr
wbcChangeTrustCredentials(const char *domain
,
534 struct wbcAuthErrorInfo
**error
)
536 struct winbindd_request request
;
537 struct winbindd_response response
;
538 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
540 ZERO_STRUCT(request
);
541 ZERO_STRUCT(response
);
544 strncpy(request
.domain_name
, domain
,
545 sizeof(request
.domain_name
)-1);
550 wbc_status
= wbcRequestResponse(WINBINDD_CHANGE_MACHACC
,
553 if (response
.data
.auth
.nt_status
!= 0) {
555 wbc_status
= wbc_create_error_info(&response
,
557 BAIL_ON_WBC_ERROR(wbc_status
);
560 wbc_status
= WBC_ERR_AUTH_ERROR
;
561 BAIL_ON_WBC_ERROR(wbc_status
);
563 BAIL_ON_WBC_ERROR(wbc_status
);
570 * Trigger a no-op NETLOGON call. Lightweight version of
571 * wbcCheckTrustCredentials
573 wbcErr
wbcPingDc(const char *domain
, struct wbcAuthErrorInfo
**error
)
575 struct winbindd_request request
;
576 struct winbindd_response response
;
577 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
581 * the current protocol doesn't support
582 * specifying a domain
584 wbc_status
= WBC_ERR_NOT_IMPLEMENTED
;
585 BAIL_ON_WBC_ERROR(wbc_status
);
588 ZERO_STRUCT(request
);
589 ZERO_STRUCT(response
);
593 wbc_status
= wbcRequestResponse(WINBINDD_PING_DC
,
596 if (response
.data
.auth
.nt_status
!= 0) {
598 wbc_status
= wbc_create_error_info(&response
,
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 an extended logoff notification to Winbind for a specific user */
613 wbcErr
wbcLogoffUserEx(const struct wbcLogoffUserParams
*params
,
614 struct wbcAuthErrorInfo
**error
)
616 struct winbindd_request request
;
617 struct winbindd_response response
;
618 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
623 if (!params
|| !params
->username
) {
624 wbc_status
= WBC_ERR_INVALID_PARAM
;
625 BAIL_ON_WBC_ERROR(wbc_status
);
628 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
629 wbc_status
= WBC_ERR_INVALID_PARAM
;
630 BAIL_ON_WBC_ERROR(wbc_status
);
632 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
633 wbc_status
= WBC_ERR_INVALID_PARAM
;
634 BAIL_ON_WBC_ERROR(wbc_status
);
637 ZERO_STRUCT(request
);
638 ZERO_STRUCT(response
);
640 strncpy(request
.data
.logoff
.user
, params
->username
,
641 sizeof(request
.data
.logoff
.user
)-1);
643 for (i
=0; i
<params
->num_blobs
; i
++) {
645 if (strcasecmp(params
->blobs
[i
].name
, "ccfilename") == 0) {
646 if (params
->blobs
[i
].blob
.data
) {
647 strncpy(request
.data
.logoff
.krb5ccname
,
648 (const char *)params
->blobs
[i
].blob
.data
,
649 sizeof(request
.data
.logoff
.krb5ccname
) - 1);
654 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
655 if (params
->blobs
[i
].blob
.data
) {
656 memcpy(&request
.data
.logoff
.uid
,
657 params
->blobs
[i
].blob
.data
,
658 MIN(params
->blobs
[i
].blob
.length
,
659 sizeof(request
.data
.logoff
.uid
)));
664 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
665 if (params
->blobs
[i
].blob
.data
) {
666 memcpy(&request
.flags
,
667 params
->blobs
[i
].blob
.data
,
668 MIN(params
->blobs
[i
].blob
.length
,
669 sizeof(request
.flags
)));
677 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
681 /* Take the response above and return it to the caller */
682 if (response
.data
.auth
.nt_status
!= 0) {
684 wbc_status
= wbc_create_error_info(&response
,
686 BAIL_ON_WBC_ERROR(wbc_status
);
689 wbc_status
= WBC_ERR_AUTH_ERROR
;
690 BAIL_ON_WBC_ERROR(wbc_status
);
692 BAIL_ON_WBC_ERROR(wbc_status
);
698 /* Trigger a logoff notification to Winbind for a specific user */
699 wbcErr
wbcLogoffUser(const char *username
,
701 const char *ccfilename
)
703 struct winbindd_request request
;
704 struct winbindd_response response
;
705 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
710 wbc_status
= WBC_ERR_INVALID_PARAM
;
711 BAIL_ON_WBC_ERROR(wbc_status
);
714 ZERO_STRUCT(request
);
715 ZERO_STRUCT(response
);
717 strncpy(request
.data
.logoff
.user
, username
,
718 sizeof(request
.data
.logoff
.user
)-1);
719 request
.data
.logoff
.uid
= uid
;
722 strncpy(request
.data
.logoff
.krb5ccname
, ccfilename
,
723 sizeof(request
.data
.logoff
.krb5ccname
)-1);
728 wbc_status
= wbcRequestResponse(WINBINDD_PAM_LOGOFF
,
732 /* Take the response above and return it to the caller */
738 /* Change a password for a user with more detailed information upon failure */
739 wbcErr
wbcChangeUserPasswordEx(const struct wbcChangePasswordParams
*params
,
740 struct wbcAuthErrorInfo
**error
,
741 enum wbcPasswordChangeRejectReason
*reject_reason
,
742 struct wbcUserPasswordPolicyInfo
**policy
)
744 struct winbindd_request request
;
745 struct winbindd_response response
;
746 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
751 if (!params
->account_name
) {
752 wbc_status
= WBC_ERR_INVALID_PARAM
;
753 BAIL_ON_WBC_ERROR(wbc_status
);
768 ZERO_STRUCT(request
);
769 ZERO_STRUCT(response
);
771 switch (params
->level
) {
772 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN
:
773 cmd
= WINBINDD_PAM_CHAUTHTOK
;
775 if (!params
->account_name
) {
776 wbc_status
= WBC_ERR_INVALID_PARAM
;
777 BAIL_ON_WBC_ERROR(wbc_status
);
780 strncpy(request
.data
.chauthtok
.user
, params
->account_name
,
781 sizeof(request
.data
.chauthtok
.user
) - 1);
783 if (params
->old_password
.plaintext
) {
784 strncpy(request
.data
.chauthtok
.oldpass
,
785 params
->old_password
.plaintext
,
786 sizeof(request
.data
.chauthtok
.oldpass
) - 1);
789 if (params
->new_password
.plaintext
) {
790 strncpy(request
.data
.chauthtok
.newpass
,
791 params
->new_password
.plaintext
,
792 sizeof(request
.data
.chauthtok
.newpass
) - 1);
796 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE
:
797 cmd
= WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP
;
799 if (!params
->account_name
|| !params
->domain_name
) {
800 wbc_status
= WBC_ERR_INVALID_PARAM
;
801 BAIL_ON_WBC_ERROR(wbc_status
);
804 if (params
->old_password
.response
.old_lm_hash_enc_length
&&
805 !params
->old_password
.response
.old_lm_hash_enc_data
) {
806 wbc_status
= WBC_ERR_INVALID_PARAM
;
807 BAIL_ON_WBC_ERROR(wbc_status
);
810 if (params
->old_password
.response
.old_lm_hash_enc_length
== 0 &&
811 params
->old_password
.response
.old_lm_hash_enc_data
) {
812 wbc_status
= WBC_ERR_INVALID_PARAM
;
813 BAIL_ON_WBC_ERROR(wbc_status
);
816 if (params
->old_password
.response
.old_nt_hash_enc_length
&&
817 !params
->old_password
.response
.old_nt_hash_enc_data
) {
818 wbc_status
= WBC_ERR_INVALID_PARAM
;
819 BAIL_ON_WBC_ERROR(wbc_status
);
822 if (params
->old_password
.response
.old_nt_hash_enc_length
== 0 &&
823 params
->old_password
.response
.old_nt_hash_enc_data
) {
824 wbc_status
= WBC_ERR_INVALID_PARAM
;
825 BAIL_ON_WBC_ERROR(wbc_status
);
828 if (params
->new_password
.response
.lm_length
&&
829 !params
->new_password
.response
.lm_data
) {
830 wbc_status
= WBC_ERR_INVALID_PARAM
;
831 BAIL_ON_WBC_ERROR(wbc_status
);
834 if (params
->new_password
.response
.lm_length
== 0 &&
835 params
->new_password
.response
.lm_data
) {
836 wbc_status
= WBC_ERR_INVALID_PARAM
;
837 BAIL_ON_WBC_ERROR(wbc_status
);
840 if (params
->new_password
.response
.nt_length
&&
841 !params
->new_password
.response
.nt_data
) {
842 wbc_status
= WBC_ERR_INVALID_PARAM
;
843 BAIL_ON_WBC_ERROR(wbc_status
);
846 if (params
->new_password
.response
.nt_length
== 0 &&
847 params
->new_password
.response
.nt_data
) {
848 wbc_status
= WBC_ERR_INVALID_PARAM
;
849 BAIL_ON_WBC_ERROR(wbc_status
);
852 strncpy(request
.data
.chng_pswd_auth_crap
.user
,
853 params
->account_name
,
854 sizeof(request
.data
.chng_pswd_auth_crap
.user
) - 1);
856 strncpy(request
.data
.chng_pswd_auth_crap
.domain
,
858 sizeof(request
.data
.chng_pswd_auth_crap
.domain
) - 1);
860 if (params
->new_password
.response
.nt_data
) {
861 memcpy(request
.data
.chng_pswd_auth_crap
.new_nt_pswd
,
862 params
->new_password
.response
.nt_data
,
863 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
);
864 request
.data
.chng_pswd_auth_crap
.new_nt_pswd_len
=
865 params
->new_password
.response
.nt_length
;
868 if (params
->new_password
.response
.lm_data
) {
869 memcpy(request
.data
.chng_pswd_auth_crap
.new_lm_pswd
,
870 params
->new_password
.response
.lm_data
,
871 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
);
872 request
.data
.chng_pswd_auth_crap
.new_lm_pswd_len
=
873 params
->new_password
.response
.lm_length
;
876 if (params
->old_password
.response
.old_nt_hash_enc_data
) {
877 memcpy(request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc
,
878 params
->old_password
.response
.old_nt_hash_enc_data
,
879 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
);
880 request
.data
.chng_pswd_auth_crap
.old_nt_hash_enc_len
=
881 params
->old_password
.response
.old_nt_hash_enc_length
;
884 if (params
->old_password
.response
.old_lm_hash_enc_data
) {
885 memcpy(request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc
,
886 params
->old_password
.response
.old_lm_hash_enc_data
,
887 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
);
888 request
.data
.chng_pswd_auth_crap
.old_lm_hash_enc_len
=
889 params
->old_password
.response
.old_lm_hash_enc_length
;
894 wbc_status
= WBC_ERR_INVALID_PARAM
;
895 BAIL_ON_WBC_ERROR(wbc_status
);
901 wbc_status
= wbcRequestResponse(cmd
,
904 if (WBC_ERROR_IS_OK(wbc_status
)) {
908 /* Take the response above and return it to the caller */
910 if (response
.data
.auth
.nt_status
!= 0) {
912 wbc_status
= wbc_create_error_info(&response
,
914 BAIL_ON_WBC_ERROR(wbc_status
);
920 wbc_status
= wbc_create_password_policy_info(&response
,
922 BAIL_ON_WBC_ERROR(wbc_status
);
926 *reject_reason
= response
.data
.auth
.reject_reason
;
929 wbc_status
= WBC_ERR_PWD_CHANGE_FAILED
;
930 BAIL_ON_WBC_ERROR(wbc_status
);
936 /* Change a password for a user */
937 wbcErr
wbcChangeUserPassword(const char *username
,
938 const char *old_password
,
939 const char *new_password
)
941 wbcErr wbc_status
= WBC_ERR_SUCCESS
;
942 struct wbcChangePasswordParams params
;
946 params
.account_name
= username
;
947 params
.level
= WBC_CHANGE_PASSWORD_LEVEL_PLAIN
;
948 params
.old_password
.plaintext
= old_password
;
949 params
.new_password
.plaintext
= new_password
;
951 wbc_status
= wbcChangeUserPasswordEx(¶ms
,
955 BAIL_ON_WBC_ERROR(wbc_status
);
962 wbcErr
wbcLogonUser(const struct wbcLogonUserParams
*params
,
963 struct wbcLogonUserInfo
**info
,
964 struct wbcAuthErrorInfo
**error
,
965 struct wbcUserPasswordPolicyInfo
**policy
)
967 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
969 struct winbindd_request request
;
970 struct winbindd_response response
;
973 ZERO_STRUCT(request
);
974 ZERO_STRUCT(response
);
987 wbc_status
= WBC_ERR_INVALID_PARAM
;
988 BAIL_ON_WBC_ERROR(wbc_status
);
991 if (!params
->username
) {
992 wbc_status
= WBC_ERR_INVALID_PARAM
;
993 BAIL_ON_WBC_ERROR(wbc_status
);
996 if ((params
->num_blobs
> 0) && (params
->blobs
== NULL
)) {
997 wbc_status
= WBC_ERR_INVALID_PARAM
;
998 BAIL_ON_WBC_ERROR(wbc_status
);
1000 if ((params
->num_blobs
== 0) && (params
->blobs
!= NULL
)) {
1001 wbc_status
= WBC_ERR_INVALID_PARAM
;
1002 BAIL_ON_WBC_ERROR(wbc_status
);
1005 /* Initialize request */
1007 cmd
= WINBINDD_PAM_AUTH
;
1008 request
.flags
= WBFLAG_PAM_INFO3_TEXT
|
1009 WBFLAG_PAM_USER_SESSION_KEY
|
1012 if (!params
->password
) {
1013 wbc_status
= WBC_ERR_INVALID_PARAM
;
1014 BAIL_ON_WBC_ERROR(wbc_status
);
1017 strncpy(request
.data
.auth
.user
,
1019 sizeof(request
.data
.auth
.user
)-1);
1021 strncpy(request
.data
.auth
.pass
,
1023 sizeof(request
.data
.auth
.pass
)-1);
1025 for (i
=0; i
<params
->num_blobs
; i
++) {
1027 if (strcasecmp(params
->blobs
[i
].name
, "krb5_cc_type") == 0) {
1028 if (params
->blobs
[i
].blob
.data
) {
1029 strncpy(request
.data
.auth
.krb5_cc_type
,
1030 (const char *)params
->blobs
[i
].blob
.data
,
1031 sizeof(request
.data
.auth
.krb5_cc_type
) - 1);
1036 if (strcasecmp(params
->blobs
[i
].name
, "user_uid") == 0) {
1037 if (params
->blobs
[i
].blob
.data
) {
1038 memcpy(&request
.data
.auth
.uid
,
1039 params
->blobs
[i
].blob
.data
,
1040 MIN(sizeof(request
.data
.auth
.uid
),
1041 params
->blobs
[i
].blob
.length
));
1046 if (strcasecmp(params
->blobs
[i
].name
, "flags") == 0) {
1047 if (params
->blobs
[i
].blob
.data
) {
1050 params
->blobs
[i
].blob
.data
,
1052 params
->blobs
[i
].blob
.length
));
1053 request
.flags
|= flags
;
1058 if (strcasecmp(params
->blobs
[i
].name
, "membership_of") == 0) {
1059 if (params
->blobs
[i
].blob
.data
&&
1060 params
->blobs
[i
].blob
.data
[0] > 0) {
1061 strncpy(request
.data
.auth
.require_membership_of_sid
,
1062 (const char *)params
->blobs
[i
].blob
.data
,
1063 sizeof(request
.data
.auth
.require_membership_of_sid
) - 1);
1069 wbc_status
= wbcRequestResponse(cmd
,
1073 if (response
.data
.auth
.nt_status
!= 0) {
1075 wbc_status
= wbc_create_error_info(&response
,
1077 BAIL_ON_WBC_ERROR(wbc_status
);
1080 wbc_status
= WBC_ERR_AUTH_ERROR
;
1081 BAIL_ON_WBC_ERROR(wbc_status
);
1083 BAIL_ON_WBC_ERROR(wbc_status
);
1086 wbc_status
= wbc_create_logon_info(NULL
,
1089 BAIL_ON_WBC_ERROR(wbc_status
);
1093 wbc_status
= wbc_create_password_policy_info(&response
,
1095 BAIL_ON_WBC_ERROR(wbc_status
);
1099 winbindd_free_response(&response
);
1104 /* Authenticate a user with cached credentials */
1105 wbcErr
wbcCredentialCache(struct wbcCredentialCacheParams
*params
,
1106 struct wbcCredentialCacheInfo
**info
,
1107 struct wbcAuthErrorInfo
**error
)
1109 wbcErr status
= WBC_ERR_UNKNOWN_FAILURE
;
1110 struct wbcCredentialCacheInfo
*result
= NULL
;
1111 struct winbindd_request request
;
1112 struct winbindd_response response
;
1113 struct wbcNamedBlob
*initial_blob
= NULL
;
1114 struct wbcNamedBlob
*challenge_blob
= NULL
;
1117 ZERO_STRUCT(request
);
1118 ZERO_STRUCT(response
);
1123 if (error
!= NULL
) {
1126 if ((params
== NULL
)
1127 || (params
->account_name
== NULL
)
1128 || (params
->level
!= WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP
)) {
1129 status
= WBC_ERR_INVALID_PARAM
;
1133 if (params
->domain_name
!= NULL
) {
1134 status
= wbcRequestResponse(WINBINDD_INFO
, NULL
, &response
);
1135 if (!WBC_ERROR_IS_OK(status
)) {
1138 snprintf(request
.data
.ccache_ntlm_auth
.user
,
1139 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1,
1140 "%s%c%s", params
->domain_name
,
1141 response
.data
.info
.winbind_separator
,
1142 params
->account_name
);
1144 strncpy(request
.data
.ccache_ntlm_auth
.user
,
1145 params
->account_name
,
1146 sizeof(request
.data
.ccache_ntlm_auth
.user
)-1);
1148 request
.data
.ccache_ntlm_auth
.uid
= getuid();
1150 for (i
=0; i
<params
->num_blobs
; i
++) {
1151 if (strcasecmp(params
->blobs
[i
].name
, "initial_blob") == 0) {
1152 initial_blob
= ¶ms
->blobs
[i
];
1155 if (strcasecmp(params
->blobs
[i
].name
, "challenge_blob") == 0) {
1156 challenge_blob
= ¶ms
->blobs
[i
];
1161 request
.data
.ccache_ntlm_auth
.initial_blob_len
= 0;
1162 request
.data
.ccache_ntlm_auth
.challenge_blob_len
= 0;
1163 request
.extra_len
= 0;
1165 if (initial_blob
!= NULL
) {
1166 request
.data
.ccache_ntlm_auth
.initial_blob_len
=
1167 initial_blob
->blob
.length
;
1168 request
.extra_len
+= initial_blob
->blob
.length
;
1170 if (challenge_blob
!= NULL
) {
1171 request
.data
.ccache_ntlm_auth
.challenge_blob_len
=
1172 challenge_blob
->blob
.length
;
1173 request
.extra_len
+= challenge_blob
->blob
.length
;
1176 if (request
.extra_len
!= 0) {
1177 request
.extra_data
.data
= talloc_array(
1178 NULL
, char, request
.extra_len
);
1179 if (request
.extra_data
.data
== NULL
) {
1180 status
= WBC_ERR_NO_MEMORY
;
1184 if (initial_blob
!= NULL
) {
1185 memcpy(request
.extra_data
.data
,
1186 initial_blob
->blob
.data
, initial_blob
->blob
.length
);
1188 if (challenge_blob
!= NULL
) {
1189 memcpy(request
.extra_data
.data
1190 + request
.data
.ccache_ntlm_auth
.initial_blob_len
,
1191 challenge_blob
->blob
.data
,
1192 challenge_blob
->blob
.length
);
1195 status
= wbcRequestResponse(WINBINDD_CCACHE_NTLMAUTH
, &request
,
1197 if (!WBC_ERROR_IS_OK(status
)) {
1201 result
= talloc(NULL
, struct wbcCredentialCacheInfo
);
1202 if (result
== NULL
) {
1203 status
= WBC_ERR_NO_MEMORY
;
1206 result
->num_blobs
= 0;
1207 result
->blobs
= talloc(result
, struct wbcNamedBlob
);
1208 if (result
->blobs
== NULL
) {
1209 status
= WBC_ERR_NO_MEMORY
;
1212 status
= wbcAddNamedBlob(&result
->num_blobs
, &result
->blobs
,
1214 (uint8_t *)response
.extra_data
.data
,
1215 response
.data
.ccache_ntlm_auth
.auth_blob_len
);
1216 if (!WBC_ERROR_IS_OK(status
)) {
1219 status
= wbcAddNamedBlob(
1220 &result
->num_blobs
, &result
->blobs
, "session_key", 0,
1221 response
.data
.ccache_ntlm_auth
.session_key
,
1222 sizeof(response
.data
.ccache_ntlm_auth
.session_key
));
1223 if (!WBC_ERROR_IS_OK(status
)) {
1227 winbindd_free_response(&response
);
1229 return WBC_ERR_SUCCESS
;
1232 TALLOC_FREE(request
.extra_data
.data
);
1233 winbindd_free_response(&response
);
1234 talloc_free(result
);
1238 /* Authenticate a user with cached credentials */
1239 wbcErr
wbcCredentialSave(const char *user
, const char *password
)
1241 struct winbindd_request request
;
1242 struct winbindd_response response
;
1244 ZERO_STRUCT(request
);
1245 ZERO_STRUCT(response
);
1247 strncpy(request
.data
.ccache_save
.user
, user
,
1248 sizeof(request
.data
.ccache_save
.user
)-1);
1249 strncpy(request
.data
.ccache_save
.pass
, password
,
1250 sizeof(request
.data
.ccache_save
.pass
)-1);
1251 request
.data
.ccache_save
.uid
= getuid();
1253 return wbcRequestResponse(WINBINDD_CCACHE_SAVE
, &request
, &response
);