/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- wbcAuthenticateUser
- wbc_create_auth_info
- wbc_create_error_info
- wbc_create_password_policy_info
- wbc_create_logon_info
- wbcAuthenticateUserEx
- wbcCheckTrustCredentials
- wbcLogoffUserEx
- wbcLogoffUser
- wbcChangeUserPasswordEx
- wbcChangeUserPassword
- wbcLogonUser
- wbcCredentialCache
1 /*
2 Unix SMB/CIFS implementation.
3
4 Winbind client API
5
6 Copyright (C) Gerald (Jerry) Carter 2007
7 Copyright (C) Guenther Deschner 2008
8
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.
13
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.
18
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/>.
21 */
22
23 /* Required Headers */
24
25 #include "libwbclient.h"
26
27 /* Authenticate a username/password pair */
28 wbcErr wbcAuthenticateUser(const char *username,
/* [<][>][^][v][top][bottom][index][help] */
29 const char *password)
30 {
31 wbcErr wbc_status = WBC_ERR_SUCCESS;
32 struct wbcAuthUserParams params;
33
34 ZERO_STRUCT(params);
35
36 params.account_name = username;
37 params.level = WBC_AUTH_USER_LEVEL_PLAIN;
38 params.password.plaintext = password;
39
40 wbc_status = wbcAuthenticateUserEx(¶ms, NULL, NULL);
41 BAIL_ON_WBC_ERROR(wbc_status);
42
43 done:
44 return wbc_status;
45 }
46
47 static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
48 const struct winbindd_response *resp,
49 struct wbcAuthUserInfo **_i)
50 {
51 wbcErr wbc_status = WBC_ERR_SUCCESS;
52 struct wbcAuthUserInfo *i;
53 struct wbcDomainSid domain_sid;
54 char *p;
55 uint32_t sn = 0;
56 uint32_t j;
57
58 i = talloc(mem_ctx, struct wbcAuthUserInfo);
59 BAIL_ON_PTR_ERROR(i, wbc_status);
60
61 i->user_flags = resp->data.auth.info3.user_flgs;
62
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;
71
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));
79
80 i->logon_count = resp->data.auth.info3.logon_count;
81 i->bad_password_count = resp->data.auth.info3.bad_pw_count;
82
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;
89
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);
100
101 i->num_sids = 2;
102 i->num_sids += resp->data.auth.info3.num_groups;
103 i->num_sids += resp->data.auth.info3.num_other_sids;
104
105 i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids);
106 BAIL_ON_PTR_ERROR(i->sids, wbc_status);
107
108 wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
109 &domain_sid);
110 BAIL_ON_WBC_ERROR(wbc_status);
111
112 #define _SID_COMPOSE(s, d, r, a) { \
113 (s).sid = d; \
114 if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
115 (s).sid.sub_auths[(s).sid.num_auths++] = r; \
116 } else { \
117 wbc_status = WBC_ERR_INVALID_SID; \
118 BAIL_ON_WBC_ERROR(wbc_status); \
119 } \
120 (s).attributes = a; \
121 } while (0)
122
123 sn = 0;
124 _SID_COMPOSE(i->sids[sn], domain_sid,
125 resp->data.auth.info3.user_rid,
126 0);
127 sn++;
128 _SID_COMPOSE(i->sids[sn], domain_sid,
129 resp->data.auth.info3.group_rid,
130 0);
131 sn++;
132
133 p = (char *)resp->extra_data.data;
134 if (!p) {
135 wbc_status = WBC_ERR_INVALID_RESPONSE;
136 BAIL_ON_WBC_ERROR(wbc_status);
137 }
138
139 for (j=0; j < resp->data.auth.info3.num_groups; j++) {
140 uint32_t rid;
141 uint32_t attrs;
142 int ret;
143 char *s = p;
144 char *e = strchr(p, '\n');
145 if (!e) {
146 wbc_status = WBC_ERR_INVALID_RESPONSE;
147 BAIL_ON_WBC_ERROR(wbc_status);
148 }
149 e[0] = '\0';
150 p = &e[1];
151
152 ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs);
153 if (ret != 2) {
154 wbc_status = WBC_ERR_INVALID_RESPONSE;
155 BAIL_ON_WBC_ERROR(wbc_status);
156 }
157
158 _SID_COMPOSE(i->sids[sn], domain_sid,
159 rid, attrs);
160 sn++;
161 }
162
163 for (j=0; j < resp->data.auth.info3.num_other_sids; j++) {
164 uint32_t attrs;
165 int ret;
166 char *s = p;
167 char *a;
168 char *e = strchr(p, '\n');
169 if (!e) {
170 wbc_status = WBC_ERR_INVALID_RESPONSE;
171 BAIL_ON_WBC_ERROR(wbc_status);
172 }
173 e[0] = '\0';
174 p = &e[1];
175
176 e = strchr(s, ':');
177 if (!e) {
178 wbc_status = WBC_ERR_INVALID_RESPONSE;
179 BAIL_ON_WBC_ERROR(wbc_status);
180 }
181 e[0] = '\0';
182 a = &e[1];
183
184 ret = sscanf(a, "0x%08X",
185 &attrs);
186 if (ret != 1) {
187 wbc_status = WBC_ERR_INVALID_RESPONSE;
188 BAIL_ON_WBC_ERROR(wbc_status);
189 }
190
191 wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
192 BAIL_ON_WBC_ERROR(wbc_status);
193
194 i->sids[sn].attributes = attrs;
195 sn++;
196 }
197
198 i->num_sids = sn;
199
200 *_i = i;
201 i = NULL;
202 done:
203 talloc_free(i);
204 return wbc_status;
205 }
206
207 static wbcErr wbc_create_error_info(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
208 const struct winbindd_response *resp,
209 struct wbcAuthErrorInfo **_e)
210 {
211 wbcErr wbc_status = WBC_ERR_SUCCESS;
212 struct wbcAuthErrorInfo *e;
213
214 e = talloc(mem_ctx, struct wbcAuthErrorInfo);
215 BAIL_ON_PTR_ERROR(e, wbc_status);
216
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);
221
222 e->display_string = talloc_strdup(e, resp->data.auth.error_string);
223 BAIL_ON_PTR_ERROR(e->display_string, wbc_status);
224
225 *_e = e;
226 e = NULL;
227
228 done:
229 talloc_free(e);
230 return wbc_status;
231 }
232
233 static wbcErr wbc_create_password_policy_info(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
234 const struct winbindd_response *resp,
235 struct wbcUserPasswordPolicyInfo **_i)
236 {
237 wbcErr wbc_status = WBC_ERR_SUCCESS;
238 struct wbcUserPasswordPolicyInfo *i;
239
240 i = talloc(mem_ctx, struct wbcUserPasswordPolicyInfo);
241 BAIL_ON_PTR_ERROR(i, wbc_status);
242
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;
248
249 *_i = i;
250 i = NULL;
251
252 done:
253 talloc_free(i);
254 return wbc_status;
255 }
256
257 static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
258 const struct winbindd_response *resp,
259 struct wbcLogonUserInfo **_i)
260 {
261 wbcErr wbc_status = WBC_ERR_SUCCESS;
262 struct wbcLogonUserInfo *i;
263
264 i = talloc_zero(mem_ctx, struct wbcLogonUserInfo);
265 BAIL_ON_PTR_ERROR(i, wbc_status);
266
267 wbc_status = wbc_create_auth_info(i, resp, &i->info);
268 BAIL_ON_WBC_ERROR(wbc_status);
269
270 if (resp->data.auth.krb5ccname) {
271 wbc_status = wbcAddNamedBlob(&i->num_blobs,
272 &i->blobs,
273 "krb5ccname",
274 0,
275 (uint8_t *)resp->data.auth.krb5ccname,
276 strlen(resp->data.auth.krb5ccname)+1);
277 BAIL_ON_WBC_ERROR(wbc_status);
278 }
279
280 if (resp->data.auth.unix_username) {
281 wbc_status = wbcAddNamedBlob(&i->num_blobs,
282 &i->blobs,
283 "unix_username",
284 0,
285 (uint8_t *)resp->data.auth.unix_username,
286 strlen(resp->data.auth.unix_username)+1);
287 BAIL_ON_WBC_ERROR(wbc_status);
288 }
289
290 *_i = i;
291 i = NULL;
292 done:
293 if (!WBC_ERROR_IS_OK(wbc_status) && i) {
294 wbcFreeMemory(i->blobs);
295 }
296
297 talloc_free(i);
298 return wbc_status;
299 }
300
301 /* Authenticate with more detailed information */
302 wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
/* [<][>][^][v][top][bottom][index][help] */
303 struct wbcAuthUserInfo **info,
304 struct wbcAuthErrorInfo **error)
305 {
306 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
307 int cmd = 0;
308 struct winbindd_request request;
309 struct winbindd_response response;
310
311 ZERO_STRUCT(request);
312 ZERO_STRUCT(response);
313
314 if (error) {
315 *error = NULL;
316 }
317
318 if (!params) {
319 wbc_status = WBC_ERR_INVALID_PARAM;
320 BAIL_ON_WBC_ERROR(wbc_status);
321 }
322
323 if (!params->account_name) {
324 wbc_status = WBC_ERR_INVALID_PARAM;
325 BAIL_ON_WBC_ERROR(wbc_status);
326 }
327
328 /* Initialize request */
329
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 |
335 WBFLAG_PAM_LMKEY;
336
337 if (!params->password.plaintext) {
338 wbc_status = WBC_ERR_INVALID_PARAM;
339 BAIL_ON_WBC_ERROR(wbc_status);
340 }
341
342 if (params->domain_name && params->domain_name[0]) {
343 /* We need to get the winbind separator :-( */
344 struct winbindd_response sep_response;
345
346 ZERO_STRUCT(sep_response);
347
348 wbc_status = wbcRequestResponse(WINBINDD_INFO,
349 NULL, &sep_response);
350 BAIL_ON_WBC_ERROR(wbc_status);
351
352 snprintf(request.data.auth.user,
353 sizeof(request.data.auth.user)-1,
354 "%s%c%s",
355 params->domain_name,
356 sep_response.data.info.winbind_separator,
357 params->account_name);
358 } else {
359 strncpy(request.data.auth.user,
360 params->account_name,
361 sizeof(request.data.auth.user)-1);
362 }
363
364 strncpy(request.data.auth.pass,
365 params->password.plaintext,
366 sizeof(request.data.auth.pass)-1);
367 break;
368
369 case WBC_AUTH_USER_LEVEL_HASH:
370 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
371 BAIL_ON_WBC_ERROR(wbc_status);
372 break;
373
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 |
378 WBFLAG_PAM_LMKEY;
379
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);
384 }
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);
389 }
390
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);
395 }
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);
400 }
401
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,
407 params->domain_name,
408 sizeof(request.data.auth_crap.domain)-1);
409 }
410 if (params->workstation_name) {
411 strncpy(request.data.auth_crap.workstation,
412 params->workstation_name,
413 sizeof(request.data.auth_crap.workstation)-1);
414 }
415
416 request.data.auth_crap.logon_parameters =
417 params->parameter_control;
418
419 memcpy(request.data.auth_crap.chal,
420 params->password.response.challenge,
421 sizeof(request.data.auth_crap.chal));
422
423 request.data.auth_crap.lm_resp_len =
424 MIN(params->password.response.lm_length,
425 sizeof(request.data.auth_crap.lm_resp));
426 if (params->password.response.lm_data) {
427 memcpy(request.data.auth_crap.lm_resp,
428 params->password.response.lm_data,
429 request.data.auth_crap.lm_resp_len);
430 }
431 request.data.auth_crap.nt_resp_len = params->password.response.nt_length;
432 if (params->password.response.nt_length > sizeof(request.data.auth_crap.nt_resp)) {
433 request.flags |= WBFLAG_BIG_NTLMV2_BLOB;
434 request.extra_len = params->password.response.nt_length;
435 request.extra_data.data = talloc_zero_array(NULL, char, request.extra_len);
436 if (request.extra_data.data == NULL) {
437 wbc_status = WBC_ERR_NO_MEMORY;
438 BAIL_ON_WBC_ERROR(wbc_status);
439 }
440 memcpy(request.extra_data.data,
441 params->password.response.nt_data,
442 request.data.auth_crap.nt_resp_len);
443 } else if (params->password.response.nt_data) {
444 memcpy(request.data.auth_crap.nt_resp,
445 params->password.response.nt_data,
446 request.data.auth_crap.nt_resp_len);
447 }
448 break;
449 default:
450 break;
451 }
452
453 if (cmd == 0) {
454 wbc_status = WBC_ERR_INVALID_PARAM;
455 BAIL_ON_WBC_ERROR(wbc_status);
456 }
457
458 if (params->flags) {
459 request.flags |= params->flags;
460 }
461
462 wbc_status = wbcRequestResponse(cmd,
463 &request,
464 &response);
465 if (response.data.auth.nt_status != 0) {
466 if (error) {
467 wbc_status = wbc_create_error_info(NULL,
468 &response,
469 error);
470 BAIL_ON_WBC_ERROR(wbc_status);
471 }
472
473 wbc_status = WBC_ERR_AUTH_ERROR;
474 BAIL_ON_WBC_ERROR(wbc_status);
475 }
476 BAIL_ON_WBC_ERROR(wbc_status);
477
478 if (info) {
479 wbc_status = wbc_create_auth_info(NULL,
480 &response,
481 info);
482 BAIL_ON_WBC_ERROR(wbc_status);
483 }
484
485 done:
486 if (response.extra_data.data)
487 free(response.extra_data.data);
488
489 talloc_free(request.extra_data.data);
490
491 return wbc_status;
492 }
493
494 /* Trigger a verification of the trust credentials of a specific domain */
495 wbcErr wbcCheckTrustCredentials(const char *domain,
/* [<][>][^][v][top][bottom][index][help] */
496 struct wbcAuthErrorInfo **error)
497 {
498 struct winbindd_request request;
499 struct winbindd_response response;
500 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
501
502 if (domain) {
503 /*
504 * the current protocol doesn't support
505 * specifying a domain
506 */
507 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
508 BAIL_ON_WBC_ERROR(wbc_status);
509 }
510
511 ZERO_STRUCT(request);
512 ZERO_STRUCT(response);
513
514 /* Send request */
515
516 wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC,
517 &request,
518 &response);
519 if (response.data.auth.nt_status != 0) {
520 if (error) {
521 wbc_status = wbc_create_error_info(NULL,
522 &response,
523 error);
524 BAIL_ON_WBC_ERROR(wbc_status);
525 }
526
527 wbc_status = WBC_ERR_AUTH_ERROR;
528 BAIL_ON_WBC_ERROR(wbc_status);
529 }
530 BAIL_ON_WBC_ERROR(wbc_status);
531
532 done:
533 return wbc_status;
534 }
535
536 /* Trigger an extended logoff notification to Winbind for a specific user */
537 wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params,
/* [<][>][^][v][top][bottom][index][help] */
538 struct wbcAuthErrorInfo **error)
539 {
540 struct winbindd_request request;
541 struct winbindd_response response;
542 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
543 int i;
544
545 /* validate input */
546
547 if (!params || !params->username) {
548 wbc_status = WBC_ERR_INVALID_PARAM;
549 BAIL_ON_WBC_ERROR(wbc_status);
550 }
551
552 if ((params->num_blobs > 0) && (params->blobs == NULL)) {
553 wbc_status = WBC_ERR_INVALID_PARAM;
554 BAIL_ON_WBC_ERROR(wbc_status);
555 }
556 if ((params->num_blobs == 0) && (params->blobs != NULL)) {
557 wbc_status = WBC_ERR_INVALID_PARAM;
558 BAIL_ON_WBC_ERROR(wbc_status);
559 }
560
561 ZERO_STRUCT(request);
562 ZERO_STRUCT(response);
563
564 strncpy(request.data.logoff.user, params->username,
565 sizeof(request.data.logoff.user)-1);
566
567 for (i=0; i<params->num_blobs; i++) {
568
569 if (strcasecmp(params->blobs[i].name, "ccfilename") == 0) {
570 if (params->blobs[i].blob.data) {
571 strncpy(request.data.logoff.krb5ccname,
572 (const char *)params->blobs[i].blob.data,
573 sizeof(request.data.logoff.krb5ccname) - 1);
574 }
575 continue;
576 }
577
578 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
579 if (params->blobs[i].blob.data) {
580 memcpy(&request.data.logoff.uid,
581 params->blobs[i].blob.data,
582 MIN(params->blobs[i].blob.length,
583 sizeof(request.data.logoff.uid)));
584 }
585 continue;
586 }
587
588 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
589 if (params->blobs[i].blob.data) {
590 memcpy(&request.flags,
591 params->blobs[i].blob.data,
592 MIN(params->blobs[i].blob.length,
593 sizeof(request.flags)));
594 }
595 continue;
596 }
597 }
598
599 /* Send request */
600
601 wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF,
602 &request,
603 &response);
604
605 /* Take the response above and return it to the caller */
606 if (response.data.auth.nt_status != 0) {
607 if (error) {
608 wbc_status = wbc_create_error_info(NULL,
609 &response,
610 error);
611 BAIL_ON_WBC_ERROR(wbc_status);
612 }
613
614 wbc_status = WBC_ERR_AUTH_ERROR;
615 BAIL_ON_WBC_ERROR(wbc_status);
616 }
617 BAIL_ON_WBC_ERROR(wbc_status);
618
619 done:
620 return wbc_status;
621 }
622
623 /* Trigger a logoff notification to Winbind for a specific user */
624 wbcErr wbcLogoffUser(const char *username,
/* [<][>][^][v][top][bottom][index][help] */
625 uid_t uid,
626 const char *ccfilename)
627 {
628 struct winbindd_request request;
629 struct winbindd_response response;
630 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
631
632 /* validate input */
633
634 if (!username) {
635 wbc_status = WBC_ERR_INVALID_PARAM;
636 BAIL_ON_WBC_ERROR(wbc_status);
637 }
638
639 ZERO_STRUCT(request);
640 ZERO_STRUCT(response);
641
642 strncpy(request.data.logoff.user, username,
643 sizeof(request.data.logoff.user)-1);
644 request.data.logoff.uid = uid;
645
646 if (ccfilename) {
647 strncpy(request.data.logoff.krb5ccname, ccfilename,
648 sizeof(request.data.logoff.krb5ccname)-1);
649 }
650
651 /* Send request */
652
653 wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF,
654 &request,
655 &response);
656
657 /* Take the response above and return it to the caller */
658
659 done:
660 return wbc_status;
661 }
662
663 /* Change a password for a user with more detailed information upon failure */
664 wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
/* [<][>][^][v][top][bottom][index][help] */
665 struct wbcAuthErrorInfo **error,
666 enum wbcPasswordChangeRejectReason *reject_reason,
667 struct wbcUserPasswordPolicyInfo **policy)
668 {
669 struct winbindd_request request;
670 struct winbindd_response response;
671 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
672 int cmd = 0;
673
674 /* validate input */
675
676 if (!params->account_name) {
677 wbc_status = WBC_ERR_INVALID_PARAM;
678 BAIL_ON_WBC_ERROR(wbc_status);
679 }
680
681 if (error) {
682 *error = NULL;
683 }
684
685 if (policy) {
686 *policy = NULL;
687 }
688
689 if (reject_reason) {
690 *reject_reason = -1;
691 }
692
693 ZERO_STRUCT(request);
694 ZERO_STRUCT(response);
695
696 switch (params->level) {
697 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN:
698 cmd = WINBINDD_PAM_CHAUTHTOK;
699
700 if (!params->account_name) {
701 wbc_status = WBC_ERR_INVALID_PARAM;
702 BAIL_ON_WBC_ERROR(wbc_status);
703 }
704
705 strncpy(request.data.chauthtok.user, params->account_name,
706 sizeof(request.data.chauthtok.user) - 1);
707
708 if (params->old_password.plaintext) {
709 strncpy(request.data.chauthtok.oldpass,
710 params->old_password.plaintext,
711 sizeof(request.data.chauthtok.oldpass) - 1);
712 }
713
714 if (params->new_password.plaintext) {
715 strncpy(request.data.chauthtok.newpass,
716 params->new_password.plaintext,
717 sizeof(request.data.chauthtok.newpass) - 1);
718 }
719 break;
720
721 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE:
722 cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP;
723
724 if (!params->account_name || !params->domain_name) {
725 wbc_status = WBC_ERR_INVALID_PARAM;
726 BAIL_ON_WBC_ERROR(wbc_status);
727 }
728
729 if (params->old_password.response.old_lm_hash_enc_length &&
730 !params->old_password.response.old_lm_hash_enc_data) {
731 wbc_status = WBC_ERR_INVALID_PARAM;
732 BAIL_ON_WBC_ERROR(wbc_status);
733 }
734
735 if (params->old_password.response.old_lm_hash_enc_length == 0 &&
736 params->old_password.response.old_lm_hash_enc_data) {
737 wbc_status = WBC_ERR_INVALID_PARAM;
738 BAIL_ON_WBC_ERROR(wbc_status);
739 }
740
741 if (params->old_password.response.old_nt_hash_enc_length &&
742 !params->old_password.response.old_nt_hash_enc_data) {
743 wbc_status = WBC_ERR_INVALID_PARAM;
744 BAIL_ON_WBC_ERROR(wbc_status);
745 }
746
747 if (params->old_password.response.old_nt_hash_enc_length == 0 &&
748 params->old_password.response.old_nt_hash_enc_data) {
749 wbc_status = WBC_ERR_INVALID_PARAM;
750 BAIL_ON_WBC_ERROR(wbc_status);
751 }
752
753 if (params->new_password.response.lm_length &&
754 !params->new_password.response.lm_data) {
755 wbc_status = WBC_ERR_INVALID_PARAM;
756 BAIL_ON_WBC_ERROR(wbc_status);
757 }
758
759 if (params->new_password.response.lm_length == 0 &&
760 params->new_password.response.lm_data) {
761 wbc_status = WBC_ERR_INVALID_PARAM;
762 BAIL_ON_WBC_ERROR(wbc_status);
763 }
764
765 if (params->new_password.response.nt_length &&
766 !params->new_password.response.nt_data) {
767 wbc_status = WBC_ERR_INVALID_PARAM;
768 BAIL_ON_WBC_ERROR(wbc_status);
769 }
770
771 if (params->new_password.response.nt_length == 0 &&
772 params->new_password.response.nt_data) {
773 wbc_status = WBC_ERR_INVALID_PARAM;
774 BAIL_ON_WBC_ERROR(wbc_status);
775 }
776
777 strncpy(request.data.chng_pswd_auth_crap.user,
778 params->account_name,
779 sizeof(request.data.chng_pswd_auth_crap.user) - 1);
780
781 strncpy(request.data.chng_pswd_auth_crap.domain,
782 params->domain_name,
783 sizeof(request.data.chng_pswd_auth_crap.domain) - 1);
784
785 if (params->new_password.response.nt_data) {
786 memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd,
787 params->new_password.response.nt_data,
788 request.data.chng_pswd_auth_crap.new_nt_pswd_len);
789 request.data.chng_pswd_auth_crap.new_nt_pswd_len =
790 params->new_password.response.nt_length;
791 }
792
793 if (params->new_password.response.lm_data) {
794 memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd,
795 params->new_password.response.lm_data,
796 request.data.chng_pswd_auth_crap.new_lm_pswd_len);
797 request.data.chng_pswd_auth_crap.new_lm_pswd_len =
798 params->new_password.response.lm_length;
799 }
800
801 if (params->old_password.response.old_nt_hash_enc_data) {
802 memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc,
803 params->old_password.response.old_nt_hash_enc_data,
804 request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
805 request.data.chng_pswd_auth_crap.old_nt_hash_enc_len =
806 params->old_password.response.old_nt_hash_enc_length;
807 }
808
809 if (params->old_password.response.old_lm_hash_enc_data) {
810 memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc,
811 params->old_password.response.old_lm_hash_enc_data,
812 request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
813 request.data.chng_pswd_auth_crap.old_lm_hash_enc_len =
814 params->old_password.response.old_lm_hash_enc_length;
815 }
816
817 break;
818 default:
819 wbc_status = WBC_ERR_INVALID_PARAM;
820 BAIL_ON_WBC_ERROR(wbc_status);
821 break;
822 }
823
824 /* Send request */
825
826 wbc_status = wbcRequestResponse(cmd,
827 &request,
828 &response);
829 if (WBC_ERROR_IS_OK(wbc_status)) {
830 goto done;
831 }
832
833 /* Take the response above and return it to the caller */
834
835 if (response.data.auth.nt_status != 0) {
836 if (error) {
837 wbc_status = wbc_create_error_info(NULL,
838 &response,
839 error);
840 BAIL_ON_WBC_ERROR(wbc_status);
841 }
842
843 }
844
845 if (policy) {
846 wbc_status = wbc_create_password_policy_info(NULL,
847 &response,
848 policy);
849 BAIL_ON_WBC_ERROR(wbc_status);
850 }
851
852 if (reject_reason) {
853 *reject_reason = response.data.auth.reject_reason;
854 }
855
856 wbc_status = WBC_ERR_PWD_CHANGE_FAILED;
857 BAIL_ON_WBC_ERROR(wbc_status);
858
859 done:
860 return wbc_status;
861 }
862
863 /* Change a password for a user */
864 wbcErr wbcChangeUserPassword(const char *username,
/* [<][>][^][v][top][bottom][index][help] */
865 const char *old_password,
866 const char *new_password)
867 {
868 wbcErr wbc_status = WBC_ERR_SUCCESS;
869 struct wbcChangePasswordParams params;
870
871 ZERO_STRUCT(params);
872
873 params.account_name = username;
874 params.level = WBC_CHANGE_PASSWORD_LEVEL_PLAIN;
875 params.old_password.plaintext = old_password;
876 params.new_password.plaintext = new_password;
877
878 wbc_status = wbcChangeUserPasswordEx(¶ms,
879 NULL,
880 NULL,
881 NULL);
882 BAIL_ON_WBC_ERROR(wbc_status);
883
884 done:
885 return wbc_status;
886 }
887
888 /* Logon a User */
889 wbcErr wbcLogonUser(const struct wbcLogonUserParams *params,
/* [<][>][^][v][top][bottom][index][help] */
890 struct wbcLogonUserInfo **info,
891 struct wbcAuthErrorInfo **error,
892 struct wbcUserPasswordPolicyInfo **policy)
893 {
894 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
895 int cmd = 0;
896 struct winbindd_request request;
897 struct winbindd_response response;
898 uint32_t i;
899
900 ZERO_STRUCT(request);
901 ZERO_STRUCT(response);
902
903 if (info) {
904 *info = NULL;
905 }
906 if (error) {
907 *error = NULL;
908 }
909 if (policy) {
910 *policy = NULL;
911 }
912
913 if (!params) {
914 wbc_status = WBC_ERR_INVALID_PARAM;
915 BAIL_ON_WBC_ERROR(wbc_status);
916 }
917
918 if (!params->username) {
919 wbc_status = WBC_ERR_INVALID_PARAM;
920 BAIL_ON_WBC_ERROR(wbc_status);
921 }
922
923 if ((params->num_blobs > 0) && (params->blobs == NULL)) {
924 wbc_status = WBC_ERR_INVALID_PARAM;
925 BAIL_ON_WBC_ERROR(wbc_status);
926 }
927 if ((params->num_blobs == 0) && (params->blobs != NULL)) {
928 wbc_status = WBC_ERR_INVALID_PARAM;
929 BAIL_ON_WBC_ERROR(wbc_status);
930 }
931
932 /* Initialize request */
933
934 cmd = WINBINDD_PAM_AUTH;
935 request.flags = WBFLAG_PAM_INFO3_TEXT |
936 WBFLAG_PAM_USER_SESSION_KEY |
937 WBFLAG_PAM_LMKEY;
938
939 if (!params->password) {
940 wbc_status = WBC_ERR_INVALID_PARAM;
941 BAIL_ON_WBC_ERROR(wbc_status);
942 }
943
944 strncpy(request.data.auth.user,
945 params->username,
946 sizeof(request.data.auth.user)-1);
947
948 strncpy(request.data.auth.pass,
949 params->password,
950 sizeof(request.data.auth.pass)-1);
951
952 for (i=0; i<params->num_blobs; i++) {
953
954 if (strcasecmp(params->blobs[i].name, "krb5_cc_type") == 0) {
955 if (params->blobs[i].blob.data) {
956 strncpy(request.data.auth.krb5_cc_type,
957 (const char *)params->blobs[i].blob.data,
958 sizeof(request.data.auth.krb5_cc_type) - 1);
959 }
960 continue;
961 }
962
963 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
964 if (params->blobs[i].blob.data) {
965 memcpy(&request.data.auth.uid,
966 params->blobs[i].blob.data,
967 MIN(sizeof(request.data.auth.uid),
968 params->blobs[i].blob.length));
969 }
970 continue;
971 }
972
973 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
974 if (params->blobs[i].blob.data) {
975 uint32_t flags;
976 memcpy(&flags,
977 params->blobs[i].blob.data,
978 MIN(sizeof(flags),
979 params->blobs[i].blob.length));
980 request.flags |= flags;
981 }
982 continue;
983 }
984
985 if (strcasecmp(params->blobs[i].name, "membership_of") == 0) {
986 if (params->blobs[i].blob.data &&
987 params->blobs[i].blob.data[0] > 0) {
988 strncpy(request.data.auth.require_membership_of_sid,
989 (const char *)params->blobs[i].blob.data,
990 sizeof(request.data.auth.require_membership_of_sid) - 1);
991 }
992 continue;
993 }
994 }
995
996 wbc_status = wbcRequestResponse(cmd,
997 &request,
998 &response);
999
1000 if (response.data.auth.nt_status != 0) {
1001 if (error) {
1002 wbc_status = wbc_create_error_info(NULL,
1003 &response,
1004 error);
1005 BAIL_ON_WBC_ERROR(wbc_status);
1006 }
1007
1008 wbc_status = WBC_ERR_AUTH_ERROR;
1009 BAIL_ON_WBC_ERROR(wbc_status);
1010 }
1011 BAIL_ON_WBC_ERROR(wbc_status);
1012
1013 if (info) {
1014 wbc_status = wbc_create_logon_info(NULL,
1015 &response,
1016 info);
1017 BAIL_ON_WBC_ERROR(wbc_status);
1018 }
1019
1020 if (policy) {
1021 wbc_status = wbc_create_password_policy_info(NULL,
1022 &response,
1023 policy);
1024 BAIL_ON_WBC_ERROR(wbc_status);
1025 }
1026
1027 done:
1028 if (response.extra_data.data)
1029 free(response.extra_data.data);
1030
1031 return wbc_status;
1032 }
1033
1034 /* Authenticate a user with cached credentials */
1035 wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
/* [<][>][^][v][top][bottom][index][help] */
1036 struct wbcCredentialCacheInfo **info,
1037 struct wbcAuthErrorInfo **error)
1038 {
1039 return WBC_ERR_NOT_IMPLEMENTED;
1040 }