Line data Source code
1 : /*
2 : Authors:
3 : Sumit Bose <sbose@redhat.com>
4 :
5 : Copyright (C) 2009 Red Hat
6 : Copyright (C) 2010, rhafer@suse.de, Novell Inc.
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU Lesser General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU Lesser General Public License for more details.
17 :
18 : You should have received a copy of the GNU Lesser General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "config.h"
23 : #include <sys/types.h>
24 : #include <unistd.h>
25 : #include <stdlib.h>
26 : #include <stdint.h>
27 : #include <stdio.h>
28 : #include <syslog.h>
29 : #include <time.h>
30 : #include <sys/stat.h>
31 : #include <fcntl.h>
32 : #include <errno.h>
33 : #include <locale.h>
34 : #include <stdbool.h>
35 :
36 : #include <security/pam_modules.h>
37 : #include <security/pam_appl.h>
38 :
39 : #include "sss_pam_compat.h"
40 : #include "sss_pam_macros.h"
41 :
42 : #include "sss_cli.h"
43 : #include "pam_message.h"
44 : #include "util/atomic_io.h"
45 : #include "util/authtok-utils.h"
46 :
47 : #include <libintl.h>
48 : #define _(STRING) dgettext (PACKAGE, STRING)
49 :
50 : #define FLAGS_USE_FIRST_PASS (1 << 0)
51 : #define FLAGS_FORWARD_PASS (1 << 1)
52 : #define FLAGS_USE_AUTHTOK (1 << 2)
53 : #define FLAGS_IGNORE_UNKNOWN_USER (1 << 3)
54 : #define FLAGS_IGNORE_AUTHINFO_UNAVAIL (1 << 4)
55 : #define FLAGS_USE_2FA (1 << 5)
56 : #define FLAGS_ALLOW_MISSING_NAME (1 << 6)
57 :
58 : #define PWEXP_FLAG "pam_sss:password_expired_flag"
59 : #define FD_DESTRUCTOR "pam_sss:fd_destructor"
60 :
61 : #define PW_RESET_MSG_FILENAME_TEMPLATE SSSD_CONF_DIR"/customize/%s/pam_sss_pw_reset_message.%s"
62 : #define PW_RESET_MSG_MAX_SIZE 4096
63 :
64 : #define OPT_RETRY_KEY "retry="
65 : #define OPT_DOMAINS_KEY "domains="
66 :
67 : #define EXP_ACC_MSG _("Permission denied. ")
68 : #define SRV_MSG _("Server message: ")
69 :
70 : #define DEBUG_MGS_LEN 1024
71 : #define MAX_AUTHTOK_SIZE (1024*1024)
72 : #define CHECK_AND_RETURN_PI_STRING(s) ((s != NULL && *s != '\0')? s : "(not available)")
73 :
74 0 : static void logger(pam_handle_t *pamh, int level, const char *fmt, ...) {
75 : va_list ap;
76 :
77 0 : va_start(ap, fmt);
78 :
79 : #ifdef DEBUG
80 : va_list apd;
81 : char debug_msg[DEBUG_MGS_LEN];
82 : int ret;
83 : va_copy(apd, ap);
84 :
85 : ret = vsnprintf(debug_msg, DEBUG_MGS_LEN, fmt, apd);
86 : if (ret >= DEBUG_MGS_LEN) {
87 : D(("the following message is truncated: %s", debug_msg));
88 : } else if (ret < 0) {
89 : D(("vsnprintf failed to format debug message!"));
90 : } else {
91 : D((debug_msg));
92 : }
93 :
94 : va_end(apd);
95 : #endif
96 :
97 0 : pam_vsyslog(pamh, LOG_AUTHPRIV|level, fmt, ap);
98 :
99 0 : va_end(ap);
100 0 : }
101 :
102 0 : static void free_exp_data(pam_handle_t *pamh, void *ptr, int err)
103 : {
104 0 : free(ptr);
105 0 : }
106 :
107 0 : static void close_fd(pam_handle_t *pamh, void *ptr, int err)
108 : {
109 : #ifdef PAM_DATA_REPLACE
110 0 : if (err & PAM_DATA_REPLACE) {
111 : /* Nothing to do */
112 0 : return;
113 : }
114 : #endif /* PAM_DATA_REPLACE */
115 :
116 : D(("Closing the fd"));
117 0 : sss_pam_close_fd();
118 : }
119 :
120 0 : static void overwrite_and_free_authtoks(struct pam_items *pi)
121 : {
122 0 : if (pi->pam_authtok != NULL) {
123 0 : _pam_overwrite_n((void *)pi->pam_authtok, pi->pam_authtok_size);
124 0 : free((void *)pi->pam_authtok);
125 0 : pi->pam_authtok = NULL;
126 : }
127 :
128 0 : if (pi->pam_newauthtok != NULL) {
129 0 : _pam_overwrite_n((void *)pi->pam_newauthtok, pi->pam_newauthtok_size);
130 0 : free((void *)pi->pam_newauthtok);
131 0 : pi->pam_newauthtok = NULL;
132 : }
133 :
134 0 : if (pi->first_factor != NULL) {
135 0 : _pam_overwrite_n((void *)pi->first_factor, strlen(pi->first_factor));
136 0 : free((void *)pi->first_factor);
137 0 : pi->first_factor = NULL;
138 : }
139 :
140 0 : pi->pamstack_authtok = NULL;
141 0 : pi->pamstack_oldauthtok = NULL;
142 0 : }
143 :
144 0 : static void overwrite_and_free_pam_items(struct pam_items *pi)
145 : {
146 0 : overwrite_and_free_authtoks(pi);
147 :
148 0 : free(pi->domain_name);
149 0 : pi->domain_name = NULL;
150 :
151 0 : free(pi->otp_vendor);
152 0 : pi->otp_vendor = NULL;
153 :
154 0 : free(pi->otp_token_id);
155 0 : pi->otp_token_id = NULL;
156 :
157 0 : free(pi->otp_challenge);
158 0 : pi->otp_challenge = NULL;
159 :
160 0 : free(pi->cert_user);
161 0 : pi->cert_user = NULL;
162 :
163 0 : free(pi->token_name);
164 0 : pi->token_name = NULL;
165 0 : }
166 :
167 0 : static int null_strcmp(const char *s1, const char *s2) {
168 0 : if (s1 == NULL && s2 == NULL) return 0;
169 0 : if (s1 == NULL && s2 != NULL) return -1;
170 0 : if (s1 != NULL && s2 == NULL) return 1;
171 0 : return strcmp(s1, s2);
172 : }
173 :
174 : enum {
175 : SSS_PAM_CONV_DONE = 0,
176 : SSS_PAM_CONV_STD,
177 : SSS_PAM_CONV_REENTER,
178 : };
179 :
180 0 : static int do_pam_conversation(pam_handle_t *pamh, const int msg_style,
181 : const char *msg,
182 : const char *reenter_msg,
183 : char **_answer)
184 : {
185 : int ret;
186 0 : int state = SSS_PAM_CONV_STD;
187 : const struct pam_conv *conv;
188 : const struct pam_message *mesg[1];
189 : struct pam_message *pam_msg;
190 0 : struct pam_response *resp=NULL;
191 0 : char *answer = NULL;
192 :
193 0 : if ((msg_style == PAM_TEXT_INFO || msg_style == PAM_ERROR_MSG) &&
194 0 : msg == NULL) return PAM_SYSTEM_ERR;
195 :
196 0 : if ((msg_style == PAM_PROMPT_ECHO_OFF ||
197 0 : msg_style == PAM_PROMPT_ECHO_ON) &&
198 0 : (msg == NULL || _answer == NULL)) return PAM_SYSTEM_ERR;
199 :
200 0 : if (msg_style == PAM_TEXT_INFO || msg_style == PAM_ERROR_MSG) {
201 0 : logger(pamh, LOG_INFO, "User %s message: %s",
202 : msg_style == PAM_TEXT_INFO ? "info" : "error",
203 : msg);
204 : }
205 :
206 0 : ret=pam_get_item(pamh, PAM_CONV, (const void **) &conv);
207 0 : if (ret != PAM_SUCCESS) return ret;
208 :
209 : do {
210 0 : pam_msg = malloc(sizeof(struct pam_message));
211 0 : if (pam_msg == NULL) {
212 : D(("Malloc failed."));
213 0 : ret = PAM_SYSTEM_ERR;
214 0 : goto failed;
215 : }
216 :
217 0 : pam_msg->msg_style = msg_style;
218 0 : if (state == SSS_PAM_CONV_REENTER) {
219 0 : pam_msg->msg = reenter_msg;
220 : } else {
221 0 : pam_msg->msg = msg;
222 : }
223 :
224 0 : mesg[0] = (const struct pam_message *) pam_msg;
225 :
226 0 : ret=conv->conv(1, mesg, &resp,
227 0 : conv->appdata_ptr);
228 0 : free(pam_msg);
229 0 : if (ret != PAM_SUCCESS) {
230 : D(("Conversation failure: %s.", pam_strerror(pamh,ret)));
231 0 : goto failed;
232 : }
233 :
234 0 : if (msg_style == PAM_PROMPT_ECHO_OFF ||
235 : msg_style == PAM_PROMPT_ECHO_ON) {
236 0 : if (resp == NULL) {
237 : D(("response expected, but resp==NULL"));
238 0 : ret = PAM_SYSTEM_ERR;
239 0 : goto failed;
240 : }
241 :
242 0 : if (state == SSS_PAM_CONV_REENTER) {
243 0 : if (null_strcmp(answer, resp[0].resp) != 0) {
244 0 : logger(pamh, LOG_NOTICE, "Passwords do not match.");
245 0 : _pam_overwrite((void *)resp[0].resp);
246 0 : free(resp[0].resp);
247 0 : if (answer != NULL) {
248 0 : _pam_overwrite((void *) answer);
249 0 : free(answer);
250 0 : answer = NULL;
251 : }
252 0 : ret = do_pam_conversation(pamh, PAM_ERROR_MSG,
253 0 : _("Passwords do not match"),
254 : NULL, NULL);
255 0 : if (ret != PAM_SUCCESS) {
256 : D(("do_pam_conversation failed."));
257 0 : ret = PAM_SYSTEM_ERR;
258 0 : goto failed;
259 : }
260 0 : ret = PAM_CRED_ERR;
261 0 : goto failed;
262 : }
263 0 : _pam_overwrite((void *)resp[0].resp);
264 0 : free(resp[0].resp);
265 : } else {
266 0 : if (resp[0].resp == NULL) {
267 : D(("Empty password"));
268 0 : answer = NULL;
269 : } else {
270 0 : answer = strndup(resp[0].resp, MAX_AUTHTOK_SIZE);
271 0 : _pam_overwrite((void *)resp[0].resp);
272 0 : free(resp[0].resp);
273 0 : if(answer == NULL) {
274 : D(("strndup failed"));
275 0 : ret = PAM_BUF_ERR;
276 0 : goto failed;
277 : }
278 : }
279 : }
280 0 : free(resp);
281 0 : resp = NULL;
282 : }
283 :
284 0 : if (reenter_msg != NULL && state == SSS_PAM_CONV_STD) {
285 0 : state = SSS_PAM_CONV_REENTER;
286 : } else {
287 0 : state = SSS_PAM_CONV_DONE;
288 : }
289 0 : } while (state != SSS_PAM_CONV_DONE);
290 :
291 0 : if (_answer) *_answer = answer;
292 0 : return PAM_SUCCESS;
293 :
294 : failed:
295 0 : free(answer);
296 0 : return ret;
297 :
298 : }
299 :
300 0 : static errno_t display_pw_reset_message(pam_handle_t *pamh,
301 : const char *domain_name,
302 : const char *suffix)
303 : {
304 : int ret;
305 : struct stat stat_buf;
306 0 : char *msg_buf = NULL;
307 0 : int fd = -1;
308 : size_t size;
309 : size_t total_len;
310 0 : char *filename = NULL;
311 :
312 0 : if (strchr(suffix, '/') != NULL || strchr(domain_name, '/') != NULL) {
313 : D(("Suffix [%s] or domain name [%s] contain illegal character.", suffix,
314 : domain_name));
315 0 : return EINVAL;
316 : }
317 :
318 0 : size = sizeof(PW_RESET_MSG_FILENAME_TEMPLATE) + strlen(domain_name) +
319 0 : strlen(suffix);
320 0 : filename = malloc(size);
321 0 : if (filename == NULL) {
322 : D(("malloc failed."));
323 0 : ret = ENOMEM;
324 0 : goto done;
325 : }
326 0 : ret = snprintf(filename, size, PW_RESET_MSG_FILENAME_TEMPLATE, domain_name,
327 : suffix);
328 0 : if (ret < 0 || ret >= size) {
329 : D(("snprintf failed."));
330 0 : ret = EFAULT;
331 0 : goto done;
332 : }
333 :
334 0 : fd = open(filename, O_RDONLY);
335 0 : if (fd == -1) {
336 0 : ret = errno;
337 : D(("open failed [%d][%s].\n", ret, strerror(ret)));
338 0 : goto done;
339 : }
340 :
341 0 : ret = fstat(fd, &stat_buf);
342 0 : if (ret == -1) {
343 0 : ret = errno;
344 : D(("fstat failed [%d][%s].", ret, strerror(ret)));
345 0 : goto done;
346 : }
347 :
348 0 : if (!S_ISREG(stat_buf.st_mode)) {
349 0 : logger(pamh, LOG_ERR,
350 : "Password reset message file is not a regular file.");
351 0 : ret = EINVAL;
352 0 : goto done;
353 : }
354 :
355 0 : if (stat_buf.st_uid != 0 || stat_buf.st_gid != 0 ||
356 0 : (stat_buf.st_mode & ~S_IFMT) != 0644) {
357 0 : logger(pamh, LOG_ERR,"Permission error, "
358 : "file [%s] must be owned by root with permissions 0644.",
359 : filename);
360 0 : ret = EPERM;
361 0 : goto done;
362 : }
363 :
364 0 : if (stat_buf.st_size > PW_RESET_MSG_MAX_SIZE) {
365 0 : logger(pamh, LOG_ERR, "Password reset message file is too large.");
366 0 : ret = EFBIG;
367 0 : goto done;
368 : }
369 :
370 0 : msg_buf = malloc(stat_buf.st_size + 1);
371 0 : if (msg_buf == NULL) {
372 : D(("malloc failed."));
373 0 : ret = ENOMEM;
374 0 : goto done;
375 : }
376 :
377 0 : errno = 0;
378 0 : total_len = sss_atomic_read_s(fd, msg_buf, stat_buf.st_size);
379 0 : if (total_len == -1) {
380 0 : ret = errno;
381 : D(("read failed [%d][%s].", ret, strerror(ret)));
382 0 : goto done;
383 : }
384 :
385 0 : ret = close(fd);
386 0 : fd = -1;
387 0 : if (ret == -1) {
388 0 : ret = errno;
389 : D(("close failed [%d][%s].", ret, strerror(ret)));
390 : }
391 :
392 0 : if (total_len != stat_buf.st_size) {
393 : D(("read fewer bytes [%d] than expected [%d].", total_len,
394 : stat_buf.st_size));
395 0 : ret = EIO;
396 0 : goto done;
397 : }
398 :
399 0 : msg_buf[stat_buf.st_size] = '\0';
400 :
401 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, msg_buf, NULL, NULL);
402 : if (ret != PAM_SUCCESS) {
403 : D(("do_pam_conversation failed."));
404 : }
405 :
406 : done:
407 0 : if (fd != -1) {
408 0 : close(fd);
409 : }
410 0 : free(msg_buf);
411 0 : free(filename);
412 :
413 0 : return ret;
414 : }
415 :
416 0 : static errno_t select_pw_reset_message(pam_handle_t *pamh, struct pam_items *pi)
417 : {
418 : int ret;
419 : char *locale;
420 : const char *domain_name;
421 :
422 0 : domain_name = pi->domain_name;
423 0 : if (domain_name == NULL || *domain_name == '\0') {
424 : D(("Domain name is unknown."));
425 0 : return EINVAL;
426 : }
427 :
428 0 : locale = setlocale(LC_MESSAGES, NULL);
429 :
430 0 : ret = -1;
431 0 : if (locale != NULL) {
432 0 : ret = display_pw_reset_message(pamh, domain_name, locale);
433 : }
434 :
435 0 : if (ret != 0) {
436 0 : ret = display_pw_reset_message(pamh, domain_name, "txt");
437 : }
438 :
439 0 : if (ret != 0) {
440 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO,
441 0 : _("Password reset by root is not supported."),
442 : NULL, NULL);
443 : if (ret != PAM_SUCCESS) {
444 : D(("do_pam_conversation failed."));
445 : }
446 : }
447 :
448 0 : return ret;
449 : }
450 :
451 0 : static int user_info_offline_auth(pam_handle_t *pamh, size_t buflen,
452 : uint8_t *buf)
453 : {
454 : int ret;
455 : int64_t expire_date;
456 : struct tm tm;
457 : char expire_str[128];
458 : char user_msg[256];
459 :
460 0 : expire_str[0] = '\0';
461 :
462 0 : if (buflen != sizeof(uint32_t) + sizeof(int64_t)) {
463 : D(("User info response data has the wrong size"));
464 0 : return PAM_BUF_ERR;
465 : }
466 :
467 0 : memcpy(&expire_date, buf + sizeof(uint32_t), sizeof(int64_t));
468 :
469 0 : if (expire_date > 0) {
470 0 : if (localtime_r((time_t *) &expire_date, &tm) != NULL) {
471 0 : ret = strftime(expire_str, sizeof(expire_str), "%c", &tm);
472 0 : if (ret == 0) {
473 : D(("strftime failed."));
474 0 : expire_str[0] = '\0';
475 : }
476 : } else {
477 : D(("localtime_r failed"));
478 : }
479 : }
480 :
481 0 : ret = snprintf(user_msg, sizeof(user_msg), "%s%s%s.",
482 : _("Authenticated with cached credentials"),
483 0 : expire_str[0] ? _(", your cached password will expire at: ") : "",
484 0 : expire_str[0] ? expire_str : "");
485 0 : if (ret < 0 || ret >= sizeof(user_msg)) {
486 : D(("snprintf failed."));
487 0 : return PAM_SYSTEM_ERR;
488 : }
489 :
490 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
491 0 : if (ret != PAM_SUCCESS) {
492 : D(("do_pam_conversation failed."));
493 0 : return PAM_SYSTEM_ERR;
494 : }
495 :
496 0 : return PAM_SUCCESS;
497 : }
498 :
499 0 : static int user_info_grace_login(pam_handle_t *pamh,
500 : size_t buflen,
501 : uint8_t *buf)
502 : {
503 : int ret;
504 : uint32_t grace;
505 : char user_msg[256];
506 :
507 0 : if (buflen != 2* sizeof(uint32_t)) {
508 : D(("User info response data has the wrong size"));
509 0 : return PAM_BUF_ERR;
510 : }
511 0 : memcpy(&grace, buf + sizeof(uint32_t), sizeof(uint32_t));
512 0 : ret = snprintf(user_msg, sizeof(user_msg),
513 0 : _("Your password has expired. "
514 : "You have %1$d grace login(s) remaining."),
515 : grace);
516 0 : if (ret < 0 || ret >= sizeof(user_msg)) {
517 : D(("snprintf failed."));
518 0 : return PAM_SYSTEM_ERR;
519 : }
520 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
521 :
522 0 : if (ret != PAM_SUCCESS) {
523 : D(("do_pam_conversation failed."));
524 0 : return PAM_SYSTEM_ERR;
525 : }
526 :
527 0 : return PAM_SUCCESS;
528 : }
529 :
530 : #define MINSEC 60
531 : #define HOURSEC (60*MINSEC)
532 : #define DAYSEC (24*HOURSEC)
533 0 : static int user_info_expire_warn(pam_handle_t *pamh,
534 : size_t buflen,
535 : uint8_t *buf)
536 : {
537 : int ret;
538 : uint32_t expire;
539 : char user_msg[256];
540 0 : const char* unit="second(s)";
541 :
542 0 : if (buflen != 2* sizeof(uint32_t)) {
543 : D(("User info response data has the wrong size"));
544 0 : return PAM_BUF_ERR;
545 : }
546 0 : memcpy(&expire, buf + sizeof(uint32_t), sizeof(uint32_t));
547 0 : if (expire >= DAYSEC) {
548 0 : expire /= DAYSEC;
549 0 : unit = "day(s)";
550 0 : } else if (expire >= HOURSEC) {
551 0 : expire /= HOURSEC;
552 0 : unit = "hour(s)";
553 0 : } else if (expire >= MINSEC) {
554 0 : expire /= MINSEC;
555 0 : unit = "minute(s)";
556 : }
557 :
558 0 : ret = snprintf(user_msg, sizeof(user_msg),
559 0 : _("Your password will expire in %1$d %2$s."), expire, unit);
560 0 : if (ret < 0 || ret >= sizeof(user_msg)) {
561 : D(("snprintf failed."));
562 0 : return PAM_SYSTEM_ERR;
563 : }
564 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
565 :
566 0 : if (ret != PAM_SUCCESS) {
567 : D(("do_pam_conversation failed."));
568 0 : return PAM_SYSTEM_ERR;
569 : }
570 :
571 0 : return PAM_SUCCESS;
572 : }
573 :
574 0 : static int user_info_offline_auth_delayed(pam_handle_t *pamh, size_t buflen,
575 : uint8_t *buf)
576 : {
577 : int ret;
578 : int64_t delayed_until;
579 : struct tm tm;
580 : char delay_str[128];
581 : char user_msg[256];
582 :
583 0 : delay_str[0] = '\0';
584 :
585 0 : if (buflen != sizeof(uint32_t) + sizeof(int64_t)) {
586 : D(("User info response data has the wrong size"));
587 0 : return PAM_BUF_ERR;
588 : }
589 :
590 0 : memcpy(&delayed_until, buf + sizeof(uint32_t), sizeof(int64_t));
591 :
592 0 : if (delayed_until <= 0) {
593 : D(("User info response data has an invalid value"));
594 0 : return PAM_BUF_ERR;
595 : }
596 :
597 0 : if (localtime_r((time_t *) &delayed_until, &tm) != NULL) {
598 0 : ret = strftime(delay_str, sizeof(delay_str), "%c", &tm);
599 0 : if (ret == 0) {
600 : D(("strftime failed."));
601 0 : delay_str[0] = '\0';
602 : }
603 : } else {
604 : D(("localtime_r failed"));
605 : }
606 :
607 0 : ret = snprintf(user_msg, sizeof(user_msg), "%s%s.",
608 : _("Authentication is denied until: "),
609 : delay_str);
610 0 : if (ret < 0 || ret >= sizeof(user_msg)) {
611 : D(("snprintf failed."));
612 0 : return PAM_SYSTEM_ERR;
613 : }
614 :
615 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
616 0 : if (ret != PAM_SUCCESS) {
617 : D(("do_pam_conversation failed."));
618 0 : return PAM_SYSTEM_ERR;
619 : }
620 :
621 0 : return PAM_SUCCESS;
622 : }
623 :
624 0 : static int user_info_offline_chpass(pam_handle_t *pamh)
625 : {
626 : int ret;
627 :
628 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO,
629 0 : _("System is offline, password change not possible"),
630 : NULL, NULL);
631 0 : if (ret != PAM_SUCCESS) {
632 : D(("do_pam_conversation failed."));
633 0 : return PAM_SYSTEM_ERR;
634 : }
635 :
636 0 : return PAM_SUCCESS;
637 : }
638 :
639 0 : static int user_info_otp_chpass(pam_handle_t *pamh)
640 : {
641 : int ret;
642 :
643 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO,
644 0 : _("After changing the OTP password, you need to "
645 : "log out and back in order to acquire a ticket"),
646 : NULL, NULL);
647 0 : if (ret != PAM_SUCCESS) {
648 : D(("do_pam_conversation failed."));
649 0 : return PAM_SYSTEM_ERR;
650 : }
651 :
652 0 : return PAM_SUCCESS;
653 : }
654 :
655 0 : static int user_info_account_expired(pam_handle_t *pamh, size_t buflen,
656 : uint8_t *buf)
657 : {
658 : int ret;
659 : uint32_t msg_len;
660 : char *user_msg;
661 0 : size_t bufsize = 0;
662 :
663 : /* resp_type and length of message are expected to be in buf */
664 0 : if (buflen < 2* sizeof(uint32_t)) {
665 : D(("User info response data is too short"));
666 0 : return PAM_BUF_ERR;
667 : }
668 :
669 : /* msg_len = legth of message */
670 0 : memcpy(&msg_len, buf + sizeof(uint32_t), sizeof(uint32_t));
671 :
672 0 : if (buflen != 2* sizeof(uint32_t) + msg_len) {
673 : D(("User info response data has the wrong size"));
674 0 : return PAM_BUF_ERR;
675 : }
676 :
677 0 : bufsize = strlen(EXP_ACC_MSG) + 1;
678 :
679 0 : if (msg_len > 0) {
680 0 : bufsize += strlen(SRV_MSG) + msg_len;
681 : }
682 :
683 0 : user_msg = (char *)malloc(sizeof(char) * bufsize);
684 0 : if (!user_msg) {
685 : D(("Out of memory."));
686 0 : return PAM_SYSTEM_ERR;
687 : }
688 :
689 0 : ret = snprintf(user_msg, bufsize, "%s%s%.*s",
690 : EXP_ACC_MSG,
691 0 : msg_len > 0 ? SRV_MSG : "",
692 : msg_len,
693 0 : msg_len > 0 ? (char *)(buf + 2 * sizeof(uint32_t)) : "" );
694 0 : if (ret < 0 || ret > bufsize) {
695 : D(("snprintf failed."));
696 :
697 0 : free(user_msg);
698 0 : return PAM_SYSTEM_ERR;
699 : }
700 :
701 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
702 0 : free(user_msg);
703 0 : if (ret != PAM_SUCCESS) {
704 : D(("do_pam_conversation failed."));
705 :
706 0 : return PAM_SYSTEM_ERR;
707 : }
708 :
709 0 : return PAM_SUCCESS;
710 : }
711 :
712 0 : static int user_info_chpass_error(pam_handle_t *pamh, size_t buflen,
713 : uint8_t *buf)
714 : {
715 : int ret;
716 : uint32_t msg_len;
717 : char *user_msg;
718 0 : size_t bufsize = 0;
719 :
720 0 : if (buflen < 2* sizeof(uint32_t)) {
721 : D(("User info response data is too short"));
722 0 : return PAM_BUF_ERR;
723 : }
724 :
725 0 : memcpy(&msg_len, buf + sizeof(uint32_t), sizeof(uint32_t));
726 :
727 0 : if (buflen != 2* sizeof(uint32_t) + msg_len) {
728 : D(("User info response data has the wrong size"));
729 0 : return PAM_BUF_ERR;
730 : }
731 :
732 0 : bufsize = strlen(_("Password change failed. ")) + 1;
733 :
734 0 : if (msg_len > 0) {
735 0 : bufsize += strlen(_("Server message: ")) + msg_len;
736 : }
737 :
738 0 : user_msg = (char *)malloc(sizeof(char) * bufsize);
739 0 : if (!user_msg) {
740 : D(("Out of memory."));
741 0 : return PAM_SYSTEM_ERR;
742 : }
743 :
744 0 : ret = snprintf(user_msg, bufsize, "%s%s%.*s",
745 : _("Password change failed. "),
746 0 : msg_len > 0 ? _("Server message: ") : "",
747 : msg_len,
748 0 : msg_len > 0 ? (char *)(buf + 2 * sizeof(uint32_t)) : "" );
749 0 : if (ret < 0 || ret > bufsize) {
750 : D(("snprintf failed."));
751 :
752 0 : free(user_msg);
753 0 : return PAM_SYSTEM_ERR;
754 : }
755 :
756 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
757 0 : free(user_msg);
758 0 : if (ret != PAM_SUCCESS) {
759 : D(("do_pam_conversation failed."));
760 :
761 0 : return PAM_SYSTEM_ERR;
762 : }
763 :
764 0 : return PAM_SUCCESS;
765 : }
766 :
767 0 : static int eval_user_info_response(pam_handle_t *pamh, size_t buflen,
768 : uint8_t *buf)
769 : {
770 : int ret;
771 : uint32_t type;
772 :
773 0 : if (buflen < sizeof(uint32_t)) {
774 : D(("User info response data is too short"));
775 0 : return PAM_BUF_ERR;
776 : }
777 :
778 0 : memcpy(&type, buf, sizeof(uint32_t));
779 :
780 0 : switch(type) {
781 : case SSS_PAM_USER_INFO_OFFLINE_AUTH:
782 0 : ret = user_info_offline_auth(pamh, buflen, buf);
783 0 : break;
784 : case SSS_PAM_USER_INFO_GRACE_LOGIN:
785 0 : ret = user_info_grace_login(pamh, buflen, buf);
786 0 : break;
787 : case SSS_PAM_USER_INFO_EXPIRE_WARN:
788 0 : ret = user_info_expire_warn(pamh, buflen, buf);
789 0 : break;
790 : case SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED:
791 0 : ret = user_info_offline_auth_delayed(pamh, buflen, buf);
792 0 : break;
793 : case SSS_PAM_USER_INFO_OFFLINE_CHPASS:
794 0 : ret = user_info_offline_chpass(pamh);
795 0 : break;
796 : case SSS_PAM_USER_INFO_OTP_CHPASS:
797 0 : ret = user_info_otp_chpass(pamh);
798 0 : break;
799 : case SSS_PAM_USER_INFO_CHPASS_ERROR:
800 0 : ret = user_info_chpass_error(pamh, buflen, buf);
801 0 : break;
802 : case SSS_PAM_USER_INFO_ACCOUNT_EXPIRED:
803 0 : ret = user_info_account_expired(pamh, buflen, buf);
804 0 : break;
805 : default:
806 : D(("Unknown user info type [%d]", type));
807 0 : ret = PAM_SYSTEM_ERR;
808 : }
809 :
810 0 : return ret;
811 : }
812 :
813 0 : static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
814 : struct pam_items *pi)
815 : {
816 : int ret;
817 0 : size_t p=0;
818 : char *env_item;
819 : int32_t c;
820 : int32_t type;
821 : int32_t len;
822 : int32_t pam_status;
823 : size_t offset;
824 :
825 0 : if (buflen < (2*sizeof(int32_t))) {
826 : D(("response buffer is too small"));
827 0 : return PAM_BUF_ERR;
828 : }
829 :
830 0 : memcpy(&pam_status, buf+p, sizeof(int32_t));
831 0 : p += sizeof(int32_t);
832 :
833 :
834 0 : memcpy(&c, buf+p, sizeof(int32_t));
835 0 : p += sizeof(int32_t);
836 :
837 0 : while(c>0) {
838 0 : if (buflen < (p+2*sizeof(int32_t))) {
839 : D(("response buffer is too small"));
840 0 : return PAM_BUF_ERR;
841 : }
842 :
843 0 : memcpy(&type, buf+p, sizeof(int32_t));
844 0 : p += sizeof(int32_t);
845 :
846 0 : memcpy(&len, buf+p, sizeof(int32_t));
847 0 : p += sizeof(int32_t);
848 :
849 0 : if (buflen < (p + len)) {
850 : D(("response buffer is too small"));
851 0 : return PAM_BUF_ERR;
852 : }
853 :
854 0 : switch(type) {
855 : case SSS_PAM_SYSTEM_INFO:
856 0 : if (buf[p + (len -1)] != '\0') {
857 : D(("system info does not end with \\0."));
858 0 : break;
859 : }
860 0 : logger(pamh, LOG_INFO, "system info: [%s]", &buf[p]);
861 0 : break;
862 : case SSS_PAM_DOMAIN_NAME:
863 0 : if (buf[p + (len -1)] != '\0') {
864 : D(("domain name does not end with \\0."));
865 0 : break;
866 : }
867 : D(("domain name: [%s]", &buf[p]));
868 0 : pi->domain_name = strdup((char *) &buf[p]);
869 0 : if (pi->domain_name == NULL) {
870 : D(("strdup failed"));
871 : }
872 0 : break;
873 : case SSS_ENV_ITEM:
874 : case SSS_PAM_ENV_ITEM:
875 : case SSS_ALL_ENV_ITEM:
876 0 : if (buf[p + (len -1)] != '\0') {
877 : D(("env item does not end with \\0."));
878 0 : break;
879 : }
880 :
881 : D(("env item: [%s]", &buf[p]));
882 0 : if (type == SSS_PAM_ENV_ITEM || type == SSS_ALL_ENV_ITEM) {
883 0 : ret = pam_putenv(pamh, (char *)&buf[p]);
884 0 : if (ret != PAM_SUCCESS) {
885 : D(("pam_putenv failed."));
886 0 : break;
887 : }
888 : }
889 :
890 0 : if (type == SSS_ENV_ITEM || type == SSS_ALL_ENV_ITEM) {
891 0 : env_item = strdup((char *)&buf[p]);
892 0 : if (env_item == NULL) {
893 : D(("strdup failed"));
894 0 : break;
895 : }
896 0 : ret = putenv(env_item);
897 0 : if (ret == -1) {
898 : D(("putenv failed."));
899 0 : break;
900 : }
901 : }
902 0 : break;
903 : case SSS_PAM_USER_INFO:
904 0 : ret = eval_user_info_response(pamh, len, &buf[p]);
905 : if (ret != PAM_SUCCESS) {
906 : D(("eval_user_info_response failed"));
907 : }
908 0 : break;
909 : case SSS_PAM_TEXT_MSG:
910 0 : if (buf[p + (len -1)] != '\0') {
911 : D(("system info does not end with \\0."));
912 0 : break;
913 : }
914 :
915 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO, (char *) &buf[p],
916 : NULL, NULL);
917 : if (ret != PAM_SUCCESS) {
918 : D(("do_pam_conversation failed."));
919 : }
920 0 : break;
921 : case SSS_OTP:
922 : D(("OTP was used, removing authtokens."));
923 0 : overwrite_and_free_authtoks(pi);
924 0 : ret = pam_set_item(pamh, PAM_AUTHTOK, NULL);
925 : if (ret != PAM_SUCCESS) {
926 : D(("Failed to remove PAM_AUTHTOK after using otp [%s]",
927 : pam_strerror(pamh,ret)));
928 : }
929 0 : break;
930 : case SSS_PAM_OTP_INFO:
931 0 : if (buf[p + (len - 1)] != '\0') {
932 : D(("otp info does not end with \\0."));
933 0 : break;
934 : }
935 :
936 0 : pi->otp_vendor = strdup((char *) &buf[p]);
937 0 : if (pi->otp_vendor == NULL) {
938 : D(("strdup failed"));
939 0 : break;
940 : }
941 :
942 0 : offset = strlen(pi->otp_vendor) + 1;
943 0 : if (offset >= len) {
944 : D(("OTP message size mismatch"));
945 0 : free(pi->otp_vendor);
946 0 : pi->otp_vendor = NULL;
947 0 : break;
948 : }
949 0 : pi->otp_token_id = strdup((char *) &buf[p + offset]);
950 0 : if (pi->otp_token_id == NULL) {
951 : D(("strdup failed"));
952 0 : break;
953 : }
954 :
955 0 : offset += strlen(pi->otp_token_id) + 1;
956 0 : if (offset >= len) {
957 : D(("OTP message size mismatch"));
958 0 : free(pi->otp_token_id);
959 0 : pi->otp_token_id = NULL;
960 0 : break;
961 : }
962 0 : pi->otp_challenge = strdup((char *) &buf[p + offset]);
963 0 : if (pi->otp_challenge == NULL) {
964 : D(("strdup failed"));
965 0 : break;
966 : }
967 :
968 0 : break;
969 : case SSS_PAM_CERT_INFO:
970 0 : if (buf[p + (len - 1)] != '\0') {
971 : D(("cert info does not end with \\0."));
972 0 : break;
973 : }
974 :
975 0 : pi->cert_user = strdup((char *) &buf[p]);
976 0 : if (pi->cert_user == NULL) {
977 : D(("strdup failed"));
978 0 : break;
979 : }
980 :
981 0 : if (pi->pam_user == NULL || *(pi->pam_user) == '\0') {
982 0 : ret = pam_set_item(pamh, PAM_USER, pi->cert_user);
983 0 : if (ret != PAM_SUCCESS) {
984 : D(("Failed to set PAM_USER during "
985 : "Smartcard authentication [%s]",
986 : pam_strerror(pamh, ret)));
987 0 : break;
988 : }
989 :
990 0 : ret = pam_get_item(pamh, PAM_USER,
991 0 : (const void **)&(pi->pam_user));
992 0 : if (ret != PAM_SUCCESS) {
993 : D(("Failed to get PAM_USER during "
994 : "Smartcard authentication [%s]",
995 : pam_strerror(pamh, ret)));
996 0 : break;
997 : }
998 :
999 0 : pi->pam_user_size = strlen(pi->pam_user) + 1;
1000 : }
1001 :
1002 0 : offset = strlen(pi->cert_user) + 1;
1003 0 : if (offset >= len) {
1004 : D(("Cert message size mismatch"));
1005 0 : free(pi->cert_user);
1006 0 : pi->cert_user = NULL;
1007 0 : break;
1008 : }
1009 0 : pi->token_name = strdup((char *) &buf[p + offset]);
1010 0 : if (pi->token_name == NULL) {
1011 : D(("strdup failed"));
1012 0 : break;
1013 : }
1014 : D(("cert user: [%s] token name: [%s]", pi->cert_user,
1015 : pi->token_name));
1016 0 : break;
1017 : default:
1018 : D(("Unknown response type [%d]", type));
1019 : }
1020 0 : p += len;
1021 :
1022 0 : --c;
1023 : }
1024 :
1025 0 : return PAM_SUCCESS;
1026 : }
1027 :
1028 0 : static int get_pam_items(pam_handle_t *pamh, uint32_t flags,
1029 : struct pam_items *pi)
1030 : {
1031 : int ret;
1032 :
1033 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
1034 0 : pi->pam_authtok = NULL;
1035 0 : pi->pam_authtok_size = 0;
1036 0 : pi->pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY;
1037 0 : pi->pam_newauthtok = NULL;
1038 0 : pi->pam_newauthtok_size = 0;
1039 0 : pi->first_factor = NULL;
1040 :
1041 0 : ret = pam_get_item(pamh, PAM_SERVICE, (const void **) &(pi->pam_service));
1042 0 : if (ret != PAM_SUCCESS) return ret;
1043 0 : if (pi->pam_service == NULL) pi->pam_service="";
1044 0 : pi->pam_service_size=strlen(pi->pam_service)+1;
1045 :
1046 0 : ret = pam_get_item(pamh, PAM_USER, (const void **) &(pi->pam_user));
1047 0 : if (ret == PAM_PERM_DENIED && (flags & FLAGS_ALLOW_MISSING_NAME)) {
1048 0 : pi->pam_user = "";
1049 0 : ret = PAM_SUCCESS;
1050 : }
1051 0 : if (ret != PAM_SUCCESS) return ret;
1052 0 : if (pi->pam_user == NULL) {
1053 0 : if (flags & FLAGS_ALLOW_MISSING_NAME) {
1054 0 : pi->pam_user = "";
1055 : } else {
1056 : D(("No user found, aborting."));
1057 0 : return PAM_BAD_ITEM;
1058 : }
1059 : }
1060 0 : if (strcmp(pi->pam_user, "root") == 0) {
1061 : D(("pam_sss will not handle root."));
1062 0 : return PAM_USER_UNKNOWN;
1063 : }
1064 0 : pi->pam_user_size=strlen(pi->pam_user)+1;
1065 :
1066 :
1067 0 : ret = pam_get_item(pamh, PAM_TTY, (const void **) &(pi->pam_tty));
1068 0 : if (ret != PAM_SUCCESS) return ret;
1069 0 : if (pi->pam_tty == NULL) pi->pam_tty="";
1070 0 : pi->pam_tty_size=strlen(pi->pam_tty)+1;
1071 :
1072 0 : ret = pam_get_item(pamh, PAM_RUSER, (const void **) &(pi->pam_ruser));
1073 0 : if (ret != PAM_SUCCESS) return ret;
1074 0 : if (pi->pam_ruser == NULL) pi->pam_ruser="";
1075 0 : pi->pam_ruser_size=strlen(pi->pam_ruser)+1;
1076 :
1077 0 : ret = pam_get_item(pamh, PAM_RHOST, (const void **) &(pi->pam_rhost));
1078 0 : if (ret != PAM_SUCCESS) return ret;
1079 0 : if (pi->pam_rhost == NULL) pi->pam_rhost="";
1080 0 : pi->pam_rhost_size=strlen(pi->pam_rhost)+1;
1081 :
1082 0 : ret = pam_get_item(pamh, PAM_AUTHTOK,
1083 0 : (const void **) &(pi->pamstack_authtok));
1084 0 : if (ret != PAM_SUCCESS) return ret;
1085 0 : if (pi->pamstack_authtok == NULL) pi->pamstack_authtok="";
1086 :
1087 0 : ret = pam_get_item(pamh, PAM_OLDAUTHTOK,
1088 0 : (const void **) &(pi->pamstack_oldauthtok));
1089 0 : if (ret != PAM_SUCCESS) return ret;
1090 0 : if (pi->pamstack_oldauthtok == NULL) pi->pamstack_oldauthtok="";
1091 :
1092 0 : pi->cli_pid = getpid();
1093 :
1094 0 : pi->login_name = pam_modutil_getlogin(pamh);
1095 0 : if (pi->login_name == NULL) pi->login_name="";
1096 :
1097 0 : pi->domain_name = NULL;
1098 :
1099 0 : if (pi->requested_domains == NULL) pi->requested_domains = "";
1100 0 : pi->requested_domains_size = strlen(pi->requested_domains) + 1;
1101 :
1102 0 : pi->otp_vendor = NULL;
1103 0 : pi->otp_token_id = NULL;
1104 0 : pi->otp_challenge = NULL;
1105 :
1106 0 : pi->cert_user = NULL;
1107 0 : pi->token_name = NULL;
1108 :
1109 0 : return PAM_SUCCESS;
1110 : }
1111 :
1112 0 : static void print_pam_items(struct pam_items *pi)
1113 : {
1114 0 : if (pi == NULL) return;
1115 :
1116 : D(("Service: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_service)));
1117 : D(("User: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_user)));
1118 : D(("Tty: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_tty)));
1119 : D(("Ruser: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_ruser)));
1120 : D(("Rhost: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_rhost)));
1121 : D(("Pamstack_Authtok: %s",
1122 : CHECK_AND_RETURN_PI_STRING(pi->pamstack_authtok)));
1123 : D(("Pamstack_Oldauthtok: %s",
1124 : CHECK_AND_RETURN_PI_STRING(pi->pamstack_oldauthtok)));
1125 : D(("Authtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_authtok)));
1126 : D(("Newauthtok: %s", CHECK_AND_RETURN_PI_STRING(pi->pam_newauthtok)));
1127 : D(("Cli_PID: %d", pi->cli_pid));
1128 : D(("Requested domains: %s", pi->requested_domains));
1129 : }
1130 :
1131 0 : static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
1132 : enum sss_cli_command task, bool quiet_mode)
1133 : {
1134 : int ret;
1135 : int sret;
1136 : int errnop;
1137 : struct sss_cli_req_data rd;
1138 0 : uint8_t *buf = NULL;
1139 0 : uint8_t *repbuf = NULL;
1140 : size_t replen;
1141 0 : int pam_status = PAM_SYSTEM_ERR;
1142 :
1143 0 : print_pam_items(pi);
1144 :
1145 0 : ret = pack_message_v3(pi, &rd.len, &buf);
1146 0 : if (ret != 0) {
1147 : D(("pack_message failed."));
1148 0 : pam_status = PAM_SYSTEM_ERR;
1149 0 : goto done;
1150 : }
1151 0 : rd.data = buf;
1152 :
1153 0 : errnop = 0;
1154 0 : ret = sss_pam_make_request(task, &rd, &repbuf, &replen, &errnop);
1155 :
1156 0 : sret = pam_set_data(pamh, FD_DESTRUCTOR, NULL, close_fd);
1157 : if (sret != PAM_SUCCESS) {
1158 : D(("pam_set_data failed, client might leaks fds"));
1159 : }
1160 :
1161 0 : if (ret != PAM_SUCCESS) {
1162 0 : if (errnop != 0) {
1163 0 : logger(pamh, LOG_ERR, "Request to sssd failed. %s", ssscli_err2string(errnop));
1164 : }
1165 0 : pam_status = PAM_AUTHINFO_UNAVAIL;
1166 0 : goto done;
1167 : }
1168 :
1169 : /* FIXME: add an end signature */
1170 0 : if (replen < (2*sizeof(int32_t))) {
1171 : D(("response not in expected format."));
1172 0 : pam_status = PAM_SYSTEM_ERR;
1173 0 : goto done;
1174 : }
1175 :
1176 0 : SAFEALIGN_COPY_UINT32(&pam_status, repbuf, NULL);
1177 0 : ret = eval_response(pamh, replen, repbuf, pi);
1178 0 : if (ret != PAM_SUCCESS) {
1179 : D(("eval_response failed."));
1180 0 : pam_status = ret;
1181 0 : goto done;
1182 : }
1183 :
1184 0 : switch (task) {
1185 : case SSS_PAM_AUTHENTICATE:
1186 0 : logger(pamh, (pam_status == PAM_SUCCESS ? LOG_INFO : LOG_NOTICE),
1187 : "authentication %s; logname=%s uid=%lu euid=%d tty=%s "
1188 : "ruser=%s rhost=%s user=%s",
1189 0 : pam_status == PAM_SUCCESS ? "success" : "failure",
1190 0 : pi->login_name, getuid(), (unsigned long) geteuid(),
1191 : pi->pam_tty, pi->pam_ruser, pi->pam_rhost, pi->pam_user);
1192 0 : if (pam_status != PAM_SUCCESS) {
1193 : /* don't log if quiet_mode is on and pam_status is
1194 : * User not known to the underlying authentication module
1195 : */
1196 0 : if (!quiet_mode || pam_status != 10) {
1197 0 : logger(pamh, LOG_NOTICE, "received for user %s: %d (%s)",
1198 : pi->pam_user, pam_status,
1199 : pam_strerror(pamh,pam_status));
1200 : }
1201 : }
1202 0 : break;
1203 : case SSS_PAM_CHAUTHTOK_PRELIM:
1204 0 : if (pam_status != PAM_SUCCESS) {
1205 : /* don't log if quiet_mode is on and pam_status is
1206 : * User not known to the underlying authentication module
1207 : */
1208 0 : if (!quiet_mode || pam_status != 10) {
1209 0 : logger(pamh, LOG_NOTICE,
1210 : "Authentication failed for user %s: %d (%s)",
1211 : pi->pam_user, pam_status,
1212 : pam_strerror(pamh,pam_status));
1213 : }
1214 : }
1215 0 : break;
1216 : case SSS_PAM_CHAUTHTOK:
1217 0 : if (pam_status != PAM_SUCCESS) {
1218 0 : logger(pamh, LOG_NOTICE,
1219 : "Password change failed for user %s: %d (%s)",
1220 : pi->pam_user, pam_status,
1221 : pam_strerror(pamh,pam_status));
1222 : }
1223 0 : break;
1224 : case SSS_PAM_ACCT_MGMT:
1225 0 : if (pam_status != PAM_SUCCESS) {
1226 : /* don't log if quiet_mode is on and pam_status is
1227 : * User not known to the underlying authentication module
1228 : */
1229 0 : if (!quiet_mode || pam_status != 10) {
1230 0 : logger(pamh, LOG_NOTICE,
1231 : "Access denied for user %s: %d (%s)",
1232 : pi->pam_user, pam_status,
1233 : pam_strerror(pamh,pam_status));
1234 : }
1235 : }
1236 0 : break;
1237 : case SSS_PAM_OPEN_SESSION:
1238 : case SSS_PAM_SETCRED:
1239 : case SSS_PAM_CLOSE_SESSION:
1240 : case SSS_PAM_PREAUTH:
1241 0 : break;
1242 : default:
1243 : D(("Illegal task [%#x]", task));
1244 0 : return PAM_SYSTEM_ERR;
1245 : }
1246 :
1247 : done:
1248 0 : if (buf != NULL ) {
1249 0 : _pam_overwrite_n((void *)buf, rd.len);
1250 0 : free(buf);
1251 : }
1252 0 : free(repbuf);
1253 :
1254 0 : return pam_status;
1255 : }
1256 :
1257 0 : static int prompt_password(pam_handle_t *pamh, struct pam_items *pi,
1258 : const char *prompt)
1259 : {
1260 : int ret;
1261 0 : char *answer = NULL;
1262 :
1263 0 : ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer);
1264 0 : if (ret != PAM_SUCCESS) {
1265 : D(("do_pam_conversation failed."));
1266 0 : return ret;
1267 : }
1268 :
1269 0 : if (answer == NULL) {
1270 0 : pi->pam_authtok = NULL;
1271 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
1272 0 : pi->pam_authtok_size=0;
1273 : } else {
1274 0 : pi->pam_authtok = strdup(answer);
1275 0 : _pam_overwrite((void *)answer);
1276 0 : free(answer);
1277 0 : answer=NULL;
1278 0 : if (pi->pam_authtok == NULL) {
1279 0 : return PAM_BUF_ERR;
1280 : }
1281 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
1282 0 : pi->pam_authtok_size=strlen(pi->pam_authtok);
1283 : }
1284 :
1285 0 : return PAM_SUCCESS;
1286 : }
1287 :
1288 0 : static int prompt_2fa(pam_handle_t *pamh, struct pam_items *pi,
1289 : const char *prompt_fa1, const char *prompt_fa2)
1290 : {
1291 : int ret;
1292 : const struct pam_conv *conv;
1293 0 : const struct pam_message *mesg[2] = { NULL, NULL };
1294 0 : struct pam_message m[2] = { {0}, {0} };
1295 0 : struct pam_response *resp = NULL;
1296 : size_t needed_size;
1297 :
1298 0 : ret = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
1299 0 : if (ret != PAM_SUCCESS) {
1300 0 : return ret;
1301 : }
1302 :
1303 0 : m[0].msg_style = PAM_PROMPT_ECHO_OFF;
1304 0 : m[0].msg = prompt_fa1;
1305 0 : m[1].msg_style = PAM_PROMPT_ECHO_OFF;
1306 0 : m[1].msg = prompt_fa2;
1307 :
1308 0 : mesg[0] = (const struct pam_message *) m;
1309 : /* The following assignment might look a bit odd but is recommended in the
1310 : * pam_conv man page to make sure that the second argument of the PAM
1311 : * conversation function can be interpreted in two different ways.
1312 : * Basically it is important that both the actual struct pam_message and
1313 : * the pointers to the struct pam_message are arrays. Since the assignment
1314 : * makes clear that mesg[] and (*mesg)[] are arrays it should be kept this
1315 : * way and not be replaced by other equivalent assignments. */
1316 0 : mesg[1] = & (( *mesg )[1]);
1317 :
1318 0 : ret = conv->conv(2, mesg, &resp, conv->appdata_ptr);
1319 0 : if (ret != PAM_SUCCESS) {
1320 : D(("Conversation failure: %s.", pam_strerror(pamh, ret)));
1321 0 : return ret;
1322 : }
1323 :
1324 0 : if (resp == NULL) {
1325 : D(("response expected, but resp==NULL"));
1326 0 : return PAM_SYSTEM_ERR;
1327 : }
1328 :
1329 0 : if (resp[0].resp == NULL || *(resp[0].resp) == '\0') {
1330 : D(("Missing factor."));
1331 0 : ret = PAM_CRED_INSUFFICIENT;
1332 0 : goto done;
1333 : }
1334 :
1335 0 : if (resp[1].resp == NULL || *(resp[1].resp) == '\0'
1336 0 : || (pi->pam_service != NULL && strcmp(pi->pam_service, "sshd") == 0
1337 0 : && strcmp(resp[0].resp, resp[1].resp) == 0)) {
1338 : /* Missing second factor, assume first factor contains combined 2FA
1339 : * credentials.
1340 : * Special handling for SSH with password authentication. Combined
1341 : * 2FA credentials are used but SSH puts them in both responses. */
1342 :
1343 0 : pi->pam_authtok = strndup(resp[0].resp, MAX_AUTHTOK_SIZE);
1344 0 : if (pi->pam_authtok == NULL) {
1345 : D(("strndup failed."));
1346 0 : ret = PAM_BUF_ERR;
1347 0 : goto done;
1348 : }
1349 0 : pi->pam_authtok_size = strlen(pi->pam_authtok) + 1;
1350 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
1351 : } else {
1352 :
1353 0 : ret = sss_auth_pack_2fa_blob(resp[0].resp, 0, resp[1].resp, 0, NULL, 0,
1354 : &needed_size);
1355 0 : if (ret != EAGAIN) {
1356 : D(("sss_auth_pack_2fa_blob failed."));
1357 0 : ret = PAM_BUF_ERR;
1358 0 : goto done;
1359 : }
1360 :
1361 0 : pi->pam_authtok = malloc(needed_size);
1362 0 : if (pi->pam_authtok == NULL) {
1363 : D(("malloc failed."));
1364 0 : ret = PAM_BUF_ERR;
1365 0 : goto done;
1366 : }
1367 :
1368 0 : ret = sss_auth_pack_2fa_blob(resp[0].resp, 0, resp[1].resp, 0,
1369 0 : (uint8_t *) pi->pam_authtok, needed_size,
1370 : &needed_size);
1371 0 : if (ret != EOK) {
1372 : D(("sss_auth_pack_2fa_blob failed."));
1373 0 : ret = PAM_BUF_ERR;
1374 0 : goto done;
1375 : }
1376 :
1377 0 : pi->pam_authtok_size = needed_size;
1378 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_2FA;
1379 0 : pi->first_factor = strndup(resp[0].resp, MAX_AUTHTOK_SIZE);
1380 0 : if (pi->first_factor == NULL) {
1381 : D(("strndup failed."));
1382 0 : ret = PAM_BUF_ERR;
1383 0 : goto done;
1384 : }
1385 : }
1386 :
1387 0 : ret = PAM_SUCCESS;
1388 :
1389 : done:
1390 0 : if (resp != NULL) {
1391 0 : if (resp[0].resp != NULL) {
1392 0 : _pam_overwrite((void *)resp[0].resp);
1393 0 : free(resp[0].resp);
1394 : }
1395 0 : if (resp[1].resp != NULL) {
1396 0 : _pam_overwrite((void *)resp[1].resp);
1397 0 : free(resp[1].resp);
1398 : }
1399 :
1400 0 : free(resp);
1401 0 : resp = NULL;
1402 : }
1403 :
1404 0 : return ret;
1405 : }
1406 :
1407 : #define SC_PROMPT_FMT "PIN for %s for user %s"
1408 0 : static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi)
1409 : {
1410 : int ret;
1411 0 : char *answer = NULL;
1412 : char *prompt;
1413 : size_t size;
1414 :
1415 0 : if (pi->token_name == NULL || *pi->token_name == '\0'
1416 0 : || pi->cert_user == NULL || *pi->cert_user == '\0') {
1417 0 : return EINVAL;
1418 : }
1419 :
1420 0 : size = sizeof(SC_PROMPT_FMT) + strlen(pi->token_name) +
1421 0 : strlen(pi->cert_user);
1422 0 : prompt = malloc(size);
1423 0 : if (prompt == NULL) {
1424 : D(("malloc failed."));
1425 0 : return ENOMEM;
1426 : }
1427 :
1428 0 : ret = snprintf(prompt, size, SC_PROMPT_FMT, pi->token_name, pi->cert_user);
1429 0 : if (ret < 0 || ret >= size) {
1430 : D(("snprintf failed."));
1431 0 : free(prompt);
1432 0 : return EFAULT;
1433 : }
1434 :
1435 0 : ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer);
1436 0 : free(prompt);
1437 0 : if (ret != PAM_SUCCESS) {
1438 : D(("do_pam_conversation failed."));
1439 0 : return ret;
1440 : }
1441 :
1442 0 : if (answer == NULL) {
1443 0 : pi->pam_authtok = NULL;
1444 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
1445 0 : pi->pam_authtok_size=0;
1446 : } else {
1447 0 : pi->pam_authtok = strdup(answer);
1448 0 : _pam_overwrite((void *)answer);
1449 0 : free(answer);
1450 0 : answer=NULL;
1451 0 : if (pi->pam_authtok == NULL) {
1452 0 : return PAM_BUF_ERR;
1453 : }
1454 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_SC_PIN;
1455 0 : pi->pam_authtok_size=strlen(pi->pam_authtok);
1456 : }
1457 :
1458 0 : return PAM_SUCCESS;
1459 : }
1460 :
1461 0 : static int prompt_new_password(pam_handle_t *pamh, struct pam_items *pi)
1462 : {
1463 : int ret;
1464 0 : char *answer = NULL;
1465 :
1466 0 : ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF,
1467 0 : _("New Password: "),
1468 0 : _("Reenter new Password: "),
1469 : &answer);
1470 0 : if (ret != PAM_SUCCESS) {
1471 : D(("do_pam_conversation failed."));
1472 0 : return ret;
1473 : }
1474 0 : if (answer == NULL) {
1475 0 : pi->pam_newauthtok = NULL;
1476 0 : pi->pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY;
1477 0 : pi->pam_newauthtok_size=0;
1478 : } else {
1479 0 : pi->pam_newauthtok = strdup(answer);
1480 0 : _pam_overwrite((void *)answer);
1481 0 : free(answer);
1482 0 : answer=NULL;
1483 0 : if (pi->pam_newauthtok == NULL) {
1484 0 : return PAM_BUF_ERR;
1485 : }
1486 0 : pi->pam_newauthtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
1487 0 : pi->pam_newauthtok_size=strlen(pi->pam_newauthtok);
1488 : }
1489 :
1490 0 : return PAM_SUCCESS;
1491 : }
1492 :
1493 0 : static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
1494 : uint32_t *flags, int *retries, bool *quiet_mode,
1495 : const char **domains)
1496 : {
1497 : char *ep;
1498 :
1499 0 : *quiet_mode = false;
1500 :
1501 0 : for (; argc-- > 0; ++argv) {
1502 0 : if (strcmp(*argv, "forward_pass") == 0) {
1503 0 : *flags |= FLAGS_FORWARD_PASS;
1504 0 : } else if (strcmp(*argv, "use_first_pass") == 0) {
1505 0 : *flags |= FLAGS_USE_FIRST_PASS;
1506 0 : } else if (strcmp(*argv, "use_authtok") == 0) {
1507 0 : *flags |= FLAGS_USE_AUTHTOK;
1508 0 : } else if (strncmp(*argv, OPT_DOMAINS_KEY, strlen(OPT_DOMAINS_KEY)) == 0) {
1509 0 : if (*(*argv+strlen(OPT_DOMAINS_KEY)) == '\0') {
1510 0 : logger(pamh, LOG_ERR, "Missing argument to option domains.");
1511 0 : *domains = "";
1512 : } else {
1513 0 : *domains = *argv+strlen(OPT_DOMAINS_KEY);
1514 : }
1515 :
1516 0 : } else if (strncmp(*argv, OPT_RETRY_KEY, strlen(OPT_RETRY_KEY)) == 0) {
1517 0 : if (*(*argv+6) == '\0') {
1518 0 : logger(pamh, LOG_ERR, "Missing argument to option retry.");
1519 0 : *retries = 0;
1520 : } else {
1521 0 : errno = 0;
1522 0 : *retries = strtol(*argv+6, &ep, 10);
1523 0 : if (errno != 0) {
1524 : D(("strtol failed [%d][%s]", errno, strerror(errno)));
1525 0 : *retries = 0;
1526 : }
1527 0 : if (*ep != '\0') {
1528 0 : logger(pamh, LOG_ERR, "Argument to option retry contains "
1529 : "extra characters.");
1530 0 : *retries = 0;
1531 : }
1532 0 : if (*retries < 0) {
1533 0 : logger(pamh, LOG_ERR, "Argument to option retry must not "
1534 : "be negative.");
1535 0 : *retries = 0;
1536 : }
1537 : }
1538 0 : } else if (strcmp(*argv, "quiet") == 0) {
1539 0 : *quiet_mode = true;
1540 0 : } else if (strcmp(*argv, "ignore_unknown_user") == 0) {
1541 0 : *flags |= FLAGS_IGNORE_UNKNOWN_USER;
1542 0 : } else if (strcmp(*argv, "ignore_authinfo_unavail") == 0) {
1543 0 : *flags |= FLAGS_IGNORE_AUTHINFO_UNAVAIL;
1544 0 : } else if (strcmp(*argv, "use_2fa") == 0) {
1545 0 : *flags |= FLAGS_USE_2FA;
1546 0 : } else if (strcmp(*argv, "allow_missing_name") == 0) {
1547 0 : *flags |= FLAGS_ALLOW_MISSING_NAME;
1548 : } else {
1549 0 : logger(pamh, LOG_WARNING, "unknown option: %s", *argv);
1550 : }
1551 : }
1552 :
1553 0 : return;
1554 : }
1555 :
1556 0 : static int get_authtok_for_authentication(pam_handle_t *pamh,
1557 : struct pam_items *pi,
1558 : uint32_t flags)
1559 : {
1560 : int ret;
1561 :
1562 0 : if (flags & FLAGS_USE_FIRST_PASS) {
1563 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
1564 0 : pi->pam_authtok = strdup(pi->pamstack_authtok);
1565 0 : if (pi->pam_authtok == NULL) {
1566 : D(("option use_first_pass set, but no password found"));
1567 0 : return PAM_BUF_ERR;
1568 : }
1569 0 : pi->pam_authtok_size = strlen(pi->pam_authtok);
1570 : } else {
1571 0 : if (flags & FLAGS_USE_2FA
1572 0 : || (pi->otp_vendor != NULL && pi->otp_token_id != NULL
1573 0 : && pi->otp_challenge != NULL)) {
1574 0 : ret = prompt_2fa(pamh, pi, _("First Factor: "),
1575 0 : _("Second Factor: "));
1576 0 : } else if (pi->cert_user != NULL) {
1577 0 : ret = prompt_sc_pin(pamh, pi);
1578 : } else {
1579 0 : ret = prompt_password(pamh, pi, _("Password: "));
1580 : }
1581 0 : if (ret != PAM_SUCCESS) {
1582 : D(("failed to get password from user"));
1583 0 : return ret;
1584 : }
1585 :
1586 0 : if (flags & FLAGS_FORWARD_PASS) {
1587 0 : if (pi->pam_authtok_type == SSS_AUTHTOK_TYPE_PASSWORD) {
1588 0 : ret = pam_set_item(pamh, PAM_AUTHTOK, pi->pam_authtok);
1589 0 : } else if (pi->pam_authtok_type == SSS_AUTHTOK_TYPE_2FA
1590 0 : && pi->first_factor != NULL) {
1591 0 : ret = pam_set_item(pamh, PAM_AUTHTOK, pi->first_factor);
1592 : } else {
1593 0 : ret = EINVAL;
1594 : }
1595 : if (ret != PAM_SUCCESS) {
1596 : D(("Failed to set PAM_AUTHTOK [%s], "
1597 : "authtok may not be available for other modules",
1598 : pam_strerror(pamh,ret)));
1599 : }
1600 : }
1601 : }
1602 :
1603 0 : return PAM_SUCCESS;
1604 : }
1605 :
1606 0 : static int get_authtok_for_password_change(pam_handle_t *pamh,
1607 : struct pam_items *pi,
1608 : uint32_t flags,
1609 : int pam_flags)
1610 : {
1611 : int ret;
1612 0 : const int *exp_data = NULL;
1613 0 : pam_get_data(pamh, PWEXP_FLAG, (const void **) &exp_data);
1614 :
1615 : /* we query for the old password during PAM_PRELIM_CHECK to make
1616 : * pam_sss work e.g. with pam_cracklib */
1617 0 : if (pam_flags & PAM_PRELIM_CHECK) {
1618 0 : if ( (getuid() != 0 || exp_data ) && !(flags & FLAGS_USE_FIRST_PASS)) {
1619 0 : ret = prompt_password(pamh, pi, _("Current Password: "));
1620 0 : if (ret != PAM_SUCCESS) {
1621 : D(("failed to get password from user"));
1622 0 : return ret;
1623 : }
1624 :
1625 0 : ret = pam_set_item(pamh, PAM_OLDAUTHTOK, pi->pam_authtok);
1626 0 : if (ret != PAM_SUCCESS) {
1627 : D(("Failed to set PAM_OLDAUTHTOK [%s], "
1628 : "oldauthtok may not be available",
1629 : pam_strerror(pamh,ret)));
1630 0 : return ret;
1631 : }
1632 : }
1633 :
1634 0 : return PAM_SUCCESS;
1635 : }
1636 :
1637 0 : if (pi->pamstack_oldauthtok == NULL) {
1638 0 : if (getuid() != 0) {
1639 : D(("no password found for chauthtok"));
1640 0 : return PAM_BUF_ERR;
1641 : } else {
1642 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
1643 0 : pi->pam_authtok = NULL;
1644 0 : pi->pam_authtok_size = 0;
1645 : }
1646 : } else {
1647 0 : pi->pam_authtok = strdup(pi->pamstack_oldauthtok);
1648 0 : if (pi->pam_authtok == NULL) {
1649 : D(("strdup failed"));
1650 0 : return PAM_BUF_ERR;
1651 : }
1652 0 : pi->pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
1653 0 : pi->pam_authtok_size = strlen(pi->pam_authtok);
1654 : }
1655 :
1656 0 : if (flags & FLAGS_USE_AUTHTOK) {
1657 0 : pi->pam_newauthtok_type = SSS_AUTHTOK_TYPE_PASSWORD;
1658 0 : pi->pam_newauthtok = strdup(pi->pamstack_authtok);
1659 0 : if (pi->pam_newauthtok == NULL) {
1660 : D(("option use_authtok set, but no new password found"));
1661 0 : return PAM_BUF_ERR;
1662 : }
1663 0 : pi->pam_newauthtok_size = strlen(pi->pam_newauthtok);
1664 : } else {
1665 0 : ret = prompt_new_password(pamh, pi);
1666 0 : if (ret != PAM_SUCCESS) {
1667 : D(("failed to get new password from user"));
1668 0 : return ret;
1669 : }
1670 :
1671 0 : if (flags & FLAGS_FORWARD_PASS) {
1672 0 : ret = pam_set_item(pamh, PAM_AUTHTOK, pi->pam_newauthtok);
1673 : if (ret != PAM_SUCCESS) {
1674 : D(("Failed to set PAM_AUTHTOK [%s], "
1675 : "oldauthtok may not be available",
1676 : pam_strerror(pamh,ret)));
1677 : }
1678 : }
1679 : }
1680 :
1681 0 : return PAM_SUCCESS;
1682 : }
1683 :
1684 0 : static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
1685 : int pam_flags, int argc, const char **argv)
1686 : {
1687 : int ret;
1688 : int pam_status;
1689 : struct pam_items pi;
1690 0 : uint32_t flags = 0;
1691 : const int *exp_data;
1692 : int *pw_exp_data;
1693 0 : bool retry = false;
1694 0 : bool quiet_mode = false;
1695 0 : int retries = 0;
1696 0 : const char *domains = NULL;
1697 :
1698 0 : bindtextdomain(PACKAGE, LOCALEDIR);
1699 :
1700 : D(("Hello pam_sssd: %#x", task));
1701 :
1702 0 : eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode, &domains);
1703 :
1704 : /* Fail all authentication on misconfigured domains= parameter. The admin
1705 : * probably wanted to restrict authentication, so it's safer to fail */
1706 0 : if (domains && strcmp(domains, "") == 0) {
1707 0 : return PAM_SYSTEM_ERR;
1708 : }
1709 :
1710 0 : pi.requested_domains = domains;
1711 :
1712 0 : ret = get_pam_items(pamh, flags, &pi);
1713 0 : if (ret != PAM_SUCCESS) {
1714 : D(("get items returned error: %s", pam_strerror(pamh,ret)));
1715 0 : if (flags & FLAGS_IGNORE_UNKNOWN_USER && ret == PAM_USER_UNKNOWN) {
1716 0 : ret = PAM_IGNORE;
1717 : }
1718 0 : if (flags & FLAGS_IGNORE_AUTHINFO_UNAVAIL
1719 0 : && ret == PAM_AUTHINFO_UNAVAIL) {
1720 0 : ret = PAM_IGNORE;
1721 : }
1722 0 : return ret;
1723 : }
1724 :
1725 : do {
1726 0 : retry = false;
1727 :
1728 0 : switch(task) {
1729 : case SSS_PAM_AUTHENTICATE:
1730 : /*
1731 : * Only do preauth if
1732 : * - FLAGS_USE_FIRST_PASS is not set
1733 : * - no password is on the stack
1734 : * - preauth indicator file exists.
1735 : */
1736 0 : if ( !(flags & FLAGS_USE_FIRST_PASS) && pi.pam_authtok == NULL
1737 0 : && access(PAM_PREAUTH_INDICATOR, F_OK) == 0) {
1738 0 : pam_status = send_and_receive(pamh, &pi, SSS_PAM_PREAUTH,
1739 : quiet_mode);
1740 : if (pam_status != PAM_SUCCESS) {
1741 : D(("send_and_receive returned [%d] during pre-auth",
1742 : pam_status));
1743 : /*
1744 : * Since we are only interested in the result message
1745 : * and will always use password authentication
1746 : * as a fallback, errors can be ignored here.
1747 : */
1748 : }
1749 : }
1750 :
1751 0 : ret = get_authtok_for_authentication(pamh, &pi, flags);
1752 0 : if (ret != PAM_SUCCESS) {
1753 : D(("failed to get authentication token: %s",
1754 : pam_strerror(pamh, ret)));
1755 0 : return ret;
1756 : }
1757 0 : break;
1758 : case SSS_PAM_CHAUTHTOK:
1759 0 : ret = get_authtok_for_password_change(pamh, &pi, flags, pam_flags);
1760 0 : if (ret != PAM_SUCCESS) {
1761 : D(("failed to get tokens for password change: %s",
1762 : pam_strerror(pamh, ret)));
1763 0 : overwrite_and_free_pam_items(&pi);
1764 0 : return ret;
1765 : }
1766 0 : if (pam_flags & PAM_PRELIM_CHECK) {
1767 0 : task = SSS_PAM_CHAUTHTOK_PRELIM;
1768 : }
1769 0 : break;
1770 : case SSS_PAM_ACCT_MGMT:
1771 : case SSS_PAM_SETCRED:
1772 : case SSS_PAM_OPEN_SESSION:
1773 : case SSS_PAM_CLOSE_SESSION:
1774 0 : break;
1775 : default:
1776 : D(("Illegal task [%#x]", task));
1777 0 : return PAM_SYSTEM_ERR;
1778 : }
1779 :
1780 0 : pam_status = send_and_receive(pamh, &pi, task, quiet_mode);
1781 :
1782 0 : if (flags & FLAGS_IGNORE_UNKNOWN_USER
1783 0 : && pam_status == PAM_USER_UNKNOWN) {
1784 0 : pam_status = PAM_IGNORE;
1785 : }
1786 0 : if (flags & FLAGS_IGNORE_AUTHINFO_UNAVAIL
1787 0 : && pam_status == PAM_AUTHINFO_UNAVAIL) {
1788 0 : pam_status = PAM_IGNORE;
1789 : }
1790 :
1791 0 : switch (task) {
1792 : case SSS_PAM_AUTHENTICATE:
1793 : /* We allow sssd to send the return code PAM_NEW_AUTHTOK_REQD during
1794 : * authentication, see sss_cli.h for details */
1795 0 : if (pam_status == PAM_NEW_AUTHTOK_REQD) {
1796 : D(("Authtoken expired, trying to change it"));
1797 :
1798 0 : pw_exp_data = malloc(sizeof(int));
1799 0 : if (pw_exp_data == NULL) {
1800 : D(("malloc failed."));
1801 0 : pam_status = PAM_BUF_ERR;
1802 0 : break;
1803 : }
1804 0 : *pw_exp_data = 1;
1805 :
1806 0 : pam_status = pam_set_data(pamh, PWEXP_FLAG, pw_exp_data,
1807 : free_exp_data);
1808 : if (pam_status != PAM_SUCCESS) {
1809 : D(("pam_set_data failed."));
1810 : }
1811 : }
1812 0 : break;
1813 : case SSS_PAM_ACCT_MGMT:
1814 0 : if (pam_status == PAM_SUCCESS &&
1815 0 : pam_get_data(pamh, PWEXP_FLAG, (const void **) &exp_data) ==
1816 : PAM_SUCCESS) {
1817 0 : ret = do_pam_conversation(pamh, PAM_TEXT_INFO,
1818 0 : _("Password expired. Change your password now."),
1819 : NULL, NULL);
1820 : if (ret != PAM_SUCCESS) {
1821 : D(("do_pam_conversation failed."));
1822 : }
1823 0 : pam_status = PAM_NEW_AUTHTOK_REQD;
1824 : }
1825 0 : break;
1826 : case SSS_PAM_CHAUTHTOK:
1827 0 : if (pam_status != PAM_SUCCESS && pam_status != PAM_USER_UNKNOWN) {
1828 0 : ret = pam_set_item(pamh, PAM_AUTHTOK, NULL);
1829 : if (ret != PAM_SUCCESS) {
1830 : D(("Failed to unset PAM_AUTHTOK [%s]",
1831 : pam_strerror(pamh,ret)));
1832 : }
1833 0 : ret = pam_set_item(pamh, PAM_OLDAUTHTOK, NULL);
1834 : if (ret != PAM_SUCCESS) {
1835 : D(("Failed to unset PAM_OLDAUTHTOK [%s]",
1836 : pam_strerror(pamh,ret)));
1837 : }
1838 : }
1839 0 : break;
1840 : case SSS_PAM_CHAUTHTOK_PRELIM:
1841 0 : if (pam_status == PAM_PERM_DENIED && pi.pam_authtok_size == 0 &&
1842 0 : getuid() == 0 &&
1843 0 : pam_get_data(pamh, PWEXP_FLAG, (const void **) &exp_data) !=
1844 : PAM_SUCCESS) {
1845 :
1846 0 : ret = select_pw_reset_message(pamh, &pi);
1847 : if (ret != 0) {
1848 : D(("select_pw_reset_message failed.\n"));
1849 : }
1850 : }
1851 : default:
1852 : /* nothing to do */
1853 0 : break;
1854 : }
1855 :
1856 0 : overwrite_and_free_pam_items(&pi);
1857 :
1858 : D(("retries [%d].", retries));
1859 :
1860 0 : if (pam_status != PAM_SUCCESS &&
1861 0 : (task == SSS_PAM_AUTHENTICATE || task == SSS_PAM_CHAUTHTOK_PRELIM) &&
1862 0 : retries > 0) {
1863 0 : retry = true;
1864 0 : retries--;
1865 :
1866 0 : flags &= ~FLAGS_USE_FIRST_PASS;
1867 0 : ret = pam_set_item(pamh, PAM_AUTHTOK, NULL);
1868 : if (ret != PAM_SUCCESS) {
1869 : D(("Failed to unset PAM_AUTHTOK [%s]",
1870 : pam_strerror(pamh,ret)));
1871 : }
1872 0 : ret = pam_set_item(pamh, PAM_OLDAUTHTOK, NULL);
1873 : if (ret != PAM_SUCCESS) {
1874 : D(("Failed to unset PAM_OLDAUTHTOK [%s]",
1875 : pam_strerror(pamh,ret)));
1876 : }
1877 : }
1878 0 : } while(retry);
1879 :
1880 0 : return pam_status;
1881 : }
1882 :
1883 : PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
1884 : const char **argv )
1885 : {
1886 0 : return pam_sss(SSS_PAM_AUTHENTICATE, pamh, flags, argc, argv);
1887 : }
1888 :
1889 :
1890 : PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
1891 : const char **argv )
1892 : {
1893 0 : return pam_sss(SSS_PAM_SETCRED, pamh, flags, argc, argv);
1894 : }
1895 :
1896 : PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
1897 : const char **argv )
1898 : {
1899 0 : return pam_sss(SSS_PAM_ACCT_MGMT, pamh, flags, argc, argv);
1900 : }
1901 :
1902 : PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc,
1903 : const char **argv )
1904 : {
1905 0 : return pam_sss(SSS_PAM_CHAUTHTOK, pamh, flags, argc, argv);
1906 : }
1907 :
1908 : PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
1909 : const char **argv )
1910 : {
1911 0 : return pam_sss(SSS_PAM_OPEN_SESSION, pamh, flags, argc, argv);
1912 : }
1913 :
1914 : PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc,
1915 : const char **argv )
1916 : {
1917 0 : return pam_sss(SSS_PAM_CLOSE_SESSION, pamh, flags, argc, argv);
1918 : }
1919 :
1920 :
1921 : #ifdef PAM_STATIC
1922 :
1923 : /* static module data */
1924 :
1925 : struct pam_module _pam_sssd_modstruct ={
1926 : "pam_sssd",
1927 : pam_sm_authenticate,
1928 : pam_sm_setcred,
1929 : pam_sm_acct_mgmt,
1930 : pam_sm_open_session,
1931 : pam_sm_close_session,
1932 : pam_sm_chauthtok
1933 : };
1934 :
1935 : #endif
|