? aix43 ? hpux ? linux ? sol8 Index: TODO =================================================================== RCS file: /cvs/openssh/TODO,v retrieving revision 1.52 diff -u -r1.52 TODO --- TODO 9 Jan 2003 22:53:12 -0000 1.52 +++ TODO 10 Jan 2003 22:39:25 -0000 @@ -15,8 +15,6 @@ - More platforms for for setproctitle() emulation (testing needed) -- Handle changing passwords for the non-PAM expired password case - - Improve PAM support (a pam_lastlog module will cause sshd to exit) and maybe support alternate forms of authentications like OPIE via pam? Index: acconfig.h =================================================================== RCS file: /cvs/openssh/acconfig.h,v retrieving revision 1.146 diff -u -r1.146 acconfig.h --- acconfig.h 7 Jan 2003 04:18:33 -0000 1.146 +++ acconfig.h 10 Jan 2003 22:39:26 -0000 @@ -25,6 +25,9 @@ /* from environment and PATH */ #undef LOGIN_PROGRAM_FALLBACK +/* Path to passwd program */ +#undef PASSWD_PROGRAM_PATH + /* Define if your password has a pw_class field */ #undef HAVE_PW_CLASS_IN_PASSWD Index: auth-pam.c =================================================================== RCS file: /cvs/openssh/auth-pam.c,v retrieving revision 1.54 diff -u -r1.54 auth-pam.c --- auth-pam.c 28 Jul 2002 20:24:08 -0000 1.54 +++ auth-pam.c 10 Jan 2003 22:39:26 -0000 @@ -60,7 +60,7 @@ /* states for do_pam_conversation() */ enum { INITIAL_LOGIN, OTHER } pamstate = INITIAL_LOGIN; /* remember whether pam_acct_mgmt() returned PAM_NEW_AUTHTOK_REQD */ -static int password_change_required = 0; +extern int password_change_required; /* remember whether the last pam_authenticate() succeeded or not */ static int was_authenticated = 0; @@ -260,12 +260,7 @@ case PAM_NEW_AUTHTOK_REQD: message_cat(&__pam_msg, use_privsep ? NEW_AUTHTOK_MSG_PRIVSEP : NEW_AUTHTOK_MSG); - /* flag that password change is necessary */ - password_change_required = 1; - /* disallow other functionality for now */ - no_port_forwarding_flag |= 2; - no_agent_forwarding_flag |= 2; - no_x11_forwarding_flag |= 2; + flag_password_change_required(); break; #endif default: Index: auth-passwd.c =================================================================== RCS file: /cvs/openssh/auth-passwd.c,v retrieving revision 1.48 diff -u -r1.48 auth-passwd.c --- auth-passwd.c 25 Sep 2002 23:14:16 -0000 1.48 +++ auth-passwd.c 10 Jan 2003 22:39:26 -0000 @@ -42,6 +42,11 @@ #include "log.h" #include "servconf.h" #include "auth.h" +#include "buffer.h" +#include "misc.h" +#include "channels.h" +#include "monitor_wrap.h" +#include "auth-options.h" #if !defined(USE_PAM) && !defined(HAVE_OSF_SIA) /* Don't need any of these headers for the PAM or SIA cases */ @@ -81,9 +86,9 @@ #endif /* !USE_PAM && !HAVE_OSF_SIA */ extern ServerOptions options; -#ifdef WITH_AIXAUTHENTICATE -extern char *aixloginmsg; -#endif +extern Buffer login_message; +extern int password_change_required; +pid_t password_change_pid; /* pid used to reset forwarding flags */ /* * Tries to authenticate the user using password. Returns true if @@ -123,6 +128,7 @@ /* deny if no user. */ if (pw == NULL) return 0; + buffer_init(&login_message); #ifndef HAVE_CYGWIN if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) return 0; @@ -149,13 +155,25 @@ #endif #ifdef WITH_AIXAUTHENTICATE authsuccess = (authenticate(pw->pw_name,password,&reenter,&authmsg) == 0); + aix_remove_embedded_newlines(authmsg); + + if (authsuccess) { + char *msg; - if (authsuccess) + debug("authenticate() succeeded for user %s: %.100s", + pw->pw_name, authmsg); /* We don't have a pty yet, so just label the line as "ssh" */ if (loginsuccess(authctxt->user, - get_canonical_hostname(options.verify_reverse_mapping), - "ssh", &aixloginmsg) < 0) - aixloginmsg = NULL; + get_canonical_hostname(options.verify_reverse_mapping), + "ssh", &msg) < 0) + msg = NULL; + buffer_append(&login_message, msg, strlen(msg)); + } else { + debug("AIX authenticate() failed for user %s: %.100s", + pw->pw_name, authmsg); + } + if (authmsg) + xfree(authmsg); return(authsuccess); #endif @@ -232,4 +250,124 @@ /* Authentication is accepted if the encrypted passwords are identical. */ return (strcmp(encrypted_password, pw_password) == 0); #endif /* !USE_PAM && !HAVE_OSF_SIA */ +} + +/* + * Perform generic password change via tty. Like do_pam_chauthtok(), + * it throws a fatal error if the password can't be changed. + */ +int +do_tty_change_password(struct passwd *pw) +{ + pid_t pid; + int status; + mysig_t old_signal; + + old_signal = mysignal(SIGCHLD, SIG_DFL); + + if ((pid = fork()) == -1) + fatal("Couldn't fork: %s", strerror(errno)); + + if (pid == 0) { + setuid(pw->pw_uid); + if (geteuid() == 0) + execl(PASSWD_PROGRAM_PATH, "passwd", pw->pw_name, + (char *)NULL); + else + execl(PASSWD_PROGRAM_PATH, "passwd", (char *)NULL); + + /* execl shouldn't return */ + fatal("Couldn't exec %s", PASSWD_PROGRAM_PATH); + exit(1); + } + + if (waitpid(pid, &status, 0) == -1) + fatal("Couldn't wait for child: %s", strerror(errno)); + mysignal(SIGCHLD, old_signal); + + /* + * passwd sometimes returns 0 when the password has not been changed + * so we must re-test if change is still required. + */ + if (WIFEXITED(status) && WEXITSTATUS(status) == 0 && + PRIVSEP(is_password_change_required(pw)) == 0) { + debug("%s password changed sucessfully", __func__); + flag_password_change_successful(); + return 1; + } else { + fatal("Failed to change password for %s, passwd returned %d", + pw->pw_name, status); + return 0; + } +} + +/* + * Checks account requires password to be changed. + * 0 = no change, 1 = change reqd, 2 = can't change + */ +int +is_password_change_required(struct passwd *pw) +{ + password_change_required = 0; + /* re-test, sets password_change_required */ + if (getpwnamallow(pw->pw_name) == NULL) + password_change_required = 2; + debug3("%s change required %d", __func__, password_change_required); + return password_change_required; +} + +/* + * Because an expired password is changed after forking to exec the user's + * shell, restoring the port forwarding flags is done by sending a + * USR1 signal to the parent after the password is changed successfully. + */ +void +flag_password_change_required(void) +{ + debug("%s disabling forwarding flags", __func__); + /* flag that password change is necessary */ + password_change_required = 1; + + /* disallow other functionality for now */ + no_port_forwarding_flag |= 2; + no_agent_forwarding_flag |= 2; + no_x11_forwarding_flag |= 2; + + /* set handler to reset flags */ + password_change_pid = getpid(); + mysignal(SIGUSR1, password_change_successful_handler); +} + +/* + * password change successful, tell parent to restore port + * forwarding flags + */ +void +flag_password_change_successful(void) +{ + debug("%s signalling parent to reset forwarding flags", __func__); + kill(password_change_pid, SIGUSR1); + + /* reset flags in local process too */ + password_change_required = 0; + no_port_forwarding_flag &= ~2; + no_agent_forwarding_flag &= ~2; + no_x11_forwarding_flag &= ~2; +} + +/* + * signal handler to reset change flags + */ +void +password_change_successful_handler(int sig) +{ + debug("%s restoring port forwarding flags", __func__); + mysignal(SIGUSR1, SIG_DFL); /* unset handler */ + + password_change_required = 0; + no_port_forwarding_flag &= ~2; + no_agent_forwarding_flag &= ~2; + no_x11_forwarding_flag &= ~2; + if (!no_port_forwarding_flag && options.allow_tcp_forwarding) + channel_permit_all_opens(); } Index: auth.c =================================================================== RCS file: /cvs/openssh/auth.c,v retrieving revision 1.66 diff -u -r1.66 auth.c --- auth.c 9 Jan 2003 04:04:28 -0000 1.66 +++ auth.c 10 Jan 2003 22:39:26 -0000 @@ -52,12 +52,17 @@ #include "bufaux.h" #include "packet.h" +#define PWCHG_FORCED "You must change your password now.\n" +#define PWCHG_EXPIRED "Your password has expired, you must change it now.\n" + /* import */ extern ServerOptions options; /* Debugging messages */ Buffer auth_debug; int auth_debug_init; +extern int password_change_required; +extern Buffer expire_message; /* * Check if the user is allowed to log in via ssh. If user is listed @@ -75,13 +80,10 @@ const char *hostname = NULL, *ipaddr = NULL, *passwd; char *shell; int i; -#ifdef WITH_AIXAUTHENTICATE - char *loginmsg; -#endif /* WITH_AIXAUTHENTICATE */ #if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) struct spwd *spw; #if !defined(USE_PAM) && defined(HAS_SHADOW_EXPIRE) - time_t today; + time_t today, expiredate; #endif #endif @@ -111,8 +113,8 @@ #define DAY (24L * 60 * 60) /* 1 day in seconds */ today = time(NULL) / DAY; debug3("allowed_user: today %d sp_expire %d sp_lstchg %d" - " sp_max %d", (int)today, (int)spw->sp_expire, - (int)spw->sp_lstchg, (int)spw->sp_max); + " sp_max %d sp_warn %d", (int)today, (int)spw->sp_expire, + (int)spw->sp_lstchg, (int)spw->sp_max, (int)spw->sp_warn); /* * We assume account and password expiration occurs the @@ -121,19 +123,38 @@ if (spw->sp_expire != -1 && today > spw->sp_expire) { log("Account %.100s has expired", pw->pw_name); return 0; + } else if (spw->sp_expire != -1 && + spw->sp_expire - today < spw->sp_warn) { + char msg[100]; + + snprintf(msg, 100, + "Your account will expire in %d days.\n", + (int)(spw->sp_expire - today)); + buffer_append(&expire_message, msg, strlen(msg)); } + expiredate = spw->sp_lstchg + spw->sp_max; if (spw->sp_lstchg == 0) { log("User %.100s password has expired (root forced)", pw->pw_name); - return 0; - } - - if (spw->sp_max != -1 && - today > spw->sp_lstchg + spw->sp_max) { + flag_password_change_required(); + buffer_append(&expire_message, PWCHG_FORCED, + strlen(PWCHG_FORCED)); + } else if (spw->sp_max == -1) { + debug3("%s password aging disabled", __func__); + } else if (today > expiredate) { log("User %.100s password has expired (password aged)", pw->pw_name); - return 0; + flag_password_change_required(); + buffer_append(&expire_message, PWCHG_EXPIRED, + strlen(PWCHG_EXPIRED)); + } else if (expiredate - today < spw->sp_warn) { + char msg[100]; + + snprintf(msg, 100, + "Your password will expire in %d days.\n", + (int)(expiredate - today)); + buffer_append(&expire_message, msg, strlen(msg)); } #endif @@ -222,27 +243,60 @@ * PermitRootLogin to control logins via ssh), or if running as * non-root user (since loginrestrictions will always fail). */ - if ( (pw->pw_uid != 0) && (geteuid() == 0) && - loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &loginmsg) != 0) { + if ( (pw->pw_uid != 0) && (geteuid() == 0) ) { int loginrestrict_errno = errno; + char *msg; - if (loginmsg && *loginmsg) { - /* Remove embedded newlines (if any) */ - char *p; - for (p = loginmsg; *p; p++) { - if (*p == '\n') - *p = ' '; + /* check for AIX account restrictions */ + if (loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg) != 0) { + if (msg && *msg) { + aix_remove_embedded_newlines(msg); + log("Login restricted for %s: %.100s", + pw->pw_name, msg); + xfree(msg); } - /* Remove trailing newline */ - *--p = '\0'; - log("Login restricted for %s: %.100s", pw->pw_name, - loginmsg); - } - /* Don't fail if /etc/nologin set */ - if (!(loginrestrict_errno == EPERM && - stat(_PATH_NOLOGIN, &st) == 0)) - return 0; + + /* Don't fail if /etc/nologin set */ + if (!(loginrestrict_errno == EPERM && + stat(_PATH_NOLOGIN, &st) == 0)) + return 0; + } } + + /* + * Check AIX password expiry. Only check when running as root. + * Unpriv'ed users can't access /etc/security/passwd or + * /etc/security/user so passwdexpired will always fail. + */ + if (geteuid() == 0) { + char *msg; + int passexpcode; + + enduserdb(); /* flush cached results for passwdexpired */ + passexpcode = passwdexpired(pw->pw_name, &msg); + buffer_append(&expire_message, msg, strlen(msg)); + if (msg && *msg) + aix_remove_embedded_newlines(msg); + debug("AIX passwdexpired returned %d errno %d msg %.100s", + errno, passexpcode, msg); + + switch (passexpcode) { + case 0: /* success, password not expired */ + break; + case 1: /* expired, password change required */ + flag_password_change_required(); + break; + default: /* only admin can change (2) or other error (-1) */ + log("Password can't be changed for user %s: %.100s", + pw->pw_name, msg); + if (msg) + xfree(msg); + return 0; + } + if (msg) + xfree(msg); + + } #endif /* WITH_AIXAUTHENTICATE */ /* We found no reason not to let this user try to log on... */ @@ -508,6 +562,7 @@ #endif struct passwd *pw; + buffer_init(&expire_message); pw = getpwnam(user); if (pw == NULL) { log("Illegal user %.100s from %.100s", Index: auth.h =================================================================== RCS file: /cvs/openssh/auth.h,v retrieving revision 1.44 diff -u -r1.44 auth.h --- auth.h 27 Sep 2002 03:26:01 -0000 1.44 +++ auth.h 10 Jan 2003 22:39:27 -0000 @@ -101,6 +101,8 @@ int auth_rhosts_rsa(struct passwd *, char *, Key *); int auth_password(Authctxt *, const char *); +int do_tty_change_password(struct passwd *pw); +void flag_password_change_required(void); int auth_rsa(struct passwd *, BIGNUM *); int auth_rsa_challenge_dialog(Key *); BIGNUM *auth_rsa_generate_challenge(Key *); @@ -156,6 +158,8 @@ int allowed_user(struct passwd *); struct passwd * getpwnamallow(const char *user); +int is_password_change_required(struct passwd *); +void flag_password_change_successful(void); char *get_challenge(Authctxt *); int verify_response(Authctxt *, const char *); @@ -183,6 +187,8 @@ void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); void auth_debug_send(void); void auth_debug_reset(void); + +void password_change_successful_handler(int); #define AUTH_FAIL_MAX 6 #define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2) Index: configure.ac =================================================================== RCS file: /cvs/openssh/configure.ac,v retrieving revision 1.98 diff -u -r1.98 configure.ac --- configure.ac 9 Jan 2003 22:53:12 -0000 1.98 +++ configure.ac 10 Jan 2003 22:39:28 -0000 @@ -41,6 +41,13 @@ fi fi +AC_PATH_PROG(PASSWD_PROGRAM_PATH, passwd) +if test ! -z "$PASSWD_PROGRAM_PATH" ; then + AC_DEFINE_UNQUOTED(PASSWD_PROGRAM_PATH, "$PASSWD_PROGRAM_PATH") +else + AC_MSG_ERROR([*** passwd command not found - check config.log ***]) +fi + if test -z "$LD" ; then LD=$CC fi Index: log.c =================================================================== RCS file: /cvs/openssh/log.c,v retrieving revision 1.26 diff -u -r1.26 log.c --- log.c 7 Jan 2003 06:04:18 -0000 1.26 +++ log.c 10 Jan 2003 22:39:28 -0000 @@ -233,6 +233,7 @@ next_cu = cu->next; xfree(cu); } + fatal_cleanups = NULL; } /* Cleanup and exit */ Index: monitor.c =================================================================== RCS file: /cvs/openssh/monitor.c,v retrieving revision 1.33 diff -u -r1.33 monitor.c --- monitor.c 9 Nov 2002 15:47:49 -0000 1.33 +++ monitor.c 10 Jan 2003 22:39:29 -0000 @@ -98,6 +98,7 @@ int mm_answer_moduli(int, Buffer *); int mm_answer_sign(int, Buffer *); int mm_answer_pwnamallow(int, Buffer *); +int mm_answer_is_pwchange_reqd(int, Buffer *); int mm_answer_auth2_read_banner(int, Buffer *); int mm_answer_authserv(int, Buffer *); int mm_answer_authpassword(int, Buffer *); @@ -183,6 +184,7 @@ {MONITOR_REQ_PTY, 0, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, + {MONITOR_REQ_PWCHANGE_REQD, 0, mm_answer_is_pwchange_reqd}, {0, 0, NULL} }; @@ -219,6 +221,7 @@ {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, {MONITOR_REQ_TERM, 0, mm_answer_term}, + {MONITOR_REQ_PWCHANGE_REQD, 0, mm_answer_is_pwchange_reqd}, {0, 0, NULL} }; @@ -320,10 +323,12 @@ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_PWCHANGE_REQD, 1); } else { mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_PWCHANGE_REQD, 1); } if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); @@ -558,6 +563,21 @@ #ifdef USE_PAM monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); #endif + + return (0); +} + +int +mm_answer_is_pwchange_reqd(int socket, Buffer *m) +{ + int required; + + buffer_clear(m); + required = is_password_change_required(authctxt->pw); + buffer_put_int(m, required); + + debug3("%s: sending MONITOR_ANS_PWCHANGE_REQD: %d", __func__, required); + mm_request_send(socket, MONITOR_ANS_PWCHANGE_REQD, m); return (0); } Index: monitor.h =================================================================== RCS file: /cvs/openssh/monitor.h,v retrieving revision 1.10 diff -u -r1.10 monitor.h --- monitor.h 27 Sep 2002 03:26:02 -0000 1.10 +++ monitor.h 10 Jan 2003 22:39:29 -0000 @@ -33,6 +33,7 @@ MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, MONITOR_REQ_SIGN, MONITOR_ANS_SIGN, MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM, + MONITOR_REQ_PWCHANGE_REQD, MONITOR_ANS_PWCHANGE_REQD, MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER, MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD, MONITOR_REQ_BSDAUTHQUERY, MONITOR_ANS_BSDAUTHQUERY, Index: monitor_wrap.c =================================================================== RCS file: /cvs/openssh/monitor_wrap.c,v retrieving revision 1.21 diff -u -r1.21 monitor_wrap.c --- monitor_wrap.c 23 Dec 2002 02:06:20 -0000 1.21 +++ monitor_wrap.c 10 Jan 2003 22:39:30 -0000 @@ -207,6 +207,24 @@ return (pw); } +int +mm_is_password_change_required(struct passwd *pw) +{ + Buffer m; + int result; + + debug3("%s entering", __func__); + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWCHANGE_REQD, &m); + buffer_clear(&m); + mm_request_receive_expect(pmonitor->m_recvfd, + MONITOR_ANS_PWCHANGE_REQD, &m); + result = buffer_get_int(&m); + buffer_free(&m); + + return (result); +} + char *mm_auth2_read_banner(void) { Buffer m; Index: monitor_wrap.h =================================================================== RCS file: /cvs/openssh/monitor_wrap.h,v retrieving revision 1.9 diff -u -r1.9 monitor_wrap.h --- monitor_wrap.h 27 Sep 2002 03:26:04 -0000 1.9 +++ monitor_wrap.h 10 Jan 2003 22:39:30 -0000 @@ -44,6 +44,7 @@ int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(const char *); +int mm_is_password_change_required(struct passwd *); char *mm_auth2_read_banner(void); int mm_auth_password(struct Authctxt *, char *); int mm_key_allowed(enum mm_keytype, char *, char *, Key *); Index: session.c =================================================================== RCS file: /cvs/openssh/session.c,v retrieving revision 1.228 diff -u -r1.228 session.c --- session.c 9 Jan 2003 22:53:12 -0000 1.228 +++ session.c 10 Jan 2003 22:39:31 -0000 @@ -102,10 +102,9 @@ /* data */ #define MAX_SESSIONS 10 Session sessions[MAX_SESSIONS]; - -#ifdef WITH_AIXAUTHENTICATE -char *aixloginmsg; -#endif /* WITH_AIXAUTHENTICATE */ +Buffer expire_message; /* "password will expire/has expired" messages */ +Buffer login_message; /* message to be displayed after login */ +int password_change_required = 0; #ifdef HAVE_LOGIN_CAP login_cap_t *lc; @@ -456,10 +455,11 @@ #if defined(USE_PAM) do_pam_session(s->pw->pw_name, NULL); do_pam_setcred(1); - if (is_pam_password_change_required()) +#endif /* USE_PAM */ + + if (password_change_required) packet_disconnect("Password change required but no " "TTY available"); -#endif /* USE_PAM */ /* Fork the child. */ if ((pid = fork()) == 0) { @@ -723,6 +723,7 @@ socklen_t fromlen; struct sockaddr_storage from; struct passwd * pw = s->pw; + int password_changed = 0; pid_t pid = getpid(); /* @@ -746,16 +747,22 @@ options.verify_reverse_mapping), (struct sockaddr *)&from, fromlen); -#ifdef USE_PAM /* * If password change is needed, do it now. * This needs to occur before the ~/.hushlogin check. */ +#ifdef USE_PAM if (is_pam_password_change_required()) { print_pam_messages(); do_pam_chauthtok(); } #endif + buffer_append(&expire_message, "\0", 1); + if (password_change_required) { + puts((char *)buffer_ptr(&expire_message)); + do_tty_change_password(pw); + password_changed = 1; + } if (check_quietlogin(s, command)) return; @@ -764,10 +771,12 @@ if (!is_pam_password_change_required()) print_pam_messages(); #endif /* USE_PAM */ -#ifdef WITH_AIXAUTHENTICATE - if (aixloginmsg && *aixloginmsg) - printf("%s\n", aixloginmsg); -#endif /* WITH_AIXAUTHENTICATE */ + if (!password_changed) + printf("%s", (char *)buffer_ptr(&expire_message)); + + /* display post-login message */ + buffer_append(&login_message, "\0", 1); + puts((char *)buffer_ptr(&login_message)); #ifndef NO_SSH_LASTLOG if (options.print_lastlog && s->last_login_time != 0) { Index: openbsd-compat/port-aix.c =================================================================== RCS file: /cvs/openssh/openbsd-compat/port-aix.c,v retrieving revision 1.6 diff -u -r1.6 port-aix.c --- openbsd-compat/port-aix.c 7 Jul 2002 02:17:36 -0000 1.6 +++ openbsd-compat/port-aix.c 10 Jan 2003 22:39:32 -0000 @@ -52,5 +52,25 @@ xfree(cp); } -#endif /* _AIX */ +#ifdef WITH_AIXAUTHENTICATE +/* + * Remove embedded newlines in string (if any). + * Used before logging messages returned by AIX authentication functions + * so the message is logged on one line. + */ +void +aix_remove_embedded_newlines(char *p) +{ + if (p == NULL) + return; + + for (; *p; p++) { + if (*p == '\n') + *p = ' '; + } + /* Remove trailing newline */ + *--p = '\0'; +} +#endif /* WITH_AIXAUTHENTICATE */ +#endif /* _AIX */ Index: openbsd-compat/port-aix.h =================================================================== RCS file: /cvs/openssh/openbsd-compat/port-aix.h,v retrieving revision 1.6 diff -u -r1.6 port-aix.h --- openbsd-compat/port-aix.h 7 Jul 2002 02:17:36 -0000 1.6 +++ openbsd-compat/port-aix.h 10 Jan 2003 22:39:32 -0000 @@ -26,4 +26,5 @@ #ifdef _AIX void aix_usrinfo(struct passwd *pw); +void aix_remove_embedded_newlines(char *); #endif /* _AIX */