1 /*- 2 * Copyright (c) 2002 Networks Associates Technology, Inc. 3 * All rights reserved. 4 * 5 * This software was developed for the FreeBSD Project by ThinkSec AS and 6 * NAI Labs, the Security Research Division of Network Associates, Inc. 7 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 8 * DARPA CHATS research program. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (c) 2003,2004 Damien Miller <djm@mindrot.org> 33 * Copyright (c) 2003,2004 Darren Tucker <dtucker@zip.com.au> 34 * 35 * Permission to use, copy, modify, and distribute this software for any 36 * purpose with or without fee is hereby granted, provided that the above 37 * copyright notice and this permission notice appear in all copies. 38 * 39 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 40 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 41 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 42 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 43 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 44 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 45 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 46 */ 47 48 /* Based on FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des */ 49 50 #include "includes.h" 51 52 #include <sys/types.h> 53 #include <sys/stat.h> 54 #include <sys/wait.h> 55 56 #include <errno.h> 57 #include <signal.h> 58 #include <stdarg.h> 59 #include <string.h> 60 #include <unistd.h> 61 62 #ifdef USE_PAM 63 #if defined(HAVE_SECURITY_PAM_APPL_H) 64 #include <security/pam_appl.h> 65 #elif defined (HAVE_PAM_PAM_APPL_H) 66 #include <pam/pam_appl.h> 67 #endif 68 69 #if !defined(SSHD_PAM_SERVICE) 70 extern char *__progname; 71 # define SSHD_PAM_SERVICE __progname 72 #endif 73 74 /* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */ 75 #ifdef PAM_SUN_CODEBASE 76 # define sshpam_const /* Solaris, HP-UX, SunOS */ 77 #else 78 # define sshpam_const const /* LinuxPAM, OpenPAM, AIX */ 79 #endif 80 81 /* Ambiguity in spec: is it an array of pointers or a pointer to an array? */ 82 #ifdef PAM_SUN_CODEBASE 83 # define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member) 84 #else 85 # define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member) 86 #endif 87 88 #include "xmalloc.h" 89 #include "sshbuf.h" 90 #include "ssherr.h" 91 #include "hostfile.h" 92 #include "auth.h" 93 #include "auth-pam.h" 94 #include "canohost.h" 95 #include "log.h" 96 #include "msg.h" 97 #include "packet.h" 98 #include "misc.h" 99 #include "servconf.h" 100 #include "ssh2.h" 101 #include "auth-options.h" 102 #ifdef GSSAPI 103 #include "ssh-gss.h" 104 #endif 105 #include "monitor_wrap.h" 106 #include "blacklist_client.h" 107 108 extern ServerOptions options; 109 extern struct sshbuf *loginmsg; 110 extern u_int utmp_len; 111 112 /* so we don't silently change behaviour */ 113 #ifdef USE_POSIX_THREADS 114 # error "USE_POSIX_THREADS replaced by UNSUPPORTED_POSIX_THREADS_HACK" 115 #endif 116 117 /* 118 * Formerly known as USE_POSIX_THREADS, using this is completely unsupported 119 * and generally a bad idea. Use at own risk and do not expect support if 120 * this breaks. 121 */ 122 #ifdef UNSUPPORTED_POSIX_THREADS_HACK 123 #include <pthread.h> 124 /* 125 * Avoid namespace clash when *not* using pthreads for systems *with* 126 * pthreads, which unconditionally define pthread_t via sys/types.h 127 * (e.g. Linux) 128 */ 129 typedef pthread_t sp_pthread_t; 130 #else 131 typedef pid_t sp_pthread_t; 132 #define pthread_exit fake_pthread_exit 133 #define pthread_create fake_pthread_create 134 #define pthread_cancel fake_pthread_cancel 135 #define pthread_join fake_pthread_join 136 #endif 137 138 struct pam_ctxt { 139 sp_pthread_t pam_thread; 140 int pam_psock; 141 int pam_csock; 142 int pam_done; 143 }; 144 145 static void sshpam_free_ctx(void *); 146 static struct pam_ctxt *cleanup_ctxt; 147 148 #ifndef UNSUPPORTED_POSIX_THREADS_HACK 149 /* 150 * Simulate threads with processes. 151 */ 152 153 static int sshpam_thread_status = -1; 154 static mysig_t sshpam_oldsig; 155 156 static void 157 sshpam_sigchld_handler(int sig) 158 { 159 signal(SIGCHLD, SIG_DFL); 160 if (cleanup_ctxt == NULL) 161 return; /* handler called after PAM cleanup, shouldn't happen */ 162 if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG) 163 <= 0) { 164 /* PAM thread has not exitted, privsep slave must have */ 165 kill(cleanup_ctxt->pam_thread, SIGTERM); 166 while (waitpid(cleanup_ctxt->pam_thread, 167 &sshpam_thread_status, 0) == -1) { 168 if (errno == EINTR) 169 continue; 170 return; 171 } 172 } 173 if (WIFSIGNALED(sshpam_thread_status) && 174 WTERMSIG(sshpam_thread_status) == SIGTERM) 175 return; /* terminated by pthread_cancel */ 176 if (!WIFEXITED(sshpam_thread_status)) 177 sigdie("PAM: authentication thread exited unexpectedly"); 178 if (WEXITSTATUS(sshpam_thread_status) != 0) 179 sigdie("PAM: authentication thread exited uncleanly"); 180 } 181 182 /* ARGSUSED */ 183 static void 184 pthread_exit(void *value) 185 { 186 _exit(0); 187 } 188 189 /* ARGSUSED */ 190 static int 191 pthread_create(sp_pthread_t *thread, const void *attr, 192 void *(*thread_start)(void *), void *arg) 193 { 194 pid_t pid; 195 struct pam_ctxt *ctx = arg; 196 197 sshpam_thread_status = -1; 198 switch ((pid = fork())) { 199 case -1: 200 error("fork(): %s", strerror(errno)); 201 return (-1); 202 case 0: 203 close(ctx->pam_psock); 204 ctx->pam_psock = -1; 205 thread_start(arg); 206 _exit(1); 207 default: 208 *thread = pid; 209 close(ctx->pam_csock); 210 ctx->pam_csock = -1; 211 sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler); 212 return (0); 213 } 214 } 215 216 static int 217 pthread_cancel(sp_pthread_t thread) 218 { 219 signal(SIGCHLD, sshpam_oldsig); 220 return (kill(thread, SIGTERM)); 221 } 222 223 /* ARGSUSED */ 224 static int 225 pthread_join(sp_pthread_t thread, void **value) 226 { 227 int status; 228 229 if (sshpam_thread_status != -1) 230 return (sshpam_thread_status); 231 signal(SIGCHLD, sshpam_oldsig); 232 while (waitpid(thread, &status, 0) == -1) { 233 if (errno == EINTR) 234 continue; 235 fatal("%s: waitpid: %s", __func__, strerror(errno)); 236 } 237 return (status); 238 } 239 #endif 240 241 242 static pam_handle_t *sshpam_handle = NULL; 243 static int sshpam_err = 0; 244 static int sshpam_authenticated = 0; 245 static int sshpam_session_open = 0; 246 static int sshpam_cred_established = 0; 247 static int sshpam_account_status = -1; 248 static int sshpam_maxtries_reached = 0; 249 static char **sshpam_env = NULL; 250 static Authctxt *sshpam_authctxt = NULL; 251 static const char *sshpam_password = NULL; 252 253 /* Some PAM implementations don't implement this */ 254 #ifndef HAVE_PAM_GETENVLIST 255 static char ** 256 pam_getenvlist(pam_handle_t *pamh) 257 { 258 /* 259 * XXX - If necessary, we can still support envrionment passing 260 * for platforms without pam_getenvlist by searching for known 261 * env vars (e.g. KRB5CCNAME) from the PAM environment. 262 */ 263 return NULL; 264 } 265 #endif 266 267 /* 268 * Some platforms, notably Solaris, do not enforce password complexity 269 * rules during pam_chauthtok() if the real uid of the calling process 270 * is 0, on the assumption that it's being called by "passwd" run by root. 271 * This wraps pam_chauthtok and sets/restore the real uid so PAM will do 272 * the right thing. 273 */ 274 #ifdef SSHPAM_CHAUTHTOK_NEEDS_RUID 275 static int 276 sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags) 277 { 278 int result; 279 280 if (sshpam_authctxt == NULL) 281 fatal("PAM: sshpam_authctxt not initialized"); 282 if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1) 283 fatal("%s: setreuid failed: %s", __func__, strerror(errno)); 284 result = pam_chauthtok(pamh, flags); 285 if (setreuid(0, -1) == -1) 286 fatal("%s: setreuid failed: %s", __func__, strerror(errno)); 287 return result; 288 } 289 # define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b))) 290 #endif 291 292 void 293 sshpam_password_change_required(int reqd) 294 { 295 extern struct sshauthopt *auth_opts; 296 static int saved_port, saved_agent, saved_x11; 297 298 debug3("%s %d", __func__, reqd); 299 if (sshpam_authctxt == NULL) 300 fatal("%s: PAM authctxt not initialized", __func__); 301 sshpam_authctxt->force_pwchange = reqd; 302 if (reqd) { 303 saved_port = auth_opts->permit_port_forwarding_flag; 304 saved_agent = auth_opts->permit_agent_forwarding_flag; 305 saved_x11 = auth_opts->permit_x11_forwarding_flag; 306 auth_opts->permit_port_forwarding_flag = 0; 307 auth_opts->permit_agent_forwarding_flag = 0; 308 auth_opts->permit_x11_forwarding_flag = 0; 309 } else { 310 if (saved_port) 311 auth_opts->permit_port_forwarding_flag = saved_port; 312 if (saved_agent) 313 auth_opts->permit_agent_forwarding_flag = saved_agent; 314 if (saved_x11) 315 auth_opts->permit_x11_forwarding_flag = saved_x11; 316 } 317 } 318 319 /* Import regular and PAM environment from subprocess */ 320 static void 321 import_environments(struct sshbuf *b) 322 { 323 char *env; 324 u_int n, i, num_env; 325 int r; 326 327 debug3("PAM: %s entering", __func__); 328 329 #ifndef UNSUPPORTED_POSIX_THREADS_HACK 330 /* Import variables set by do_pam_account */ 331 if ((r = sshbuf_get_u32(b, &n)) != 0) 332 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 333 if (n > INT_MAX) 334 fatal("%s: invalid PAM account status %u", __func__, n); 335 sshpam_account_status = (int)n; 336 if ((r = sshbuf_get_u32(b, &n)) != 0) 337 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 338 sshpam_password_change_required(n != 0); 339 340 /* Import environment from subprocess */ 341 if ((r = sshbuf_get_u32(b, &num_env)) != 0) 342 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 343 if (num_env > 1024) 344 fatal("%s: received %u environment variables, expected <= 1024", 345 __func__, num_env); 346 sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env)); 347 debug3("PAM: num env strings %d", num_env); 348 for(i = 0; i < num_env; i++) { 349 if ((r = sshbuf_get_cstring(b, &(sshpam_env[i]), NULL)) != 0) 350 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 351 } 352 sshpam_env[num_env] = NULL; 353 354 /* Import PAM environment from subprocess */ 355 if ((r = sshbuf_get_u32(b, &num_env)) != 0) 356 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 357 debug("PAM: num PAM env strings %d", num_env); 358 for (i = 0; i < num_env; i++) { 359 if ((r = sshbuf_get_cstring(b, &env, NULL)) != 0) 360 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 361 #ifdef HAVE_PAM_PUTENV 362 /* Errors are not fatal here */ 363 if ((r = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) { 364 error("PAM: pam_putenv: %s", 365 pam_strerror(sshpam_handle, r)); 366 } 367 #endif 368 /* XXX leak env? */ 369 } 370 #endif 371 } 372 373 /* 374 * Conversation function for authentication thread. 375 */ 376 static int 377 sshpam_thread_conv(int n, sshpam_const struct pam_message **msg, 378 struct pam_response **resp, void *data) 379 { 380 struct sshbuf *buffer; 381 struct pam_ctxt *ctxt; 382 struct pam_response *reply; 383 int r, i; 384 u_char status; 385 386 debug3("PAM: %s entering, %d messages", __func__, n); 387 *resp = NULL; 388 389 if (data == NULL) { 390 error("PAM: conversation function passed a null context"); 391 return (PAM_CONV_ERR); 392 } 393 ctxt = data; 394 if (n <= 0 || n > PAM_MAX_NUM_MSG) 395 return (PAM_CONV_ERR); 396 397 if ((reply = calloc(n, sizeof(*reply))) == NULL) 398 return PAM_CONV_ERR; 399 if ((buffer = sshbuf_new()) == NULL) { 400 free(reply); 401 return PAM_CONV_ERR; 402 } 403 404 for (i = 0; i < n; ++i) { 405 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 406 case PAM_PROMPT_ECHO_OFF: 407 case PAM_PROMPT_ECHO_ON: 408 if ((r = sshbuf_put_cstring(buffer, 409 PAM_MSG_MEMBER(msg, i, msg))) != 0) 410 fatal("%s: buffer error: %s", 411 __func__, ssh_err(r)); 412 if (ssh_msg_send(ctxt->pam_csock, 413 PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1) 414 goto fail; 415 416 if (ssh_msg_recv(ctxt->pam_csock, buffer) == -1) 417 goto fail; 418 if ((r = sshbuf_get_u8(buffer, &status)) != 0) 419 fatal("%s: buffer error: %s", 420 __func__, ssh_err(r)); 421 if (status != PAM_AUTHTOK) 422 goto fail; 423 if ((r = sshbuf_get_cstring(buffer, 424 &reply[i].resp, NULL)) != 0) 425 fatal("%s: buffer error: %s", 426 __func__, ssh_err(r)); 427 break; 428 case PAM_ERROR_MSG: 429 case PAM_TEXT_INFO: 430 if ((r = sshbuf_put_cstring(buffer, 431 PAM_MSG_MEMBER(msg, i, msg))) != 0) 432 fatal("%s: buffer error: %s", 433 __func__, ssh_err(r)); 434 if (ssh_msg_send(ctxt->pam_csock, 435 PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1) 436 goto fail; 437 break; 438 default: 439 goto fail; 440 } 441 sshbuf_reset(buffer); 442 } 443 sshbuf_free(buffer); 444 *resp = reply; 445 return (PAM_SUCCESS); 446 447 fail: 448 for(i = 0; i < n; i++) { 449 free(reply[i].resp); 450 } 451 free(reply); 452 sshbuf_free(buffer); 453 return (PAM_CONV_ERR); 454 } 455 456 /* 457 * Authentication thread. 458 */ 459 static void * 460 sshpam_thread(void *ctxtp) 461 { 462 struct pam_ctxt *ctxt = ctxtp; 463 struct sshbuf *buffer = NULL; 464 struct pam_conv sshpam_conv; 465 int r, flags = (options.permit_empty_passwd == 0 ? 466 PAM_DISALLOW_NULL_AUTHTOK : 0); 467 #ifndef UNSUPPORTED_POSIX_THREADS_HACK 468 extern char **environ; 469 char **env_from_pam; 470 u_int i; 471 const char *pam_user; 472 const char **ptr_pam_user = &pam_user; 473 char *tz = getenv("TZ"); 474 475 sshpam_err = pam_get_item(sshpam_handle, PAM_USER, 476 (sshpam_const void **)ptr_pam_user); 477 if (sshpam_err != PAM_SUCCESS) 478 goto auth_fail; 479 480 environ[0] = NULL; 481 if (tz != NULL) 482 if (setenv("TZ", tz, 1) == -1) 483 error("PAM: could not set TZ environment: %s", 484 strerror(errno)); 485 486 if (sshpam_authctxt != NULL) { 487 setproctitle("%s [pam]", 488 sshpam_authctxt->valid ? pam_user : "unknown"); 489 } 490 #endif 491 492 sshpam_conv.conv = sshpam_thread_conv; 493 sshpam_conv.appdata_ptr = ctxt; 494 495 if (sshpam_authctxt == NULL) 496 fatal("%s: PAM authctxt not initialized", __func__); 497 498 if ((buffer = sshbuf_new()) == NULL) 499 fatal("%s: sshbuf_new failed", __func__); 500 501 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 502 (const void *)&sshpam_conv); 503 if (sshpam_err != PAM_SUCCESS) 504 goto auth_fail; 505 sshpam_err = pam_authenticate(sshpam_handle, flags); 506 if (sshpam_err == PAM_MAXTRIES) 507 sshpam_set_maxtries_reached(1); 508 if (sshpam_err != PAM_SUCCESS) 509 goto auth_fail; 510 511 if (!do_pam_account()) { 512 sshpam_err = PAM_ACCT_EXPIRED; 513 goto auth_fail; 514 } 515 if (sshpam_authctxt->force_pwchange) { 516 sshpam_err = pam_chauthtok(sshpam_handle, 517 PAM_CHANGE_EXPIRED_AUTHTOK); 518 if (sshpam_err != PAM_SUCCESS) 519 goto auth_fail; 520 sshpam_password_change_required(0); 521 } 522 523 if ((r = sshbuf_put_cstring(buffer, "OK")) != 0) 524 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 525 526 #ifndef UNSUPPORTED_POSIX_THREADS_HACK 527 /* Export variables set by do_pam_account */ 528 if ((r = sshbuf_put_u32(buffer, sshpam_account_status)) != 0 || 529 (r = sshbuf_put_u32(buffer, sshpam_authctxt->force_pwchange)) != 0) 530 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 531 532 /* Export any environment strings set in child */ 533 for (i = 0; environ[i] != NULL; i++) { 534 /* Count */ 535 if (i > INT_MAX) 536 fatal("%s: too many enviornment strings", __func__); 537 } 538 if ((r = sshbuf_put_u32(buffer, i)) != 0) 539 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 540 for (i = 0; environ[i] != NULL; i++) { 541 if ((r = sshbuf_put_cstring(buffer, environ[i])) != 0) 542 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 543 } 544 /* Export any environment strings set by PAM in child */ 545 env_from_pam = pam_getenvlist(sshpam_handle); 546 for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) { 547 /* Count */ 548 if (i > INT_MAX) 549 fatal("%s: too many PAM enviornment strings", __func__); 550 } 551 if ((r = sshbuf_put_u32(buffer, i)) != 0) 552 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 553 for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) { 554 if ((r = sshbuf_put_cstring(buffer, env_from_pam[i])) != 0) 555 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 556 } 557 #endif /* UNSUPPORTED_POSIX_THREADS_HACK */ 558 559 /* XXX - can't do much about an error here */ 560 ssh_msg_send(ctxt->pam_csock, sshpam_err, buffer); 561 sshbuf_free(buffer); 562 pthread_exit(NULL); 563 564 auth_fail: 565 if ((r = sshbuf_put_cstring(buffer, 566 pam_strerror(sshpam_handle, sshpam_err))) != 0) 567 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 568 /* XXX - can't do much about an error here */ 569 if (sshpam_err == PAM_ACCT_EXPIRED) 570 ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer); 571 else if (sshpam_maxtries_reached) 572 ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer); 573 else 574 ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, buffer); 575 sshbuf_free(buffer); 576 pthread_exit(NULL); 577 578 return (NULL); /* Avoid warning for non-pthread case */ 579 } 580 581 void 582 sshpam_thread_cleanup(void) 583 { 584 struct pam_ctxt *ctxt = cleanup_ctxt; 585 586 debug3("PAM: %s entering", __func__); 587 if (ctxt != NULL && ctxt->pam_thread != 0) { 588 pthread_cancel(ctxt->pam_thread); 589 pthread_join(ctxt->pam_thread, NULL); 590 close(ctxt->pam_psock); 591 close(ctxt->pam_csock); 592 memset(ctxt, 0, sizeof(*ctxt)); 593 cleanup_ctxt = NULL; 594 } 595 } 596 597 static int 598 sshpam_null_conv(int n, sshpam_const struct pam_message **msg, 599 struct pam_response **resp, void *data) 600 { 601 debug3("PAM: %s entering, %d messages", __func__, n); 602 return (PAM_CONV_ERR); 603 } 604 605 static struct pam_conv null_conv = { sshpam_null_conv, NULL }; 606 607 static int 608 sshpam_store_conv(int n, sshpam_const struct pam_message **msg, 609 struct pam_response **resp, void *data) 610 { 611 struct pam_response *reply; 612 int r, i; 613 614 debug3("PAM: %s called with %d messages", __func__, n); 615 *resp = NULL; 616 617 if (n <= 0 || n > PAM_MAX_NUM_MSG) 618 return (PAM_CONV_ERR); 619 620 if ((reply = calloc(n, sizeof(*reply))) == NULL) 621 return (PAM_CONV_ERR); 622 623 for (i = 0; i < n; ++i) { 624 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 625 case PAM_ERROR_MSG: 626 case PAM_TEXT_INFO: 627 if ((r = sshbuf_putf(loginmsg, "%s\n", 628 PAM_MSG_MEMBER(msg, i, msg))) != 0) 629 fatal("%s: buffer error: %s", 630 __func__, ssh_err(r)); 631 reply[i].resp_retcode = PAM_SUCCESS; 632 break; 633 default: 634 goto fail; 635 } 636 } 637 *resp = reply; 638 return (PAM_SUCCESS); 639 640 fail: 641 for(i = 0; i < n; i++) { 642 free(reply[i].resp); 643 } 644 free(reply); 645 return (PAM_CONV_ERR); 646 } 647 648 static struct pam_conv store_conv = { sshpam_store_conv, NULL }; 649 650 void 651 sshpam_cleanup(void) 652 { 653 if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor())) 654 return; 655 debug("PAM: cleanup"); 656 pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv); 657 if (sshpam_session_open) { 658 debug("PAM: closing session"); 659 pam_close_session(sshpam_handle, PAM_SILENT); 660 sshpam_session_open = 0; 661 } 662 if (sshpam_cred_established) { 663 debug("PAM: deleting credentials"); 664 pam_setcred(sshpam_handle, PAM_DELETE_CRED); 665 sshpam_cred_established = 0; 666 } 667 sshpam_authenticated = 0; 668 pam_end(sshpam_handle, sshpam_err); 669 sshpam_handle = NULL; 670 } 671 672 static int 673 sshpam_init(Authctxt *authctxt) 674 { 675 const char *pam_rhost, *pam_user, *user = authctxt->user; 676 const char **ptr_pam_user = &pam_user; 677 struct ssh *ssh = active_state; /* XXX */ 678 679 if (sshpam_handle != NULL) { 680 /* We already have a PAM context; check if the user matches */ 681 sshpam_err = pam_get_item(sshpam_handle, 682 PAM_USER, (sshpam_const void **)ptr_pam_user); 683 if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) 684 return (0); 685 pam_end(sshpam_handle, sshpam_err); 686 sshpam_handle = NULL; 687 } 688 debug("PAM: initializing for \"%s\"", user); 689 sshpam_err = 690 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle); 691 sshpam_authctxt = authctxt; 692 693 if (sshpam_err != PAM_SUCCESS) { 694 pam_end(sshpam_handle, sshpam_err); 695 sshpam_handle = NULL; 696 return (-1); 697 } 698 pam_rhost = auth_get_canonical_hostname(ssh, options.use_dns); 699 debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost); 700 sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost); 701 if (sshpam_err != PAM_SUCCESS) { 702 pam_end(sshpam_handle, sshpam_err); 703 sshpam_handle = NULL; 704 return (-1); 705 } 706 #ifdef PAM_TTY_KLUDGE 707 /* 708 * Some silly PAM modules (e.g. pam_time) require a TTY to operate. 709 * sshd doesn't set the tty until too late in the auth process and 710 * may not even set one (for tty-less connections) 711 */ 712 debug("PAM: setting PAM_TTY to \"ssh\""); 713 sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, "ssh"); 714 if (sshpam_err != PAM_SUCCESS) { 715 pam_end(sshpam_handle, sshpam_err); 716 sshpam_handle = NULL; 717 return (-1); 718 } 719 #endif 720 return (0); 721 } 722 723 static void 724 expose_authinfo(const char *caller) 725 { 726 char *auth_info; 727 728 /* 729 * Expose authentication information to PAM. 730 * The environment variable is versioned. Please increment the 731 * version suffix if the format of session_info changes. 732 */ 733 if (sshpam_authctxt->session_info == NULL) 734 auth_info = xstrdup(""); 735 else if ((auth_info = sshbuf_dup_string( 736 sshpam_authctxt->session_info)) == NULL) 737 fatal("%s: sshbuf_dup_string failed", __func__); 738 739 debug2("%s: auth information in SSH_AUTH_INFO_0", caller); 740 do_pam_putenv("SSH_AUTH_INFO_0", auth_info); 741 free(auth_info); 742 } 743 744 static void * 745 sshpam_init_ctx(Authctxt *authctxt) 746 { 747 struct pam_ctxt *ctxt; 748 int socks[2]; 749 750 debug3("PAM: %s entering", __func__); 751 /* 752 * Refuse to start if we don't have PAM enabled or do_pam_account 753 * has previously failed. 754 */ 755 if (!options.use_pam || sshpam_account_status == 0) 756 return NULL; 757 758 /* Initialize PAM */ 759 if (sshpam_init(authctxt) == -1) { 760 error("PAM: initialization failed"); 761 return (NULL); 762 } 763 764 expose_authinfo(__func__); 765 ctxt = xcalloc(1, sizeof *ctxt); 766 767 /* Start the authentication thread */ 768 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) { 769 error("PAM: failed create sockets: %s", strerror(errno)); 770 free(ctxt); 771 return (NULL); 772 } 773 ctxt->pam_psock = socks[0]; 774 ctxt->pam_csock = socks[1]; 775 if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) { 776 error("PAM: failed to start authentication thread: %s", 777 strerror(errno)); 778 close(socks[0]); 779 close(socks[1]); 780 free(ctxt); 781 return (NULL); 782 } 783 cleanup_ctxt = ctxt; 784 return (ctxt); 785 } 786 787 static int 788 sshpam_query(void *ctx, char **name, char **info, 789 u_int *num, char ***prompts, u_int **echo_on) 790 { 791 struct ssh *ssh = active_state; /* XXX */ 792 struct sshbuf *buffer; 793 struct pam_ctxt *ctxt = ctx; 794 size_t plen; 795 u_char type; 796 char *msg; 797 size_t len, mlen; 798 int r; 799 800 debug3("PAM: %s entering", __func__); 801 if ((buffer = sshbuf_new()) == NULL) 802 fatal("%s: sshbuf_new failed", __func__); 803 *name = xstrdup(""); 804 *info = xstrdup(""); 805 *prompts = xmalloc(sizeof(char *)); 806 **prompts = NULL; 807 plen = 0; 808 *echo_on = xmalloc(sizeof(u_int)); 809 while (ssh_msg_recv(ctxt->pam_psock, buffer) == 0) { 810 if ((r = sshbuf_get_u8(buffer, &type)) != 0 || 811 (r = sshbuf_get_cstring(buffer, &msg, &mlen)) != 0) 812 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 813 switch (type) { 814 case PAM_PROMPT_ECHO_ON: 815 case PAM_PROMPT_ECHO_OFF: 816 *num = 1; 817 len = plen + mlen + 1; 818 **prompts = xreallocarray(**prompts, 1, len); 819 strlcpy(**prompts + plen, msg, len - plen); 820 plen += mlen; 821 **echo_on = (type == PAM_PROMPT_ECHO_ON); 822 free(msg); 823 return (0); 824 case PAM_ERROR_MSG: 825 case PAM_TEXT_INFO: 826 /* accumulate messages */ 827 len = plen + mlen + 2; 828 **prompts = xreallocarray(**prompts, 1, len); 829 strlcpy(**prompts + plen, msg, len - plen); 830 plen += mlen; 831 strlcat(**prompts + plen, "\n", len - plen); 832 plen++; 833 free(msg); 834 break; 835 case PAM_ACCT_EXPIRED: 836 case PAM_MAXTRIES: 837 if (type == PAM_ACCT_EXPIRED) 838 sshpam_account_status = 0; 839 if (type == PAM_MAXTRIES) 840 sshpam_set_maxtries_reached(1); 841 /* FALLTHROUGH */ 842 case PAM_AUTH_ERR: 843 debug3("PAM: %s", pam_strerror(sshpam_handle, type)); 844 if (**prompts != NULL && strlen(**prompts) != 0) { 845 *info = **prompts; 846 **prompts = NULL; 847 *num = 0; 848 **echo_on = 0; 849 ctxt->pam_done = -1; 850 free(msg); 851 return 0; 852 } 853 /* FALLTHROUGH */ 854 case PAM_SUCCESS: 855 if (**prompts != NULL) { 856 /* drain any accumulated messages */ 857 debug("PAM: %s", **prompts); 858 if ((r = sshbuf_put(loginmsg, **prompts, 859 strlen(**prompts))) != 0) 860 fatal("%s: buffer error: %s", 861 __func__, ssh_err(r)); 862 free(**prompts); 863 **prompts = NULL; 864 } 865 if (type == PAM_SUCCESS) { 866 if (!sshpam_authctxt->valid || 867 (sshpam_authctxt->pw->pw_uid == 0 && 868 options.permit_root_login != PERMIT_YES)) 869 fatal("Internal error: PAM auth " 870 "succeeded when it should have " 871 "failed"); 872 import_environments(buffer); 873 *num = 0; 874 **echo_on = 0; 875 ctxt->pam_done = 1; 876 free(msg); 877 return (0); 878 } 879 BLACKLIST_NOTIFY(BLACKLIST_BAD_USER, 880 sshpam_authctxt->user); 881 error("PAM: %s for %s%.100s from %.100s", msg, 882 sshpam_authctxt->valid ? "" : "illegal user ", 883 sshpam_authctxt->user, 884 auth_get_canonical_hostname(ssh, options.use_dns)); 885 /* FALLTHROUGH */ 886 default: 887 *num = 0; 888 **echo_on = 0; 889 free(msg); 890 ctxt->pam_done = -1; 891 return (-1); 892 } 893 } 894 return (-1); 895 } 896 897 /* 898 * Returns a junk password of identical length to that the user supplied. 899 * Used to mitigate timing attacks against crypt(3)/PAM stacks that 900 * vary processing time in proportion to password length. 901 */ 902 static char * 903 fake_password(const char *wire_password) 904 { 905 const char junk[] = "\b\n\r\177INCORRECT"; 906 char *ret = NULL; 907 size_t i, l = wire_password != NULL ? strlen(wire_password) : 0; 908 909 if (l >= INT_MAX) 910 fatal("%s: password length too long: %zu", __func__, l); 911 912 ret = malloc(l + 1); 913 if (ret == NULL) 914 return NULL; 915 for (i = 0; i < l; i++) 916 ret[i] = junk[i % (sizeof(junk) - 1)]; 917 ret[i] = '\0'; 918 return ret; 919 } 920 921 /* XXX - see also comment in auth-chall.c:verify_response */ 922 static int 923 sshpam_respond(void *ctx, u_int num, char **resp) 924 { 925 struct sshbuf *buffer; 926 struct pam_ctxt *ctxt = ctx; 927 char *fake; 928 int r; 929 930 debug2("PAM: %s entering, %u responses", __func__, num); 931 switch (ctxt->pam_done) { 932 case 1: 933 sshpam_authenticated = 1; 934 return (0); 935 case 0: 936 break; 937 default: 938 return (-1); 939 } 940 if (num != 1) { 941 error("PAM: expected one response, got %u", num); 942 return (-1); 943 } 944 if ((buffer = sshbuf_new()) == NULL) 945 fatal("%s: sshbuf_new failed", __func__); 946 if (sshpam_authctxt->valid && 947 (sshpam_authctxt->pw->pw_uid != 0 || 948 options.permit_root_login == PERMIT_YES)) { 949 if ((r = sshbuf_put_cstring(buffer, *resp)) != 0) 950 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 951 } else { 952 fake = fake_password(*resp); 953 if ((r = sshbuf_put_cstring(buffer, fake)) != 0) 954 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 955 free(fake); 956 } 957 if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, buffer) == -1) { 958 sshbuf_free(buffer); 959 return (-1); 960 } 961 sshbuf_free(buffer); 962 return (1); 963 } 964 965 static void 966 sshpam_free_ctx(void *ctxtp) 967 { 968 struct pam_ctxt *ctxt = ctxtp; 969 970 debug3("PAM: %s entering", __func__); 971 sshpam_thread_cleanup(); 972 free(ctxt); 973 /* 974 * We don't call sshpam_cleanup() here because we may need the PAM 975 * handle at a later stage, e.g. when setting up a session. It's 976 * still on the cleanup list, so pam_end() *will* be called before 977 * the server process terminates. 978 */ 979 } 980 981 KbdintDevice sshpam_device = { 982 "pam", 983 sshpam_init_ctx, 984 sshpam_query, 985 sshpam_respond, 986 sshpam_free_ctx 987 }; 988 989 KbdintDevice mm_sshpam_device = { 990 "pam", 991 mm_sshpam_init_ctx, 992 mm_sshpam_query, 993 mm_sshpam_respond, 994 mm_sshpam_free_ctx 995 }; 996 997 /* 998 * This replaces auth-pam.c 999 */ 1000 void 1001 start_pam(Authctxt *authctxt) 1002 { 1003 if (!options.use_pam) 1004 fatal("PAM: initialisation requested when UsePAM=no"); 1005 1006 if (sshpam_init(authctxt) == -1) 1007 fatal("PAM: initialisation failed"); 1008 } 1009 1010 void 1011 finish_pam(void) 1012 { 1013 sshpam_cleanup(); 1014 } 1015 1016 1017 u_int 1018 do_pam_account(void) 1019 { 1020 debug("%s: called", __func__); 1021 if (sshpam_account_status != -1) 1022 return (sshpam_account_status); 1023 1024 expose_authinfo(__func__); 1025 1026 sshpam_err = pam_acct_mgmt(sshpam_handle, 0); 1027 debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err, 1028 pam_strerror(sshpam_handle, sshpam_err)); 1029 1030 if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) { 1031 sshpam_account_status = 0; 1032 return (sshpam_account_status); 1033 } 1034 1035 if (sshpam_err == PAM_NEW_AUTHTOK_REQD) 1036 sshpam_password_change_required(1); 1037 1038 sshpam_account_status = 1; 1039 return (sshpam_account_status); 1040 } 1041 1042 void 1043 do_pam_setcred(int init) 1044 { 1045 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 1046 (const void *)&store_conv); 1047 if (sshpam_err != PAM_SUCCESS) 1048 fatal("PAM: failed to set PAM_CONV: %s", 1049 pam_strerror(sshpam_handle, sshpam_err)); 1050 if (init) { 1051 debug("PAM: establishing credentials"); 1052 sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED); 1053 } else { 1054 debug("PAM: reinitializing credentials"); 1055 sshpam_err = pam_setcred(sshpam_handle, PAM_REINITIALIZE_CRED); 1056 } 1057 if (sshpam_err == PAM_SUCCESS) { 1058 sshpam_cred_established = 1; 1059 return; 1060 } 1061 if (sshpam_authenticated) 1062 fatal("PAM: pam_setcred(): %s", 1063 pam_strerror(sshpam_handle, sshpam_err)); 1064 else 1065 debug("PAM: pam_setcred(): %s", 1066 pam_strerror(sshpam_handle, sshpam_err)); 1067 } 1068 1069 static int 1070 sshpam_tty_conv(int n, sshpam_const struct pam_message **msg, 1071 struct pam_response **resp, void *data) 1072 { 1073 char input[PAM_MAX_MSG_SIZE]; 1074 struct pam_response *reply; 1075 int i; 1076 1077 debug3("PAM: %s called with %d messages", __func__, n); 1078 1079 *resp = NULL; 1080 1081 if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO)) 1082 return (PAM_CONV_ERR); 1083 1084 if ((reply = calloc(n, sizeof(*reply))) == NULL) 1085 return (PAM_CONV_ERR); 1086 1087 for (i = 0; i < n; ++i) { 1088 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 1089 case PAM_PROMPT_ECHO_OFF: 1090 reply[i].resp = 1091 read_passphrase(PAM_MSG_MEMBER(msg, i, msg), 1092 RP_ALLOW_STDIN); 1093 reply[i].resp_retcode = PAM_SUCCESS; 1094 break; 1095 case PAM_PROMPT_ECHO_ON: 1096 fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg)); 1097 if (fgets(input, sizeof input, stdin) == NULL) 1098 input[0] = '\0'; 1099 if ((reply[i].resp = strdup(input)) == NULL) 1100 goto fail; 1101 reply[i].resp_retcode = PAM_SUCCESS; 1102 break; 1103 case PAM_ERROR_MSG: 1104 case PAM_TEXT_INFO: 1105 fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg)); 1106 reply[i].resp_retcode = PAM_SUCCESS; 1107 break; 1108 default: 1109 goto fail; 1110 } 1111 } 1112 *resp = reply; 1113 return (PAM_SUCCESS); 1114 1115 fail: 1116 for(i = 0; i < n; i++) { 1117 free(reply[i].resp); 1118 } 1119 free(reply); 1120 return (PAM_CONV_ERR); 1121 } 1122 1123 static struct pam_conv tty_conv = { sshpam_tty_conv, NULL }; 1124 1125 /* 1126 * XXX this should be done in the authentication phase, but ssh1 doesn't 1127 * support that 1128 */ 1129 void 1130 do_pam_chauthtok(void) 1131 { 1132 if (use_privsep) 1133 fatal("Password expired (unable to change with privsep)"); 1134 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 1135 (const void *)&tty_conv); 1136 if (sshpam_err != PAM_SUCCESS) 1137 fatal("PAM: failed to set PAM_CONV: %s", 1138 pam_strerror(sshpam_handle, sshpam_err)); 1139 debug("PAM: changing password"); 1140 sshpam_err = pam_chauthtok(sshpam_handle, PAM_CHANGE_EXPIRED_AUTHTOK); 1141 if (sshpam_err != PAM_SUCCESS) 1142 fatal("PAM: pam_chauthtok(): %s", 1143 pam_strerror(sshpam_handle, sshpam_err)); 1144 } 1145 1146 void 1147 do_pam_session(struct ssh *ssh) 1148 { 1149 debug3("PAM: opening session"); 1150 1151 expose_authinfo(__func__); 1152 1153 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 1154 (const void *)&store_conv); 1155 if (sshpam_err != PAM_SUCCESS) 1156 fatal("PAM: failed to set PAM_CONV: %s", 1157 pam_strerror(sshpam_handle, sshpam_err)); 1158 sshpam_err = pam_open_session(sshpam_handle, 0); 1159 if (sshpam_err == PAM_SUCCESS) 1160 sshpam_session_open = 1; 1161 else { 1162 sshpam_session_open = 0; 1163 auth_restrict_session(ssh); 1164 error("PAM: pam_open_session(): %s", 1165 pam_strerror(sshpam_handle, sshpam_err)); 1166 } 1167 1168 } 1169 1170 int 1171 is_pam_session_open(void) 1172 { 1173 return sshpam_session_open; 1174 } 1175 1176 /* 1177 * Set a PAM environment string. We need to do this so that the session 1178 * modules can handle things like Kerberos/GSI credentials that appear 1179 * during the ssh authentication process. 1180 */ 1181 int 1182 do_pam_putenv(char *name, char *value) 1183 { 1184 int ret = 1; 1185 #ifdef HAVE_PAM_PUTENV 1186 char *compound; 1187 size_t len; 1188 1189 len = strlen(name) + strlen(value) + 2; 1190 compound = xmalloc(len); 1191 1192 snprintf(compound, len, "%s=%s", name, value); 1193 ret = pam_putenv(sshpam_handle, compound); 1194 free(compound); 1195 #endif 1196 1197 return (ret); 1198 } 1199 1200 char ** 1201 fetch_pam_child_environment(void) 1202 { 1203 return sshpam_env; 1204 } 1205 1206 char ** 1207 fetch_pam_environment(void) 1208 { 1209 return (pam_getenvlist(sshpam_handle)); 1210 } 1211 1212 void 1213 free_pam_environment(char **env) 1214 { 1215 char **envp; 1216 1217 if (env == NULL) 1218 return; 1219 1220 for (envp = env; *envp; envp++) 1221 free(*envp); 1222 free(env); 1223 } 1224 1225 /* 1226 * "Blind" conversation function for password authentication. Assumes that 1227 * echo-off prompts are for the password and stores messages for later 1228 * display. 1229 */ 1230 static int 1231 sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg, 1232 struct pam_response **resp, void *data) 1233 { 1234 struct pam_response *reply; 1235 int r, i; 1236 size_t len; 1237 1238 debug3("PAM: %s called with %d messages", __func__, n); 1239 1240 *resp = NULL; 1241 1242 if (n <= 0 || n > PAM_MAX_NUM_MSG) 1243 return (PAM_CONV_ERR); 1244 1245 if ((reply = calloc(n, sizeof(*reply))) == NULL) 1246 return (PAM_CONV_ERR); 1247 1248 for (i = 0; i < n; ++i) { 1249 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 1250 case PAM_PROMPT_ECHO_OFF: 1251 if (sshpam_password == NULL) 1252 goto fail; 1253 if ((reply[i].resp = strdup(sshpam_password)) == NULL) 1254 goto fail; 1255 reply[i].resp_retcode = PAM_SUCCESS; 1256 break; 1257 case PAM_ERROR_MSG: 1258 case PAM_TEXT_INFO: 1259 len = strlen(PAM_MSG_MEMBER(msg, i, msg)); 1260 if (len > 0) { 1261 if ((r = sshbuf_putf(loginmsg, "%s\n", 1262 PAM_MSG_MEMBER(msg, i, msg))) != 0) 1263 fatal("%s: buffer error: %s", 1264 __func__, ssh_err(r)); 1265 } 1266 if ((reply[i].resp = strdup("")) == NULL) 1267 goto fail; 1268 reply[i].resp_retcode = PAM_SUCCESS; 1269 break; 1270 default: 1271 goto fail; 1272 } 1273 } 1274 *resp = reply; 1275 return (PAM_SUCCESS); 1276 1277 fail: 1278 for(i = 0; i < n; i++) { 1279 free(reply[i].resp); 1280 } 1281 free(reply); 1282 return (PAM_CONV_ERR); 1283 } 1284 1285 static struct pam_conv passwd_conv = { sshpam_passwd_conv, NULL }; 1286 1287 /* 1288 * Attempt password authentication via PAM 1289 */ 1290 int 1291 sshpam_auth_passwd(Authctxt *authctxt, const char *password) 1292 { 1293 int flags = (options.permit_empty_passwd == 0 ? 1294 PAM_DISALLOW_NULL_AUTHTOK : 0); 1295 char *fake = NULL; 1296 1297 if (!options.use_pam || sshpam_handle == NULL) 1298 fatal("PAM: %s called when PAM disabled or failed to " 1299 "initialise.", __func__); 1300 1301 sshpam_password = password; 1302 sshpam_authctxt = authctxt; 1303 1304 /* 1305 * If the user logging in is invalid, or is root but is not permitted 1306 * by PermitRootLogin, use an invalid password to prevent leaking 1307 * information via timing (eg if the PAM config has a delay on fail). 1308 */ 1309 if (!authctxt->valid || (authctxt->pw->pw_uid == 0 && 1310 options.permit_root_login != PERMIT_YES)) 1311 sshpam_password = fake = fake_password(password); 1312 1313 sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, 1314 (const void *)&passwd_conv); 1315 if (sshpam_err != PAM_SUCCESS) 1316 fatal("PAM: %s: failed to set PAM_CONV: %s", __func__, 1317 pam_strerror(sshpam_handle, sshpam_err)); 1318 1319 sshpam_err = pam_authenticate(sshpam_handle, flags); 1320 sshpam_password = NULL; 1321 free(fake); 1322 if (sshpam_err == PAM_MAXTRIES) 1323 sshpam_set_maxtries_reached(1); 1324 if (sshpam_err == PAM_SUCCESS && authctxt->valid) { 1325 debug("PAM: password authentication accepted for %.100s", 1326 authctxt->user); 1327 return 1; 1328 } else { 1329 debug("PAM: password authentication failed for %.100s: %s", 1330 authctxt->valid ? authctxt->user : "an illegal user", 1331 pam_strerror(sshpam_handle, sshpam_err)); 1332 return 0; 1333 } 1334 } 1335 1336 int 1337 sshpam_get_maxtries_reached(void) 1338 { 1339 return sshpam_maxtries_reached; 1340 } 1341 1342 void 1343 sshpam_set_maxtries_reached(int reached) 1344 { 1345 if (reached == 0 || sshpam_maxtries_reached) 1346 return; 1347 sshpam_maxtries_reached = 1; 1348 options.password_authentication = 0; 1349 options.kbd_interactive_authentication = 0; 1350 options.challenge_response_authentication = 0; 1351 } 1352 #endif /* USE_PAM */ 1353