source: branches/samba-3.3.x/source/nsswitch/libwbclient/wbc_pam.c

Last change on this file was 342, checked in by Herwig Bauernfeind, 16 years ago

Update 3.3 to 3.3.9

File size: 29.9 KB
Line 
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/** @brief Authenticate a username/password pair
28 *
29 * @param username Name of user to authenticate
30 * @param password Clear text password os user
31 *
32 * @return #wbcErr
33 **/
34
35wbcErr wbcAuthenticateUser(const char *username,
36 const char *password)
37{
38 wbcErr wbc_status = WBC_ERR_SUCCESS;
39 struct wbcAuthUserParams params;
40
41 ZERO_STRUCT(params);
42
43 params.account_name = username;
44 params.level = WBC_AUTH_USER_LEVEL_PLAIN;
45 params.password.plaintext = password;
46
47 wbc_status = wbcAuthenticateUserEx(&params, NULL, NULL);
48 BAIL_ON_WBC_ERROR(wbc_status);
49
50done:
51 return wbc_status;
52}
53
54static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx,
55 const struct winbindd_response *resp,
56 struct wbcAuthUserInfo **_i)
57{
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;
64
65 i = talloc(mem_ctx, struct wbcAuthUserInfo);
66 BAIL_ON_PTR_ERROR(i, wbc_status);
67
68 i->user_flags = resp->data.auth.info3.user_flgs;
69
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;
78
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));
86
87 i->logon_count = resp->data.auth.info3.logon_count;
88 i->bad_password_count = resp->data.auth.info3.bad_pw_count;
89
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;
96
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);
107
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;
111
112 i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids);
113 BAIL_ON_PTR_ERROR(i->sids, wbc_status);
114
115 wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
116 &domain_sid);
117 BAIL_ON_WBC_ERROR(wbc_status);
118
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); \
126 } \
127 (s).attributes = a; \
128} while (0)
129
130 sn = 0;
131 _SID_COMPOSE(i->sids[sn], domain_sid,
132 resp->data.auth.info3.user_rid,
133 0);
134 sn++;
135 _SID_COMPOSE(i->sids[sn], domain_sid,
136 resp->data.auth.info3.group_rid,
137 0);
138 sn++;
139
140 p = (char *)resp->extra_data.data;
141 if (!p) {
142 wbc_status = WBC_ERR_INVALID_RESPONSE;
143 BAIL_ON_WBC_ERROR(wbc_status);
144 }
145
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);
155 }
156 e[0] = '\0';
157 p = &e[1];
158
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);
163 }
164
165 _SID_COMPOSE(i->sids[sn], domain_sid,
166 rid, attrs);
167 sn++;
168 }
169
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);
179 }
180 e[0] = '\0';
181 p = &e[1];
182
183 e = strchr(s, ':');
184 if (!e) {
185 wbc_status = WBC_ERR_INVALID_RESPONSE;
186 BAIL_ON_WBC_ERROR(wbc_status);
187 }
188 e[0] = '\0';
189 a = &e[1];
190
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);
196 }
197
198 wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
199 BAIL_ON_WBC_ERROR(wbc_status);
200
201 i->sids[sn].attributes = attrs;
202 sn++;
203 }
204
205 i->num_sids = sn;
206
207 *_i = i;
208 i = NULL;
209done:
210 talloc_free(i);
211 return wbc_status;
212}
213
214static wbcErr wbc_create_error_info(TALLOC_CTX *mem_ctx,
215 const struct winbindd_response *resp,
216 struct wbcAuthErrorInfo **_e)
217{
218 wbcErr wbc_status = WBC_ERR_SUCCESS;
219 struct wbcAuthErrorInfo *e;
220
221 e = talloc(mem_ctx, struct wbcAuthErrorInfo);
222 BAIL_ON_PTR_ERROR(e, wbc_status);
223
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);
228
229 e->display_string = talloc_strdup(e, resp->data.auth.error_string);
230 BAIL_ON_PTR_ERROR(e->display_string, wbc_status);
231
232 *_e = e;
233 e = NULL;
234
235done:
236 talloc_free(e);
237 return wbc_status;
238}
239
240static wbcErr wbc_create_password_policy_info(TALLOC_CTX *mem_ctx,
241 const struct winbindd_response *resp,
242 struct wbcUserPasswordPolicyInfo **_i)
243{
244 wbcErr wbc_status = WBC_ERR_SUCCESS;
245 struct wbcUserPasswordPolicyInfo *i;
246
247 i = talloc(mem_ctx, struct wbcUserPasswordPolicyInfo);
248 BAIL_ON_PTR_ERROR(i, wbc_status);
249
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;
255
256 *_i = i;
257 i = NULL;
258
259done:
260 talloc_free(i);
261 return wbc_status;
262}
263
264static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx,
265 const struct winbindd_response *resp,
266 struct wbcLogonUserInfo **_i)
267{
268 wbcErr wbc_status = WBC_ERR_SUCCESS;
269 struct wbcLogonUserInfo *i;
270
271 i = talloc_zero(mem_ctx, struct wbcLogonUserInfo);
272 BAIL_ON_PTR_ERROR(i, wbc_status);
273
274 wbc_status = wbc_create_auth_info(i, resp, &i->info);
275 BAIL_ON_WBC_ERROR(wbc_status);
276
277 if (resp->data.auth.krb5ccname) {
278 wbc_status = wbcAddNamedBlob(&i->num_blobs,
279 &i->blobs,
280 "krb5ccname",
281 0,
282 (uint8_t *)resp->data.auth.krb5ccname,
283 strlen(resp->data.auth.krb5ccname)+1);
284 BAIL_ON_WBC_ERROR(wbc_status);
285 }
286
287 if (resp->data.auth.unix_username) {
288 wbc_status = wbcAddNamedBlob(&i->num_blobs,
289 &i->blobs,
290 "unix_username",
291 0,
292 (uint8_t *)resp->data.auth.unix_username,
293 strlen(resp->data.auth.unix_username)+1);
294 BAIL_ON_WBC_ERROR(wbc_status);
295 }
296
297 *_i = i;
298 i = NULL;
299done:
300 if (!WBC_ERROR_IS_OK(wbc_status) && i) {
301 wbcFreeMemory(i->blobs);
302 }
303
304 talloc_free(i);
305 return wbc_status;
306}
307
308/** @brief Authenticate with more detailed information
309 *
310 * @param params Input parameters, WBC_AUTH_USER_LEVEL_HASH
311 * is not supported yet
312 * @param info Output details on WBC_ERR_SUCCESS
313 * @param error Output details on WBC_ERR_AUTH_ERROR
314 *
315 * @return #wbcErr
316 **/
317
318wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
319 struct wbcAuthUserInfo **info,
320 struct wbcAuthErrorInfo **error)
321{
322 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
323 int cmd = 0;
324 struct winbindd_request request;
325 struct winbindd_response response;
326
327 ZERO_STRUCT(request);
328 ZERO_STRUCT(response);
329
330 if (error) {
331 *error = NULL;
332 }
333
334 if (!params) {
335 wbc_status = WBC_ERR_INVALID_PARAM;
336 BAIL_ON_WBC_ERROR(wbc_status);
337 }
338
339 if (!params->account_name) {
340 wbc_status = WBC_ERR_INVALID_PARAM;
341 BAIL_ON_WBC_ERROR(wbc_status);
342 }
343
344 /* Initialize request */
345
346 switch (params->level) {
347 case WBC_AUTH_USER_LEVEL_PLAIN:
348 cmd = WINBINDD_PAM_AUTH;
349 request.flags = WBFLAG_PAM_INFO3_TEXT |
350 WBFLAG_PAM_USER_SESSION_KEY |
351 WBFLAG_PAM_LMKEY;
352
353 if (!params->password.plaintext) {
354 wbc_status = WBC_ERR_INVALID_PARAM;
355 BAIL_ON_WBC_ERROR(wbc_status);
356 }
357
358 if (params->domain_name && params->domain_name[0]) {
359 /* We need to get the winbind separator :-( */
360 struct winbindd_response sep_response;
361
362 ZERO_STRUCT(sep_response);
363
364 wbc_status = wbcRequestResponse(WINBINDD_INFO,
365 NULL, &sep_response);
366 BAIL_ON_WBC_ERROR(wbc_status);
367
368 snprintf(request.data.auth.user,
369 sizeof(request.data.auth.user)-1,
370 "%s%c%s",
371 params->domain_name,
372 sep_response.data.info.winbind_separator,
373 params->account_name);
374 } else {
375 strncpy(request.data.auth.user,
376 params->account_name,
377 sizeof(request.data.auth.user)-1);
378 }
379
380 strncpy(request.data.auth.pass,
381 params->password.plaintext,
382 sizeof(request.data.auth.pass)-1);
383 break;
384
385 case WBC_AUTH_USER_LEVEL_HASH:
386 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
387 BAIL_ON_WBC_ERROR(wbc_status);
388 break;
389
390 case WBC_AUTH_USER_LEVEL_RESPONSE:
391 cmd = WINBINDD_PAM_AUTH_CRAP;
392 request.flags = WBFLAG_PAM_INFO3_TEXT |
393 WBFLAG_PAM_USER_SESSION_KEY |
394 WBFLAG_PAM_LMKEY;
395
396 if (params->password.response.lm_length &&
397 !params->password.response.lm_data) {
398 wbc_status = WBC_ERR_INVALID_PARAM;
399 BAIL_ON_WBC_ERROR(wbc_status);
400 }
401 if (params->password.response.lm_length == 0 &&
402 params->password.response.lm_data) {
403 wbc_status = WBC_ERR_INVALID_PARAM;
404 BAIL_ON_WBC_ERROR(wbc_status);
405 }
406
407 if (params->password.response.nt_length &&
408 !params->password.response.nt_data) {
409 wbc_status = WBC_ERR_INVALID_PARAM;
410 BAIL_ON_WBC_ERROR(wbc_status);
411 }
412 if (params->password.response.nt_length == 0&&
413 params->password.response.nt_data) {
414 wbc_status = WBC_ERR_INVALID_PARAM;
415 BAIL_ON_WBC_ERROR(wbc_status);
416 }
417
418 strncpy(request.data.auth_crap.user,
419 params->account_name,
420 sizeof(request.data.auth_crap.user)-1);
421 if (params->domain_name) {
422 strncpy(request.data.auth_crap.domain,
423 params->domain_name,
424 sizeof(request.data.auth_crap.domain)-1);
425 }
426 if (params->workstation_name) {
427 strncpy(request.data.auth_crap.workstation,
428 params->workstation_name,
429 sizeof(request.data.auth_crap.workstation)-1);
430 }
431
432 request.data.auth_crap.logon_parameters =
433 params->parameter_control;
434
435 memcpy(request.data.auth_crap.chal,
436 params->password.response.challenge,
437 sizeof(request.data.auth_crap.chal));
438
439 request.data.auth_crap.lm_resp_len =
440 MIN(params->password.response.lm_length,
441 sizeof(request.data.auth_crap.lm_resp));
442 if (params->password.response.lm_data) {
443 memcpy(request.data.auth_crap.lm_resp,
444 params->password.response.lm_data,
445 request.data.auth_crap.lm_resp_len);
446 }
447 request.data.auth_crap.nt_resp_len = params->password.response.nt_length;
448 if (params->password.response.nt_length > sizeof(request.data.auth_crap.nt_resp)) {
449 request.flags |= WBFLAG_BIG_NTLMV2_BLOB;
450 request.extra_len = params->password.response.nt_length;
451 request.extra_data.data = talloc_zero_array(NULL, char, request.extra_len);
452 if (request.extra_data.data == NULL) {
453 wbc_status = WBC_ERR_NO_MEMORY;
454 BAIL_ON_WBC_ERROR(wbc_status);
455 }
456 memcpy(request.extra_data.data,
457 params->password.response.nt_data,
458 request.data.auth_crap.nt_resp_len);
459 } else if (params->password.response.nt_data) {
460 memcpy(request.data.auth_crap.nt_resp,
461 params->password.response.nt_data,
462 request.data.auth_crap.nt_resp_len);
463 }
464 break;
465 default:
466 break;
467 }
468
469 if (cmd == 0) {
470 wbc_status = WBC_ERR_INVALID_PARAM;
471 BAIL_ON_WBC_ERROR(wbc_status);
472 }
473
474 if (params->flags) {
475 request.flags |= params->flags;
476 }
477
478 wbc_status = wbcRequestResponse(cmd,
479 &request,
480 &response);
481 if (response.data.auth.nt_status != 0) {
482 if (error) {
483 wbc_status = wbc_create_error_info(NULL,
484 &response,
485 error);
486 BAIL_ON_WBC_ERROR(wbc_status);
487 }
488
489 wbc_status = WBC_ERR_AUTH_ERROR;
490 BAIL_ON_WBC_ERROR(wbc_status);
491 }
492 BAIL_ON_WBC_ERROR(wbc_status);
493
494 if (info) {
495 wbc_status = wbc_create_auth_info(NULL,
496 &response,
497 info);
498 BAIL_ON_WBC_ERROR(wbc_status);
499 }
500
501done:
502 if (response.extra_data.data)
503 free(response.extra_data.data);
504
505 talloc_free(request.extra_data.data);
506
507 return wbc_status;
508}
509
510/** @brief Trigger a verification of the trust credentials of a specific domain
511 *
512 * @param *domain The name of the domain, only NULL for the default domain is
513 * supported yet. Other values than NULL will result in
514 * WBC_ERR_NOT_IMPLEMENTED.
515 * @param error Output details on WBC_ERR_AUTH_ERROR
516 *
517 * @return #wbcErr
518 *
519 **/
520wbcErr wbcCheckTrustCredentials(const char *domain,
521 struct wbcAuthErrorInfo **error)
522{
523 struct winbindd_request request;
524 struct winbindd_response response;
525 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
526
527 if (domain) {
528 /*
529 * the current protocol doesn't support
530 * specifying a domain
531 */
532 wbc_status = WBC_ERR_NOT_IMPLEMENTED;
533 BAIL_ON_WBC_ERROR(wbc_status);
534 }
535
536 ZERO_STRUCT(request);
537 ZERO_STRUCT(response);
538
539 /* Send request */
540
541 wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC,
542 &request,
543 &response);
544 if (response.data.auth.nt_status != 0) {
545 if (error) {
546 wbc_status = wbc_create_error_info(NULL,
547 &response,
548 error);
549 BAIL_ON_WBC_ERROR(wbc_status);
550 }
551
552 wbc_status = WBC_ERR_AUTH_ERROR;
553 BAIL_ON_WBC_ERROR(wbc_status);
554 }
555 BAIL_ON_WBC_ERROR(wbc_status);
556
557 done:
558 return wbc_status;
559}
560
561/** @brief Trigger an extended logoff notification to Winbind for a specific user
562 *
563 * @param params A wbcLogoffUserParams structure
564 * @param error User output details on error
565 *
566 * @return #wbcErr
567 *
568 **/
569
570wbcErr wbcLogoffUserEx(const struct wbcLogoffUserParams *params,
571 struct wbcAuthErrorInfo **error)
572{
573 struct winbindd_request request;
574 struct winbindd_response response;
575 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
576 int i;
577
578 /* validate input */
579
580 if (!params || !params->username) {
581 wbc_status = WBC_ERR_INVALID_PARAM;
582 BAIL_ON_WBC_ERROR(wbc_status);
583 }
584
585 if ((params->num_blobs > 0) && (params->blobs == NULL)) {
586 wbc_status = WBC_ERR_INVALID_PARAM;
587 BAIL_ON_WBC_ERROR(wbc_status);
588 }
589 if ((params->num_blobs == 0) && (params->blobs != NULL)) {
590 wbc_status = WBC_ERR_INVALID_PARAM;
591 BAIL_ON_WBC_ERROR(wbc_status);
592 }
593
594 ZERO_STRUCT(request);
595 ZERO_STRUCT(response);
596
597 strncpy(request.data.logoff.user, params->username,
598 sizeof(request.data.logoff.user)-1);
599
600 for (i=0; i<params->num_blobs; i++) {
601
602 if (strcasecmp(params->blobs[i].name, "ccfilename") == 0) {
603 if (params->blobs[i].blob.data) {
604 strncpy(request.data.logoff.krb5ccname,
605 (const char *)params->blobs[i].blob.data,
606 sizeof(request.data.logoff.krb5ccname) - 1);
607 }
608 continue;
609 }
610
611 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
612 if (params->blobs[i].blob.data) {
613 memcpy(&request.data.logoff.uid,
614 params->blobs[i].blob.data,
615 MIN(params->blobs[i].blob.length,
616 sizeof(request.data.logoff.uid)));
617 }
618 continue;
619 }
620
621 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
622 if (params->blobs[i].blob.data) {
623 memcpy(&request.flags,
624 params->blobs[i].blob.data,
625 MIN(params->blobs[i].blob.length,
626 sizeof(request.flags)));
627 }
628 continue;
629 }
630 }
631
632 /* Send request */
633
634 wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF,
635 &request,
636 &response);
637
638 /* Take the response above and return it to the caller */
639 if (response.data.auth.nt_status != 0) {
640 if (error) {
641 wbc_status = wbc_create_error_info(NULL,
642 &response,
643 error);
644 BAIL_ON_WBC_ERROR(wbc_status);
645 }
646
647 wbc_status = WBC_ERR_AUTH_ERROR;
648 BAIL_ON_WBC_ERROR(wbc_status);
649 }
650 BAIL_ON_WBC_ERROR(wbc_status);
651
652 done:
653 return wbc_status;
654}
655
656/** @brief Trigger a logoff notification to Winbind for a specific user
657 *
658 * @param username Name of user to remove from Winbind's list of
659 * logged on users.
660 * @param uid Uid assigned to the username
661 * @param ccfilename Absolute path to the Krb5 credentials cache to
662 * be removed
663 *
664 * @return #wbcErr
665 *
666 **/
667
668wbcErr wbcLogoffUser(const char *username,
669 uid_t uid,
670 const char *ccfilename)
671{
672 struct winbindd_request request;
673 struct winbindd_response response;
674 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
675
676 /* validate input */
677
678 if (!username) {
679 wbc_status = WBC_ERR_INVALID_PARAM;
680 BAIL_ON_WBC_ERROR(wbc_status);
681 }
682
683 ZERO_STRUCT(request);
684 ZERO_STRUCT(response);
685
686 strncpy(request.data.logoff.user, username,
687 sizeof(request.data.logoff.user)-1);
688 request.data.logoff.uid = uid;
689
690 if (ccfilename) {
691 strncpy(request.data.logoff.krb5ccname, ccfilename,
692 sizeof(request.data.logoff.krb5ccname)-1);
693 }
694
695 /* Send request */
696
697 wbc_status = wbcRequestResponse(WINBINDD_PAM_LOGOFF,
698 &request,
699 &response);
700
701 /* Take the response above and return it to the caller */
702
703 done:
704 return wbc_status;
705}
706
707/** @brief Change a password for a user with more detailed information upon
708 * failure
709 * @param params Input parameters
710 * @param error User output details on WBC_ERR_PWD_CHANGE_FAILED
711 * @param reject_reason New password reject reason on WBC_ERR_PWD_CHANGE_FAILED
712 * @param policy Password policy output details on WBC_ERR_PWD_CHANGE_FAILED
713 *
714 * @return #wbcErr
715 **/
716
717wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
718 struct wbcAuthErrorInfo **error,
719 enum wbcPasswordChangeRejectReason *reject_reason,
720 struct wbcUserPasswordPolicyInfo **policy)
721{
722 struct winbindd_request request;
723 struct winbindd_response response;
724 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
725 int cmd = 0;
726
727 /* validate input */
728
729 if (!params->account_name) {
730 wbc_status = WBC_ERR_INVALID_PARAM;
731 BAIL_ON_WBC_ERROR(wbc_status);
732 }
733
734 if (error) {
735 *error = NULL;
736 }
737
738 if (policy) {
739 *policy = NULL;
740 }
741
742 if (reject_reason) {
743 *reject_reason = -1;
744 }
745
746 ZERO_STRUCT(request);
747 ZERO_STRUCT(response);
748
749 switch (params->level) {
750 case WBC_CHANGE_PASSWORD_LEVEL_PLAIN:
751 cmd = WINBINDD_PAM_CHAUTHTOK;
752
753 if (!params->account_name) {
754 wbc_status = WBC_ERR_INVALID_PARAM;
755 BAIL_ON_WBC_ERROR(wbc_status);
756 }
757
758 strncpy(request.data.chauthtok.user, params->account_name,
759 sizeof(request.data.chauthtok.user) - 1);
760
761 if (params->old_password.plaintext) {
762 strncpy(request.data.chauthtok.oldpass,
763 params->old_password.plaintext,
764 sizeof(request.data.chauthtok.oldpass) - 1);
765 }
766
767 if (params->new_password.plaintext) {
768 strncpy(request.data.chauthtok.newpass,
769 params->new_password.plaintext,
770 sizeof(request.data.chauthtok.newpass) - 1);
771 }
772 break;
773
774 case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE:
775 cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP;
776
777 if (!params->account_name || !params->domain_name) {
778 wbc_status = WBC_ERR_INVALID_PARAM;
779 BAIL_ON_WBC_ERROR(wbc_status);
780 }
781
782 if (params->old_password.response.old_lm_hash_enc_length &&
783 !params->old_password.response.old_lm_hash_enc_data) {
784 wbc_status = WBC_ERR_INVALID_PARAM;
785 BAIL_ON_WBC_ERROR(wbc_status);
786 }
787
788 if (params->old_password.response.old_lm_hash_enc_length == 0 &&
789 params->old_password.response.old_lm_hash_enc_data) {
790 wbc_status = WBC_ERR_INVALID_PARAM;
791 BAIL_ON_WBC_ERROR(wbc_status);
792 }
793
794 if (params->old_password.response.old_nt_hash_enc_length &&
795 !params->old_password.response.old_nt_hash_enc_data) {
796 wbc_status = WBC_ERR_INVALID_PARAM;
797 BAIL_ON_WBC_ERROR(wbc_status);
798 }
799
800 if (params->old_password.response.old_nt_hash_enc_length == 0 &&
801 params->old_password.response.old_nt_hash_enc_data) {
802 wbc_status = WBC_ERR_INVALID_PARAM;
803 BAIL_ON_WBC_ERROR(wbc_status);
804 }
805
806 if (params->new_password.response.lm_length &&
807 !params->new_password.response.lm_data) {
808 wbc_status = WBC_ERR_INVALID_PARAM;
809 BAIL_ON_WBC_ERROR(wbc_status);
810 }
811
812 if (params->new_password.response.lm_length == 0 &&
813 params->new_password.response.lm_data) {
814 wbc_status = WBC_ERR_INVALID_PARAM;
815 BAIL_ON_WBC_ERROR(wbc_status);
816 }
817
818 if (params->new_password.response.nt_length &&
819 !params->new_password.response.nt_data) {
820 wbc_status = WBC_ERR_INVALID_PARAM;
821 BAIL_ON_WBC_ERROR(wbc_status);
822 }
823
824 if (params->new_password.response.nt_length == 0 &&
825 params->new_password.response.nt_data) {
826 wbc_status = WBC_ERR_INVALID_PARAM;
827 BAIL_ON_WBC_ERROR(wbc_status);
828 }
829
830 strncpy(request.data.chng_pswd_auth_crap.user,
831 params->account_name,
832 sizeof(request.data.chng_pswd_auth_crap.user) - 1);
833
834 strncpy(request.data.chng_pswd_auth_crap.domain,
835 params->domain_name,
836 sizeof(request.data.chng_pswd_auth_crap.domain) - 1);
837
838 if (params->new_password.response.nt_data) {
839 memcpy(request.data.chng_pswd_auth_crap.new_nt_pswd,
840 params->new_password.response.nt_data,
841 request.data.chng_pswd_auth_crap.new_nt_pswd_len);
842 request.data.chng_pswd_auth_crap.new_nt_pswd_len =
843 params->new_password.response.nt_length;
844 }
845
846 if (params->new_password.response.lm_data) {
847 memcpy(request.data.chng_pswd_auth_crap.new_lm_pswd,
848 params->new_password.response.lm_data,
849 request.data.chng_pswd_auth_crap.new_lm_pswd_len);
850 request.data.chng_pswd_auth_crap.new_lm_pswd_len =
851 params->new_password.response.lm_length;
852 }
853
854 if (params->old_password.response.old_nt_hash_enc_data) {
855 memcpy(request.data.chng_pswd_auth_crap.old_nt_hash_enc,
856 params->old_password.response.old_nt_hash_enc_data,
857 request.data.chng_pswd_auth_crap.old_nt_hash_enc_len);
858 request.data.chng_pswd_auth_crap.old_nt_hash_enc_len =
859 params->old_password.response.old_nt_hash_enc_length;
860 }
861
862 if (params->old_password.response.old_lm_hash_enc_data) {
863 memcpy(request.data.chng_pswd_auth_crap.old_lm_hash_enc,
864 params->old_password.response.old_lm_hash_enc_data,
865 request.data.chng_pswd_auth_crap.old_lm_hash_enc_len);
866 request.data.chng_pswd_auth_crap.old_lm_hash_enc_len =
867 params->old_password.response.old_lm_hash_enc_length;
868 }
869
870 break;
871 default:
872 wbc_status = WBC_ERR_INVALID_PARAM;
873 BAIL_ON_WBC_ERROR(wbc_status);
874 break;
875 }
876
877 if (cmd == 0) {
878 wbc_status = WBC_ERR_INVALID_PARAM;
879 BAIL_ON_WBC_ERROR(wbc_status);
880 }
881
882 /* Send request */
883
884 wbc_status = wbcRequestResponse(cmd,
885 &request,
886 &response);
887 if (WBC_ERROR_IS_OK(wbc_status)) {
888 goto done;
889 }
890
891 /* Take the response above and return it to the caller */
892
893 if (response.data.auth.nt_status != 0) {
894 if (error) {
895 wbc_status = wbc_create_error_info(NULL,
896 &response,
897 error);
898 BAIL_ON_WBC_ERROR(wbc_status);
899 }
900
901 }
902
903 if (policy) {
904 wbc_status = wbc_create_password_policy_info(NULL,
905 &response,
906 policy);
907 BAIL_ON_WBC_ERROR(wbc_status);
908 }
909
910 if (reject_reason) {
911 *reject_reason = response.data.auth.reject_reason;
912 }
913
914 wbc_status = WBC_ERR_PWD_CHANGE_FAILED;
915 BAIL_ON_WBC_ERROR(wbc_status);
916
917 done:
918 return wbc_status;
919}
920
921/** @brief Change a password for a user
922 *
923 * @param username Name of user to authenticate
924 * @param old_password Old clear text password of user
925 * @param new_password New clear text password of user
926 *
927 * @return #wbcErr
928 **/
929
930wbcErr wbcChangeUserPassword(const char *username,
931 const char *old_password,
932 const char *new_password)
933{
934 wbcErr wbc_status = WBC_ERR_SUCCESS;
935 struct wbcChangePasswordParams params;
936
937 ZERO_STRUCT(params);
938
939 params.account_name = username;
940 params.level = WBC_CHANGE_PASSWORD_LEVEL_PLAIN;
941 params.old_password.plaintext = old_password;
942 params.new_password.plaintext = new_password;
943
944 wbc_status = wbcChangeUserPasswordEx(&params,
945 NULL,
946 NULL,
947 NULL);
948 BAIL_ON_WBC_ERROR(wbc_status);
949
950done:
951 return wbc_status;
952}
953
954/** @brief Logon a User
955 *
956 * @param[in] params Pointer to a wbcLogonUserParams structure
957 * @param[out] info Pointer to a pointer to a wbcLogonUserInfo structure
958 * @param[out] error Pointer to a pointer to a wbcAuthErrorInfo structure
959 * @param[out] policy Pointer to a pointer to a wbcUserPasswordPolicyInfo structure
960 *
961 * @return #wbcErr
962 *
963 **/
964
965wbcErr wbcLogonUser(const struct wbcLogonUserParams *params,
966 struct wbcLogonUserInfo **info,
967 struct wbcAuthErrorInfo **error,
968 struct wbcUserPasswordPolicyInfo **policy)
969{
970 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
971 int cmd = 0;
972 struct winbindd_request request;
973 struct winbindd_response response;
974 uint32_t i;
975
976 ZERO_STRUCT(request);
977 ZERO_STRUCT(response);
978
979 if (info) {
980 *info = NULL;
981 }
982 if (error) {
983 *error = NULL;
984 }
985 if (policy) {
986 *policy = NULL;
987 }
988
989 if (!params) {
990 wbc_status = WBC_ERR_INVALID_PARAM;
991 BAIL_ON_WBC_ERROR(wbc_status);
992 }
993
994 if (!params->username) {
995 wbc_status = WBC_ERR_INVALID_PARAM;
996 BAIL_ON_WBC_ERROR(wbc_status);
997 }
998
999 if ((params->num_blobs > 0) && (params->blobs == NULL)) {
1000 wbc_status = WBC_ERR_INVALID_PARAM;
1001 BAIL_ON_WBC_ERROR(wbc_status);
1002 }
1003 if ((params->num_blobs == 0) && (params->blobs != NULL)) {
1004 wbc_status = WBC_ERR_INVALID_PARAM;
1005 BAIL_ON_WBC_ERROR(wbc_status);
1006 }
1007
1008 /* Initialize request */
1009
1010 cmd = WINBINDD_PAM_AUTH;
1011 request.flags = WBFLAG_PAM_INFO3_TEXT |
1012 WBFLAG_PAM_USER_SESSION_KEY |
1013 WBFLAG_PAM_LMKEY;
1014
1015 if (!params->password) {
1016 wbc_status = WBC_ERR_INVALID_PARAM;
1017 BAIL_ON_WBC_ERROR(wbc_status);
1018 }
1019
1020 strncpy(request.data.auth.user,
1021 params->username,
1022 sizeof(request.data.auth.user)-1);
1023
1024 strncpy(request.data.auth.pass,
1025 params->password,
1026 sizeof(request.data.auth.pass)-1);
1027
1028 for (i=0; i<params->num_blobs; i++) {
1029
1030 if (strcasecmp(params->blobs[i].name, "krb5_cc_type") == 0) {
1031 if (params->blobs[i].blob.data) {
1032 strncpy(request.data.auth.krb5_cc_type,
1033 (const char *)params->blobs[i].blob.data,
1034 sizeof(request.data.auth.krb5_cc_type) - 1);
1035 }
1036 continue;
1037 }
1038
1039 if (strcasecmp(params->blobs[i].name, "user_uid") == 0) {
1040 if (params->blobs[i].blob.data) {
1041 memcpy(&request.data.auth.uid,
1042 params->blobs[i].blob.data,
1043 MIN(sizeof(request.data.auth.uid),
1044 params->blobs[i].blob.length));
1045 }
1046 continue;
1047 }
1048
1049 if (strcasecmp(params->blobs[i].name, "flags") == 0) {
1050 if (params->blobs[i].blob.data) {
1051 uint32_t flags;
1052 memcpy(&flags,
1053 params->blobs[i].blob.data,
1054 MIN(sizeof(flags),
1055 params->blobs[i].blob.length));
1056 request.flags |= flags;
1057 }
1058 continue;
1059 }
1060
1061 if (strcasecmp(params->blobs[i].name, "membership_of") == 0) {
1062 if (params->blobs[i].blob.data &&
1063 params->blobs[i].blob.data[0] > 0) {
1064 strncpy(request.data.auth.require_membership_of_sid,
1065 (const char *)params->blobs[i].blob.data,
1066 sizeof(request.data.auth.require_membership_of_sid) - 1);
1067 }
1068 continue;
1069 }
1070 }
1071
1072 wbc_status = wbcRequestResponse(cmd,
1073 &request,
1074 &response);
1075
1076 if (response.data.auth.nt_status != 0) {
1077 if (error) {
1078 wbc_status = wbc_create_error_info(NULL,
1079 &response,
1080 error);
1081 BAIL_ON_WBC_ERROR(wbc_status);
1082 }
1083
1084 wbc_status = WBC_ERR_AUTH_ERROR;
1085 BAIL_ON_WBC_ERROR(wbc_status);
1086 }
1087 BAIL_ON_WBC_ERROR(wbc_status);
1088
1089 if (info) {
1090 wbc_status = wbc_create_logon_info(NULL,
1091 &response,
1092 info);
1093 BAIL_ON_WBC_ERROR(wbc_status);
1094 }
1095
1096 if (policy) {
1097 wbc_status = wbc_create_password_policy_info(NULL,
1098 &response,
1099 policy);
1100 BAIL_ON_WBC_ERROR(wbc_status);
1101 }
1102
1103done:
1104 if (response.extra_data.data)
1105 free(response.extra_data.data);
1106
1107 return wbc_status;
1108}
1109
1110/** @brief Authenticate a user with cached credentials
1111 *
1112 * @param *params Pointer to a wbcCredentialCacheParams structure
1113 * @param **info Pointer to a pointer to a wbcCredentialCacheInfo structure
1114 * @param **error Pointer to a pointer to a wbcAuthErrorInfo structure
1115 *
1116 * @return #wbcErr
1117 **/
1118wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
1119 struct wbcCredentialCacheInfo **info,
1120 struct wbcAuthErrorInfo **error)
1121{
1122 return WBC_ERR_NOT_IMPLEMENTED;
1123}
Note: See TracBrowser for help on using the repository browser.