auth-pam.c (157019) | auth-pam.c (162856) |
---|---|
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. --- 33 unchanged lines hidden (view full) --- 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 $xFreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */ 49#include "includes.h" | 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. --- 33 unchanged lines hidden (view full) --- 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 $xFreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des Exp $ */ 49#include "includes.h" |
50RCSID("$Id: auth-pam.c,v 1.128 2006/01/29 05:46:13 dtucker Exp $"); 51RCSID("$FreeBSD: head/crypto/openssh/auth-pam.c 157019 2006-03-22 20:41:37Z des $"); | 50__RCSID("$FreeBSD: head/crypto/openssh/auth-pam.c 162856 2006-09-30 13:38:06Z des $"); |
52 | 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 |
|
53#ifdef USE_PAM 54#if defined(HAVE_SECURITY_PAM_APPL_H) 55#include <security/pam_appl.h> 56#elif defined (HAVE_PAM_PAM_APPL_H) 57#include <pam/pam_appl.h> 58#endif 59 60/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */ 61#ifdef PAM_SUN_CODEBASE 62# define sshpam_const /* Solaris, HP-UX, AIX */ 63#else 64# define sshpam_const const /* LinuxPAM, OpenPAM */ 65#endif 66 | 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/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */ 70#ifdef PAM_SUN_CODEBASE 71# define sshpam_const /* Solaris, HP-UX, AIX */ 72#else 73# define sshpam_const const /* LinuxPAM, OpenPAM */ 74#endif 75 |
76/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */ 77#ifdef PAM_SUN_CODEBASE 78# define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member) 79#else 80# define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member) 81#endif 82 83#include "xmalloc.h" 84#include "buffer.h" 85#include "key.h" 86#include "hostfile.h" |
|
67#include "auth.h" 68#include "auth-pam.h" | 87#include "auth.h" 88#include "auth-pam.h" |
69#include "buffer.h" 70#include "bufaux.h" | |
71#include "canohost.h" 72#include "log.h" | 89#include "canohost.h" 90#include "log.h" |
73#include "monitor_wrap.h" | |
74#include "msg.h" 75#include "packet.h" 76#include "misc.h" 77#include "servconf.h" 78#include "ssh2.h" | 91#include "msg.h" 92#include "packet.h" 93#include "misc.h" 94#include "servconf.h" 95#include "ssh2.h" |
79#include "xmalloc.h" | |
80#include "auth-options.h" | 96#include "auth-options.h" |
97#ifdef GSSAPI 98#include "ssh-gss.h" 99#endif 100#include "monitor_wrap.h" |
|
81 82extern ServerOptions options; 83extern Buffer loginmsg; 84extern int compat20; 85extern u_int utmp_len; 86 87/* so we don't silently change behaviour */ 88#ifdef USE_POSIX_THREADS --- 53 unchanged lines hidden (view full) --- 142 WTERMSIG(sshpam_thread_status) == SIGTERM) 143 return; /* terminated by pthread_cancel */ 144 if (!WIFEXITED(sshpam_thread_status)) 145 fatal("PAM: authentication thread exited unexpectedly"); 146 if (WEXITSTATUS(sshpam_thread_status) != 0) 147 fatal("PAM: authentication thread exited uncleanly"); 148} 149 | 101 102extern ServerOptions options; 103extern Buffer loginmsg; 104extern int compat20; 105extern u_int utmp_len; 106 107/* so we don't silently change behaviour */ 108#ifdef USE_POSIX_THREADS --- 53 unchanged lines hidden (view full) --- 162 WTERMSIG(sshpam_thread_status) == SIGTERM) 163 return; /* terminated by pthread_cancel */ 164 if (!WIFEXITED(sshpam_thread_status)) 165 fatal("PAM: authentication thread exited unexpectedly"); 166 if (WEXITSTATUS(sshpam_thread_status) != 0) 167 fatal("PAM: authentication thread exited uncleanly"); 168} 169 |
170/* ARGSUSED */ |
|
150static void | 171static void |
151pthread_exit(void *value __unused) | 172pthread_exit(void *value) |
152{ 153 _exit(0); 154} 155 | 173{ 174 _exit(0); 175} 176 |
177/* ARGSUSED */ |
|
156static int | 178static int |
157pthread_create(sp_pthread_t *thread, const void *attr __unused, | 179pthread_create(sp_pthread_t *thread, const void *attr, |
158 void *(*thread_start)(void *), void *arg) 159{ 160 pid_t pid; 161 struct pam_ctxt *ctx = arg; 162 163 sshpam_thread_status = -1; 164 switch ((pid = fork())) { 165 case -1: --- 15 unchanged lines hidden (view full) --- 181 182static int 183pthread_cancel(sp_pthread_t thread) 184{ 185 signal(SIGCHLD, sshpam_oldsig); 186 return (kill(thread, SIGTERM)); 187} 188 | 180 void *(*thread_start)(void *), void *arg) 181{ 182 pid_t pid; 183 struct pam_ctxt *ctx = arg; 184 185 sshpam_thread_status = -1; 186 switch ((pid = fork())) { 187 case -1: --- 15 unchanged lines hidden (view full) --- 203 204static int 205pthread_cancel(sp_pthread_t thread) 206{ 207 signal(SIGCHLD, sshpam_oldsig); 208 return (kill(thread, SIGTERM)); 209} 210 |
211/* ARGSUSED */ |
|
189static int | 212static int |
190pthread_join(sp_pthread_t thread, void **value __unused) | 213pthread_join(sp_pthread_t thread, void **value) |
191{ 192 int status; 193 194 if (sshpam_thread_status != -1) 195 return (sshpam_thread_status); 196 signal(SIGCHLD, sshpam_oldsig); 197 waitpid(thread, &status, 0); 198 return (status); --- 81 unchanged lines hidden (view full) --- 280 281#ifndef UNSUPPORTED_POSIX_THREADS_HACK 282 /* Import variables set by do_pam_account */ 283 sshpam_account_status = buffer_get_int(b); 284 sshpam_password_change_required(buffer_get_int(b)); 285 286 /* Import environment from subprocess */ 287 num_env = buffer_get_int(b); | 214{ 215 int status; 216 217 if (sshpam_thread_status != -1) 218 return (sshpam_thread_status); 219 signal(SIGCHLD, sshpam_oldsig); 220 waitpid(thread, &status, 0); 221 return (status); --- 81 unchanged lines hidden (view full) --- 303 304#ifndef UNSUPPORTED_POSIX_THREADS_HACK 305 /* Import variables set by do_pam_account */ 306 sshpam_account_status = buffer_get_int(b); 307 sshpam_password_change_required(buffer_get_int(b)); 308 309 /* Import environment from subprocess */ 310 num_env = buffer_get_int(b); |
288 sshpam_env = xmalloc((num_env + 1) * sizeof(*sshpam_env)); | 311 if (num_env > 1024) 312 fatal("%s: received %u environment variables, expected <= 1024", 313 __func__, num_env); 314 sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env)); |
289 debug3("PAM: num env strings %d", num_env); 290 for(i = 0; i < num_env; i++) 291 sshpam_env[i] = buffer_get_string(b, NULL); 292 293 sshpam_env[num_env] = NULL; 294 295 /* Import PAM environment from subprocess */ 296 num_env = buffer_get_int(b); --- 30 unchanged lines hidden (view full) --- 327 if (data == NULL) { 328 error("PAM: conversation function passed a null context"); 329 return (PAM_CONV_ERR); 330 } 331 ctxt = data; 332 if (n <= 0 || n > PAM_MAX_NUM_MSG) 333 return (PAM_CONV_ERR); 334 | 315 debug3("PAM: num env strings %d", num_env); 316 for(i = 0; i < num_env; i++) 317 sshpam_env[i] = buffer_get_string(b, NULL); 318 319 sshpam_env[num_env] = NULL; 320 321 /* Import PAM environment from subprocess */ 322 num_env = buffer_get_int(b); --- 30 unchanged lines hidden (view full) --- 353 if (data == NULL) { 354 error("PAM: conversation function passed a null context"); 355 return (PAM_CONV_ERR); 356 } 357 ctxt = data; 358 if (n <= 0 || n > PAM_MAX_NUM_MSG) 359 return (PAM_CONV_ERR); 360 |
335 if ((reply = malloc(n * sizeof(*reply))) == NULL) | 361 if ((reply = calloc(n, sizeof(*reply))) == NULL) |
336 return (PAM_CONV_ERR); | 362 return (PAM_CONV_ERR); |
337 memset(reply, 0, n * sizeof(*reply)); | |
338 339 buffer_init(&buffer); 340 for (i = 0; i < n; ++i) { 341 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 342 case PAM_PROMPT_ECHO_OFF: 343 buffer_put_cstring(&buffer, 344 PAM_MSG_MEMBER(msg, i, msg)); 345 if (ssh_msg_send(ctxt->pam_csock, --- 62 unchanged lines hidden (view full) --- 408 int flags = (options.permit_empty_passwd == 0 ? 409 PAM_DISALLOW_NULL_AUTHTOK : 0); 410#ifndef UNSUPPORTED_POSIX_THREADS_HACK 411 extern char **environ; 412 char **env_from_pam; 413 u_int i; 414 const char *pam_user; 415 const char **ptr_pam_user = &pam_user; | 363 364 buffer_init(&buffer); 365 for (i = 0; i < n; ++i) { 366 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 367 case PAM_PROMPT_ECHO_OFF: 368 buffer_put_cstring(&buffer, 369 PAM_MSG_MEMBER(msg, i, msg)); 370 if (ssh_msg_send(ctxt->pam_csock, --- 62 unchanged lines hidden (view full) --- 433 int flags = (options.permit_empty_passwd == 0 ? 434 PAM_DISALLOW_NULL_AUTHTOK : 0); 435#ifndef UNSUPPORTED_POSIX_THREADS_HACK 436 extern char **environ; 437 char **env_from_pam; 438 u_int i; 439 const char *pam_user; 440 const char **ptr_pam_user = &pam_user; |
441 char *tz = getenv("TZ"); |
|
416 417 pam_get_item(sshpam_handle, PAM_USER, 418 (sshpam_const void **)ptr_pam_user); | 442 443 pam_get_item(sshpam_handle, PAM_USER, 444 (sshpam_const void **)ptr_pam_user); |
445 |
|
419 environ[0] = NULL; | 446 environ[0] = NULL; |
447 if (tz != NULL) 448 if (setenv("TZ", tz, 1) == -1) 449 error("PAM: could not set TZ environment: %s", 450 strerror(errno)); |
|
420 421 if (sshpam_authctxt != NULL) { 422 setproctitle("%s [pam]", 423 sshpam_authctxt->valid ? pam_user : "unknown"); 424 } 425#endif 426 427 sshpam_conv.conv = sshpam_thread_conv; --- 7 unchanged lines hidden (view full) --- 435 (const void *)&sshpam_conv); 436 if (sshpam_err != PAM_SUCCESS) 437 goto auth_fail; 438 sshpam_err = pam_authenticate(sshpam_handle, flags); 439 if (sshpam_err != PAM_SUCCESS) 440 goto auth_fail; 441 442 if (compat20) { | 451 452 if (sshpam_authctxt != NULL) { 453 setproctitle("%s [pam]", 454 sshpam_authctxt->valid ? pam_user : "unknown"); 455 } 456#endif 457 458 sshpam_conv.conv = sshpam_thread_conv; --- 7 unchanged lines hidden (view full) --- 466 (const void *)&sshpam_conv); 467 if (sshpam_err != PAM_SUCCESS) 468 goto auth_fail; 469 sshpam_err = pam_authenticate(sshpam_handle, flags); 470 if (sshpam_err != PAM_SUCCESS) 471 goto auth_fail; 472 473 if (compat20) { |
443 if (!do_pam_account()) | 474 if (!do_pam_account()) { 475 sshpam_err = PAM_ACCT_EXPIRED; |
444 goto auth_fail; | 476 goto auth_fail; |
477 } |
|
445 if (sshpam_authctxt->force_pwchange) { 446 sshpam_err = pam_chauthtok(sshpam_handle, 447 PAM_CHANGE_EXPIRED_AUTHTOK); 448 if (sshpam_err != PAM_SUCCESS) 449 goto auth_fail; 450 sshpam_password_change_required(0); 451 } 452 } --- 25 unchanged lines hidden (view full) --- 478 ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer); 479 buffer_free(&buffer); 480 pthread_exit(NULL); 481 482 auth_fail: 483 buffer_put_cstring(&buffer, 484 pam_strerror(sshpam_handle, sshpam_err)); 485 /* XXX - can't do much about an error here */ | 478 if (sshpam_authctxt->force_pwchange) { 479 sshpam_err = pam_chauthtok(sshpam_handle, 480 PAM_CHANGE_EXPIRED_AUTHTOK); 481 if (sshpam_err != PAM_SUCCESS) 482 goto auth_fail; 483 sshpam_password_change_required(0); 484 } 485 } --- 25 unchanged lines hidden (view full) --- 511 ssh_msg_send(ctxt->pam_csock, sshpam_err, &buffer); 512 buffer_free(&buffer); 513 pthread_exit(NULL); 514 515 auth_fail: 516 buffer_put_cstring(&buffer, 517 pam_strerror(sshpam_handle, sshpam_err)); 518 /* XXX - can't do much about an error here */ |
486 ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer); | 519 if (sshpam_err == PAM_ACCT_EXPIRED) 520 ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer); 521 else 522 ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer); |
487 buffer_free(&buffer); 488 pthread_exit(NULL); 489 490 return (NULL); /* Avoid warning for non-pthread case */ 491} 492 493void 494sshpam_thread_cleanup(void) --- 30 unchanged lines hidden (view full) --- 525 size_t len; 526 527 debug3("PAM: %s called with %d messages", __func__, n); 528 *resp = NULL; 529 530 if (n <= 0 || n > PAM_MAX_NUM_MSG) 531 return (PAM_CONV_ERR); 532 | 523 buffer_free(&buffer); 524 pthread_exit(NULL); 525 526 return (NULL); /* Avoid warning for non-pthread case */ 527} 528 529void 530sshpam_thread_cleanup(void) --- 30 unchanged lines hidden (view full) --- 561 size_t len; 562 563 debug3("PAM: %s called with %d messages", __func__, n); 564 *resp = NULL; 565 566 if (n <= 0 || n > PAM_MAX_NUM_MSG) 567 return (PAM_CONV_ERR); 568 |
533 if ((reply = malloc(n * sizeof(*reply))) == NULL) | 569 if ((reply = calloc(n, sizeof(*reply))) == NULL) |
534 return (PAM_CONV_ERR); | 570 return (PAM_CONV_ERR); |
535 memset(reply, 0, n * sizeof(*reply)); | |
536 537 for (i = 0; i < n; ++i) { 538 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 539 case PAM_ERROR_MSG: 540 case PAM_TEXT_INFO: 541 len = strlen(PAM_MSG_MEMBER(msg, i, msg)); 542 buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len); 543 buffer_append(&loginmsg, "\n", 1 ); --- 90 unchanged lines hidden (view full) --- 634 635static void * 636sshpam_init_ctx(Authctxt *authctxt) 637{ 638 struct pam_ctxt *ctxt; 639 int socks[2]; 640 641 debug3("PAM: %s entering", __func__); | 571 572 for (i = 0; i < n; ++i) { 573 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 574 case PAM_ERROR_MSG: 575 case PAM_TEXT_INFO: 576 len = strlen(PAM_MSG_MEMBER(msg, i, msg)); 577 buffer_append(&loginmsg, PAM_MSG_MEMBER(msg, i, msg), len); 578 buffer_append(&loginmsg, "\n", 1 ); --- 90 unchanged lines hidden (view full) --- 669 670static void * 671sshpam_init_ctx(Authctxt *authctxt) 672{ 673 struct pam_ctxt *ctxt; 674 int socks[2]; 675 676 debug3("PAM: %s entering", __func__); |
642 /* Refuse to start if we don't have PAM enabled */ 643 if (!options.use_pam) | 677 /* 678 * Refuse to start if we don't have PAM enabled or do_pam_account 679 * has previously failed. 680 */ 681 if (!options.use_pam || sshpam_account_status == 0) |
644 return NULL; 645 646 /* Initialize PAM */ 647 if (sshpam_init(authctxt) == -1) { 648 error("PAM: initialization failed"); 649 return (NULL); 650 } 651 --- 43 unchanged lines hidden (view full) --- 695 type = buffer_get_char(&buffer); 696 msg = buffer_get_string(&buffer, NULL); 697 mlen = strlen(msg); 698 switch (type) { 699 case PAM_PROMPT_ECHO_ON: 700 case PAM_PROMPT_ECHO_OFF: 701 *num = 1; 702 len = plen + mlen + 1; | 682 return NULL; 683 684 /* Initialize PAM */ 685 if (sshpam_init(authctxt) == -1) { 686 error("PAM: initialization failed"); 687 return (NULL); 688 } 689 --- 43 unchanged lines hidden (view full) --- 733 type = buffer_get_char(&buffer); 734 msg = buffer_get_string(&buffer, NULL); 735 mlen = strlen(msg); 736 switch (type) { 737 case PAM_PROMPT_ECHO_ON: 738 case PAM_PROMPT_ECHO_OFF: 739 *num = 1; 740 len = plen + mlen + 1; |
703 **prompts = xrealloc(**prompts, len); | 741 **prompts = xrealloc(**prompts, 1, len); |
704 strlcpy(**prompts + plen, msg, len - plen); 705 plen += mlen; 706 **echo_on = (type == PAM_PROMPT_ECHO_ON); 707 xfree(msg); 708 return (0); 709 case PAM_ERROR_MSG: 710 case PAM_TEXT_INFO: 711 /* accumulate messages */ 712 len = plen + mlen + 2; | 742 strlcpy(**prompts + plen, msg, len - plen); 743 plen += mlen; 744 **echo_on = (type == PAM_PROMPT_ECHO_ON); 745 xfree(msg); 746 return (0); 747 case PAM_ERROR_MSG: 748 case PAM_TEXT_INFO: 749 /* accumulate messages */ 750 len = plen + mlen + 2; |
713 **prompts = xrealloc(**prompts, len); | 751 **prompts = xrealloc(**prompts, 1, len); |
714 strlcpy(**prompts + plen, msg, len - plen); 715 plen += mlen; 716 strlcat(**prompts + plen, "\n", len - plen); 717 plen++; 718 xfree(msg); 719 break; | 752 strlcpy(**prompts + plen, msg, len - plen); 753 plen += mlen; 754 strlcat(**prompts + plen, "\n", len - plen); 755 plen++; 756 xfree(msg); 757 break; |
758 case PAM_ACCT_EXPIRED: 759 sshpam_account_status = 0; 760 /* FALLTHROUGH */ |
|
720 case PAM_AUTH_ERR: | 761 case PAM_AUTH_ERR: |
721 debug3("PAM: PAM_AUTH_ERR"); | 762 debug3("PAM: %s", pam_strerror(sshpam_handle, type)); |
722 if (**prompts != NULL && strlen(**prompts) != 0) { 723 *info = **prompts; 724 **prompts = NULL; 725 *num = 0; 726 **echo_on = 0; 727 ctxt->pam_done = -1; | 763 if (**prompts != NULL && strlen(**prompts) != 0) { 764 *info = **prompts; 765 **prompts = NULL; 766 *num = 0; 767 **echo_on = 0; 768 ctxt->pam_done = -1; |
769 xfree(msg); |
|
728 return 0; 729 } 730 /* FALLTHROUGH */ 731 case PAM_SUCCESS: 732 if (**prompts != NULL) { 733 /* drain any accumulated messages */ 734 debug("PAM: %s", **prompts); 735 buffer_append(&loginmsg, **prompts, --- 190 unchanged lines hidden (view full) --- 926 927 debug3("PAM: %s called with %d messages", __func__, n); 928 929 *resp = NULL; 930 931 if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO)) 932 return (PAM_CONV_ERR); 933 | 770 return 0; 771 } 772 /* FALLTHROUGH */ 773 case PAM_SUCCESS: 774 if (**prompts != NULL) { 775 /* drain any accumulated messages */ 776 debug("PAM: %s", **prompts); 777 buffer_append(&loginmsg, **prompts, --- 190 unchanged lines hidden (view full) --- 968 969 debug3("PAM: %s called with %d messages", __func__, n); 970 971 *resp = NULL; 972 973 if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO)) 974 return (PAM_CONV_ERR); 975 |
934 if ((reply = malloc(n * sizeof(*reply))) == NULL) | 976 if ((reply = calloc(n, sizeof(*reply))) == NULL) |
935 return (PAM_CONV_ERR); | 977 return (PAM_CONV_ERR); |
936 memset(reply, 0, n * sizeof(*reply)); | |
937 938 for (i = 0; i < n; ++i) { 939 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 940 case PAM_PROMPT_ECHO_OFF: 941 reply[i].resp = 942 read_passphrase(PAM_MSG_MEMBER(msg, i, msg), 943 RP_ALLOW_STDIN); 944 reply[i].resp_retcode = PAM_SUCCESS; --- 236 unchanged lines hidden --- | 978 979 for (i = 0; i < n; ++i) { 980 switch (PAM_MSG_MEMBER(msg, i, msg_style)) { 981 case PAM_PROMPT_ECHO_OFF: 982 reply[i].resp = 983 read_passphrase(PAM_MSG_MEMBER(msg, i, msg), 984 RP_ALLOW_STDIN); 985 reply[i].resp_retcode = PAM_SUCCESS; --- 236 unchanged lines hidden --- |