wbclient: add my copyright.
[Samba.git] / source / nsswitch / libwbclient / wbc_pam.c
blob70e2aa60a53f32396d11b52183f6a26d69a9874b
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
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 /** @brief Authenticate a username/password pair
29 * @param username Name of user to authenticate
30 * @param password Clear text password os user
32 * @return #wbcErr
33 **/
35 wbcErr wbcAuthenticateUser(const char *username,
36 const char *password)
38 wbcErr wbc_status = WBC_ERR_SUCCESS;
39 struct wbcAuthUserParams params;
41 ZERO_STRUCT(params);
43 params.account_name = username;
44 params.level = WBC_AUTH_USER_LEVEL_PLAIN;
45 params.password.plaintext = password;
47 wbc_status = wbcAuthenticateUserEx(&params, NULL, NULL);
48 BAIL_ON_WBC_ERROR(wbc_status);
50 done:
51 return wbc_status;
54 static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx,
55 const struct winbindd_response *resp,
56 struct wbcAuthUserInfo **_i)
58 wbcErr wbc_status = WBC_ERR_SUCCESS;
59 struct wbcAuthUserInfo *i;
60 struct wbcDomainSid domain_sid;
61 char *p;
62 uint32_t sn = 0;
63 uint32_t j;
65 i = talloc(mem_ctx, struct wbcAuthUserInfo);
66 BAIL_ON_PTR_ERROR(i, wbc_status);
68 i->user_flags = resp->data.auth.info3.user_flgs;
70 i->account_name = talloc_strdup(i, resp->data.auth.info3.user_name);
71 BAIL_ON_PTR_ERROR(i->account_name, wbc_status);
72 i->user_principal= NULL;
73 i->full_name = talloc_strdup(i, resp->data.auth.info3.full_name);
74 BAIL_ON_PTR_ERROR(i->full_name, wbc_status);
75 i->domain_name = talloc_strdup(i, resp->data.auth.info3.logon_dom);
76 BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
77 i->dns_domain_name= NULL;
79 i->acct_flags = resp->data.auth.info3.acct_flags;
80 memcpy(i->user_session_key,
81 resp->data.auth.user_session_key,
82 sizeof(i->user_session_key));
83 memcpy(i->lm_session_key,
84 resp->data.auth.first_8_lm_hash,
85 sizeof(i->lm_session_key));
87 i->logon_count = resp->data.auth.info3.logon_count;
88 i->bad_password_count = resp->data.auth.info3.bad_pw_count;
90 i->logon_time = resp->data.auth.info3.logon_time;
91 i->logoff_time = resp->data.auth.info3.logoff_time;
92 i->kickoff_time = resp->data.auth.info3.kickoff_time;
93 i->pass_last_set_time = resp->data.auth.info3.pass_last_set_time;
94 i->pass_can_change_time = resp->data.auth.info3.pass_can_change_time;
95 i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time;
97 i->logon_server = talloc_strdup(i, resp->data.auth.info3.logon_srv);
98 BAIL_ON_PTR_ERROR(i->logon_server, wbc_status);
99 i->logon_script = talloc_strdup(i, resp->data.auth.info3.logon_script);
100 BAIL_ON_PTR_ERROR(i->logon_script, wbc_status);
101 i->profile_path = talloc_strdup(i, resp->data.auth.info3.profile_path);
102 BAIL_ON_PTR_ERROR(i->profile_path, wbc_status);
103 i->home_directory= talloc_strdup(i, resp->data.auth.info3.home_dir);
104 BAIL_ON_PTR_ERROR(i->home_directory, wbc_status);
105 i->home_drive = talloc_strdup(i, resp->data.auth.info3.dir_drive);
106 BAIL_ON_PTR_ERROR(i->home_drive, wbc_status);
108 i->num_sids = 2;
109 i->num_sids += resp->data.auth.info3.num_groups;
110 i->num_sids += resp->data.auth.info3.num_other_sids;
112 i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids);
113 BAIL_ON_PTR_ERROR(i->sids, wbc_status);
115 wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
116 &domain_sid);
117 BAIL_ON_WBC_ERROR(wbc_status);
119 #define _SID_COMPOSE(s, d, r, a) { \
120 (s).sid = d; \
121 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
122 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
123 } else { \
124 wbc_status = WBC_ERR_INVALID_SID; \
125 BAIL_ON_WBC_ERROR(wbc_status); \
127 (s).attributes = a; \
128 } while (0)
130 sn = 0;
131 _SID_COMPOSE(i->sids[sn], domain_sid,
132 resp->data.auth.info3.user_rid,
134 sn++;
135 _SID_COMPOSE(i->sids[sn], domain_sid,
136 resp->data.auth.info3.group_rid,
138 sn++;
140 p = (char *)resp->extra_data.data;
141 if (!p) {
142 wbc_status = WBC_ERR_INVALID_RESPONSE;
143 BAIL_ON_WBC_ERROR(wbc_status);
146 for (j=0; j < resp->data.auth.info3.num_groups; j++) {
147 uint32_t rid;
148 uint32_t attrs;
149 int ret;
150 char *s = p;
151 char *e = strchr(p, '\n');
152 if (!e) {
153 wbc_status = WBC_ERR_INVALID_RESPONSE;
154 BAIL_ON_WBC_ERROR(wbc_status);
156 e[0] = '\0';
157 p = &e[1];
159 ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs);
160 if (ret != 2) {
161 wbc_status = WBC_ERR_INVALID_RESPONSE;
162 BAIL_ON_WBC_ERROR(wbc_status);
165 _SID_COMPOSE(i->sids[sn], domain_sid,
166 rid, attrs);
167 sn++;
170 for (j=0; j < resp->data.auth.info3.num_other_sids; j++) {
171 uint32_t attrs;
172 int ret;
173 char *s = p;
174 char *a;
175 char *e = strchr(p, '\n');
176 if (!e) {
177 wbc_status = WBC_ERR_INVALID_RESPONSE;
178 BAIL_ON_WBC_ERROR(wbc_status);
180 e[0] = '\0';
181 p = &e[1];
183 e = strchr(s, ':');
184 if (!e) {
185 wbc_status = WBC_ERR_INVALID_RESPONSE;
186 BAIL_ON_WBC_ERROR(wbc_status);
188 e[0] = '\0';
189 a = &e[1];
191 ret = sscanf(a, "0x%08X",
192 &attrs);
193 if (ret != 1) {
194 wbc_status = WBC_ERR_INVALID_RESPONSE;
195 BAIL_ON_WBC_ERROR(wbc_status);
198 wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
199 BAIL_ON_WBC_ERROR(wbc_status);
201 i->sids[sn].attributes = attrs;
202 sn++;
205 i->num_sids = sn;
207 *_i = i;
208 i = NULL;
209 done:
210 talloc_free(i);
211 return wbc_status;
214 static wbcErr wbc_create_error_info(TALLOC_CTX *mem_ctx,
215 const struct winbindd_response *resp,
216 struct wbcAuthErrorInfo **_e)
218 wbcErr wbc_status = WBC_ERR_SUCCESS;
219 struct wbcAuthErrorInfo *e;
221 e = talloc(mem_ctx, struct wbcAuthErrorInfo);
222 BAIL_ON_PTR_ERROR(e, wbc_status);
224 e->nt_status = resp->data.auth.nt_status;
225 e->pam_error = resp->data.auth.pam_error;
226 e->nt_string = talloc_strdup(e, resp->data.auth.nt_status_string);
227 BAIL_ON_PTR_ERROR(e->nt_string, wbc_status);
229 e->display_string = talloc_strdup(e, resp->data.auth.error_string);
230 BAIL_ON_PTR_ERROR(e->display_string, wbc_status);
232 *_e = e;
233 e = NULL;
235 done:
236 talloc_free(e);
237 return wbc_status;
240 static wbcErr wbc_create_password_policy_info(TALLOC_CTX *mem_ctx,
241 const struct winbindd_response *resp,
242 struct wbcUserPasswordPolicyInfo **_i)
244 wbcErr wbc_status = WBC_ERR_SUCCESS;
245 struct wbcUserPasswordPolicyInfo *i;
247 i = talloc(mem_ctx, struct wbcUserPasswordPolicyInfo);
248 BAIL_ON_PTR_ERROR(i, wbc_status);
250 i->min_passwordage = resp->data.auth.policy.min_passwordage;
251 i->min_length_password = resp->data.auth.policy.min_length_password;
252 i->password_history = resp->data.auth.policy.password_history;
253 i->password_properties = resp->data.auth.policy.password_properties;
254 i->expire = resp->data.auth.policy.expire;
256 *_i = i;
257 i = NULL;
259 done:
260 talloc_free(i);
261 return wbc_status;
264 /** @brief Authenticate with more detailed information
266 * @param params Input parameters, WBC_AUTH_USER_LEVEL_HASH
267 * is not supported yet
268 * @param info Output details on WBC_ERR_SUCCESS
269 * @param error Output details on WBC_ERR_AUTH_ERROR
271 * @return #wbcErr
274 wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
275 struct wbcAuthUserInfo **info,
276 struct wbcAuthErrorInfo **error)
278 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
279 int cmd = 0;
280 struct winbindd_request request;
281 struct winbindd_response response;
283 ZERO_STRUCT(request);
284 ZERO_STRUCT(response);
286 if (error) {
287 *error = NULL;
290 if (!params) {
291 wbc_status = WBC_ERR_INVALID_PARAM;
292 BAIL_ON_WBC_ERROR(wbc_status);
295 if (!params->account_name) {
296 wbc_status = WBC_ERR_INVALID_PARAM;
297 BAIL_ON_WBC_ERROR(wbc_status);
300 /* Initialize request */
302 switch (params->level) {
303 case WBC_AUTH_USER_LEVEL_PLAIN:
304 cmd = WINBINDD_PAM_AUTH;
305 request.flags = WBFLAG_PAM_INFO3_TEXT |
306 WBFLAG_PAM_USER_SESSION_KEY |
307 WBFLAG_PAM_LMKEY;
309 if (!params->password.plaintext) {
310 wbc_status = WBC_ERR_INVALID_PARAM;
311 BAIL_ON_WBC_ERROR(wbc_status);
314 if (params->domain_name && params->domain_name[0]) {
315 /* We need to get the winbind separator :-( */
316 struct winbindd_response sep_response;
318 ZERO_STRUCT(sep_response);
320 wbc_status = wbcRequestResponse(WINBINDD_INFO,
321 NULL, &sep_response);
322 BAIL_ON_WBC_ERROR(wbc_status);
324 snprintf(request.data.auth.user,
325 sizeof(request.data.auth.user)-1,
326 "%s%c%s",
327 params->domain_name,
328 sep_response.data.info.winbind_separator,
329 params->account_name);
330 } else {
331 strncpy(request.data.auth.user,
332 params->account_name,
333 sizeof(request.data.auth.user)-1);
335 strncpy(request.data.auth.pass,
336 params->password.plaintext,
337 sizeof(request.data.auth.pass)-1);
338 break;
340 case WBC_AUTH_USER_LEVEL_HASH:
341 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
342 BAIL_ON_WBC_ERROR(wbc_status);
343 break;
345 case WBC_AUTH_USER_LEVEL_RESPONSE:
346 cmd = WINBINDD_PAM_AUTH_CRAP;
347 request.flags = WBFLAG_PAM_INFO3_TEXT |
348 WBFLAG_PAM_USER_SESSION_KEY |
349 WBFLAG_PAM_LMKEY;
351 if (params->password.response.lm_length &&
352 !params->password.response.lm_data) {
353 wbc_status = WBC_ERR_INVALID_PARAM;
354 BAIL_ON_WBC_ERROR(wbc_status);
356 if (params->password.response.lm_length == 0 &&
357 params->password.response.lm_data) {
358 wbc_status = WBC_ERR_INVALID_PARAM;
359 BAIL_ON_WBC_ERROR(wbc_status);
362 if (params->password.response.nt_length &&
363 !params->password.response.nt_data) {
364 wbc_status = WBC_ERR_INVALID_PARAM;
365 BAIL_ON_WBC_ERROR(wbc_status);
367 if (params->password.response.nt_length == 0&&
368 params->password.response.nt_data) {
369 wbc_status = WBC_ERR_INVALID_PARAM;
370 BAIL_ON_WBC_ERROR(wbc_status);
373 strncpy(request.data.auth_crap.user,
374 params->account_name,
375 sizeof(request.data.auth_crap.user)-1);
376 if (params->domain_name) {
377 strncpy(request.data.auth_crap.domain,
378 params->domain_name,
379 sizeof(request.data.auth_crap.domain)-1);
381 if (params->workstation_name) {
382 strncpy(request.data.auth_crap.workstation,
383 params->workstation_name,
384 sizeof(request.data.auth_crap.workstation)-1);
387 request.data.auth_crap.logon_parameters =
388 params->parameter_control;
390 memcpy(request.data.auth_crap.chal,
391 params->password.response.challenge,
392 sizeof(request.data.auth_crap.chal));
394 request.data.auth_crap.lm_resp_len =
395 MIN(params->password.response.lm_length,
396 sizeof(request.data.auth_crap.lm_resp));
397 request.data.auth_crap.nt_resp_len =
398 MIN(params->password.response.nt_length,
399 sizeof(request.data.auth_crap.nt_resp));
400 if (params->password.response.lm_data) {
401 memcpy(request.data.auth_crap.lm_resp,
402 params->password.response.lm_data,
403 request.data.auth_crap.lm_resp_len);
405 if (params->password.response.nt_data) {
406 memcpy(request.data.auth_crap.nt_resp,
407 params->password.response.nt_data,
408 request.data.auth_crap.nt_resp_len);
410 break;
411 default:
412 break;
415 if (cmd == 0) {
416 wbc_status = WBC_ERR_INVALID_PARAM;
417 BAIL_ON_WBC_ERROR(wbc_status);
420 wbc_status = wbcRequestResponse(cmd,
421 &request,
422 &response);
423 if (response.data.auth.nt_status != 0) {
424 if (error) {
425 wbc_status = wbc_create_error_info(NULL,
426 &response,
427 error);
428 BAIL_ON_WBC_ERROR(wbc_status);
431 wbc_status = WBC_ERR_AUTH_ERROR;
432 BAIL_ON_WBC_ERROR(wbc_status);
434 BAIL_ON_WBC_ERROR(wbc_status);
436 if (info) {
437 wbc_status = wbc_create_auth_info(NULL,
438 &response,
439 info);
440 BAIL_ON_WBC_ERROR(wbc_status);
443 done:
444 if (response.extra_data.data)
445 free(response.extra_data.data);
447 return wbc_status;
450 /** @brief Trigger a verification of the trust credentials of a specific domain
452 * @param *domain The name of the domain, only NULL for the default domain is
453 * supported yet. Other values than NULL will result in
454 * WBC_ERR_NOT_IMPLEMENTED.
455 * @param error Output details on WBC_ERR_AUTH_ERROR
457 * @return #wbcErr
460 wbcErr wbcCheckTrustCredentials(const char *domain,
461 struct wbcAuthErrorInfo **error)
463 struct winbindd_request request;
464 struct winbindd_response response;
465 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
467 if (domain) {
469 * the current protocol doesn't support
470 * specifying a domain
472 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
473 BAIL_ON_WBC_ERROR(wbc_status);
476 ZERO_STRUCT(request);
477 ZERO_STRUCT(response);
479 /* Send request */
481 wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC,
482 &request,
483 &response);
484 if (response.data.auth.nt_status != 0) {
485 if (error) {
486 wbc_status = wbc_create_error_info(NULL,
487 &response,
488 error);
489 BAIL_ON_WBC_ERROR(wbc_status);
492 wbc_status = WBC_ERR_AUTH_ERROR;
493 BAIL_ON_WBC_ERROR(wbc_status);
495 BAIL_ON_WBC_ERROR(wbc_status);
497 done:
498 return wbc_status;
501 /** @brief Trigger a logoff notification to Winbind for a specific user
503 * @param username Name of user to remove from Winbind's list of
504 * logged on users.
505 * @param uid Uid assigned to the username
506 * @param ccfilename Absolute path to the Krb5 credentials cache to
507 * be removed
509 * @return #wbcErr
513 wbcErr wbcLogoffUser(const char *username,
514 uid_t uid,
515 const char *ccfilename)
517 struct winbindd_request request;
518 struct winbindd_response response;
519 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
521 /* validate input */
523 if (!username) {
524 wbc_status = WBC_ERR_INVALID_PARAM;
525 BAIL_ON_WBC_ERROR(wbc_status);
528 ZERO_STRUCT(request);
529 ZERO_STRUCT(response);
531 strncpy(request.data.logoff.user, username,
532 sizeof(request.data.logoff.user)-1);
533 request.data.logoff.uid = uid;
535 if (ccfilename) {
536 strncpy(request.data.logoff.krb5ccname, ccfilename,
537 sizeof(request.data.logoff.krb5ccname)-1);
540 /* Send request */
542 wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF,
543 &request,
544 &response);
546 /* Take the response above and return it to the caller */
548 done:
549 return wbc_status;
552 /** @brief Change a password for a user with more detailed information upon
553 * failure
554 * @param params Input parameters
555 * @param error User output details on WBC_ERR_PWD_CHANGE_FAILED
556 * @param reject_reason New password reject reason on WBC_ERR_PWD_CHANGE_FAILED
557 * @param policy Password policy output details on WBC_ERR_PWD_CHANGE_FAILED
559 * @return #wbcErr
562 wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
563 struct wbcAuthErrorInfo **error,
564 enum wbcPasswordChangeRejectReason *reject_reason,
565 struct wbcUserPasswordPolicyInfo **policy)
567 struct winbindd_request request;
568 struct winbindd_response response;
569 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
570 int cmd = 0;
572 /* validate input */
574 if (!params->account_name) {
575 wbc_status = WBC_ERR_INVALID_PARAM;
576 BAIL_ON_WBC_ERROR(wbc_status);
579 if (error) {
580 *error = NULL;
583 if (policy) {
584 *policy = NULL;
587 if (reject_reason) {
588 *reject_reason = -1;
591 ZERO_STRUCT(request);
592 ZERO_STRUCT(response);
594 switch (params->level) {
595 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN:
596 cmd = WINBINDD_PAM_CHAUTHTOK;
598 if (!params->account_name) {
599 wbc_status = WBC_ERR_INVALID_PARAM;
600 BAIL_ON_WBC_ERROR(wbc_status);
603 strncpy(request.data.chauthtok.user, params->account_name,
604 sizeof(request.data.chauthtok.user) - 1);
606 if (params->old_password.plaintext) {
607 strncpy(request.data.chauthtok.oldpass,
608 params->old_password.plaintext,
609 sizeof(request.data.chauthtok.oldpass) - 1);
612 if (params->new_password.plaintext) {
613 strncpy(request.data.chauthtok.newpass,
614 params->new_password.plaintext,
615 sizeof(request.data.chauthtok.newpass) - 1);
617 break;
619 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE:
620 cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP;
622 if (!params->account_name || !params->domain_name) {
623 wbc_status = WBC_ERR_INVALID_PARAM;
624 BAIL_ON_WBC_ERROR(wbc_status);
627 if (params->old_password.response.old_lm_hash_enc_length &&
628 !params->old_password.response.old_lm_hash_enc_data) {
629 wbc_status = WBC_ERR_INVALID_PARAM;
630 BAIL_ON_WBC_ERROR(wbc_status);
633 if (params->old_password.response.old_lm_hash_enc_length == 0 &&
634 params->old_password.response.old_lm_hash_enc_data) {
635 wbc_status = WBC_ERR_INVALID_PARAM;
636 BAIL_ON_WBC_ERROR(wbc_status);
639 if (params->old_password.response.old_nt_hash_enc_length &&
640 !params->old_password.response.old_nt_hash_enc_data) {
641 wbc_status = WBC_ERR_INVALID_PARAM;
642 BAIL_ON_WBC_ERROR(wbc_status);
645 if (params->old_password.response.old_nt_hash_enc_length == 0 &&
646 params->old_password.response.old_nt_hash_enc_data) {
647 wbc_status = WBC_ERR_INVALID_PARAM;
648 BAIL_ON_WBC_ERROR(wbc_status);
651 if (params->new_password.response.lm_length &&
652 !params->new_password.response.lm_data) {
653 wbc_status = WBC_ERR_INVALID_PARAM;
654 BAIL_ON_WBC_ERROR(wbc_status);
657 if (params->new_password.response.lm_length == 0 &&
658 params->new_password.response.lm_data) {
659 wbc_status = WBC_ERR_INVALID_PARAM;
660 BAIL_ON_WBC_ERROR(wbc_status);
663 if (params->new_password.response.nt_length &&
664 !params->new_password.response.nt_data) {
665 wbc_status = WBC_ERR_INVALID_PARAM;
666 BAIL_ON_WBC_ERROR(wbc_status);
669 if (params->new_password.response.nt_length == 0 &&
670 params->new_password.response.nt_data) {
671 wbc_status = WBC_ERR_INVALID_PARAM;
672 BAIL_ON_WBC_ERROR(wbc_status);
675 strncpy(request.data.chng_pswd_auth_crap.user,
676 params->account_name,
677 sizeof(request.data.chng_pswd_auth_crap.user) - 1);
679 strncpy(request.data.chng_pswd_auth_crap.domain,
680 params->domain_name,
681 sizeof(request.data.chng_pswd_auth_crap.domain) - 1);
683 if (params->new_password.response.nt_data) {
684 memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd,
685 params->new_password.response.nt_data,
686 request.data.chng_pswd_auth_crap.new_nt_pswd_len);
687 request.data.chng_pswd_auth_crap.new_nt_pswd_len =
688 params->new_password.response.nt_length;
691 if (params->new_password.response.lm_data) {
692 memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd,
693 params->new_password.response.lm_data,
694 request.data.chng_pswd_auth_crap.new_lm_pswd_len);
695 request.data.chng_pswd_auth_crap.new_lm_pswd_len =
696 params->new_password.response.lm_length;
699 if (params->old_password.response.old_nt_hash_enc_data) {
700 memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc,
701 params->old_password.response.old_nt_hash_enc_data,
702 request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
703 request.data.chng_pswd_auth_crap.old_nt_hash_enc_len =
704 params->old_password.response.old_nt_hash_enc_length;
707 if (params->old_password.response.old_lm_hash_enc_data) {
708 memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc,
709 params->old_password.response.old_lm_hash_enc_data,
710 request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
711 request.data.chng_pswd_auth_crap.old_lm_hash_enc_len =
712 params->old_password.response.old_lm_hash_enc_length;
715 break;
716 default:
717 wbc_status = WBC_ERR_INVALID_PARAM;
718 BAIL_ON_WBC_ERROR(wbc_status);
719 break;
722 if (cmd == 0) {
723 wbc_status = WBC_ERR_INVALID_PARAM;
724 BAIL_ON_WBC_ERROR(wbc_status);
727 /* Send request */
729 wbc_status = wbcRequestResponse(cmd,
730 &request,
731 &response);
732 if (WBC_ERROR_IS_OK(wbc_status)) {
733 goto done;
736 /* Take the response above and return it to the caller */
738 if (response.data.auth.nt_status != 0) {
739 if (error) {
740 wbc_status = wbc_create_error_info(NULL,
741 &response,
742 error);
743 BAIL_ON_WBC_ERROR(wbc_status);
748 if (policy) {
749 wbc_status = wbc_create_password_policy_info(NULL,
750 &response,
751 policy);
752 BAIL_ON_WBC_ERROR(wbc_status);
755 if (reject_reason) {
756 *reject_reason = response.data.auth.reject_reason;
759 wbc_status = WBC_ERR_PWD_CHANGE_FAILED;
760 BAIL_ON_WBC_ERROR(wbc_status);
762 done:
763 return wbc_status;
766 /** @brief Change a password for a user
768 * @param username Name of user to authenticate
769 * @param old_password Old clear text password of user
770 * @param new_password New clear text password of user
772 * @return #wbcErr
775 wbcErr wbcChangeUserPassword(const char *username,
776 const char *old_password,
777 const char *new_password)
779 wbcErr wbc_status = WBC_ERR_SUCCESS;
780 struct wbcChangePasswordParams params;
782 ZERO_STRUCT(params);
784 params.account_name = username;
785 params.level = WBC_CHANGE_PASSWORD_LEVEL_PLAIN;
786 params.old_password.plaintext = old_password;
787 params.new_password.plaintext = new_password;
789 wbc_status = wbcChangeUserPasswordEx(&params,
790 NULL,
791 NULL,
792 NULL);
793 BAIL_ON_WBC_ERROR(wbc_status);
795 done:
796 return wbc_status;