diff -wpruN --no-dereference '--exclude=*.orig' a~/auth-pam.c a/auth-pam.c --- a~/auth-pam.c 1970-01-01 00:00:00 +++ a/auth-pam.c 1970-01-01 00:00:00 @@ -699,14 +699,83 @@ sshpam_cleanup(void) sshpam_initial_user = NULL; } +#ifdef PAM_ENHANCEMENT +char * +derive_pam_service_name(Authctxt *authctxt) +{ + char *svcname = xmalloc(BUFSIZ); + + /* + * If PamServiceName is set we use that for everything, including + * SSHv1 + */ + if (options.pam_service_name != NULL) { + (void) strlcpy(svcname, options.pam_service_name, BUFSIZ); + return (svcname); + } + + char *method_name = authctxt->authmethod_name; + + if (!method_name) + fatal("Userauth method unknown while starting PAM"); + + /* + * For SSHv2 we use "sshd- + * The "sshd" prefix can be changed via the PAMServicePrefix + * sshd_config option. + */ + if (strcmp(method_name, "none") == 0) { + snprintf(svcname, BUFSIZ, "%s-none", + options.pam_service_prefix); + } + if (strcmp(method_name, "password") == 0) { + snprintf(svcname, BUFSIZ, "%s-password", + options.pam_service_prefix); + } + if (strcmp(method_name, "keyboard-interactive") == 0) { + /* "keyboard-interactive" is too long, shorten it */ + snprintf(svcname, BUFSIZ, "%s-kbdint", + options.pam_service_prefix); + } + if (strcmp(method_name, "publickey") == 0) { + /* "publickey" is too long, shorten it */ + snprintf(svcname, BUFSIZ, "%s-pubkey", + options.pam_service_prefix); + } + if (strcmp(method_name, "hostbased") == 0) { + snprintf(svcname, BUFSIZ, "%s-hostbased", + options.pam_service_prefix); + } + if (strncmp(method_name, "gssapi-", 7) == 0) { + /* + * Although OpenSSH only supports "gssapi-with-mic" + * for now. We will still map any userauth method + * prefixed with "gssapi-" to the gssapi PAM service. + */ + snprintf(svcname, BUFSIZ, "%s-gssapi", + options.pam_service_prefix); + } + return svcname; +} +#endif /* PAM_ENHANCEMENT */ + static int sshpam_init(struct ssh *ssh, Authctxt *authctxt) { const char *user = authctxt->user; int r; +#ifdef PAM_ENHANCEMENT + const char *pam_service; + const char **ptr_pam_service = &pam_service; + char *svc = NULL; + + svc = derive_pam_service_name(authctxt); + debug3("PAM service is %s", svc); +#else if (options.pam_service_name == NULL) fatal_f("internal error: NULL PAM service name"); +#endif #if defined(PAM_SUN_CODEBASE) && defined(PAM_MAX_RESP_SIZE) /* Protect buggy PAM implementations from excessively long usernames */ if (strlen(user) >= PAM_MAX_RESP_SIZE) @@ -716,15 +785,62 @@ sshpam_init(struct ssh *ssh, Authctxt *a if (sshpam_handle == NULL && ssh == NULL) fatal("%s: called initially with no packet context", __func__); if (sshpam_handle != NULL) { +#ifdef PAM_ENHANCEMENT + const char *pam_user; + const char **ptr_pam_user = &pam_user; + + /* get the pam service name */ + sshpam_err = pam_get_item(sshpam_handle, + PAM_SERVICE, (sshpam_const void **)ptr_pam_service); + if (sshpam_err != PAM_SUCCESS) + fatal("Failed to get the PAM service name"); + debug3("Previous pam_service is %s", pam_service ? + pam_service : "NULL"); + + /* get the pam user name */ + sshpam_err = pam_get_item(sshpam_handle, + PAM_USER, (sshpam_const void **)ptr_pam_user); + + /* + * only need to re-start if either user or service is + * different. + */ + if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0 + && strncmp(svc, pam_service, strlen(svc)) == 0) { + free(svc); + return (0); + } + + /* + * Clean up previous PAM state. No need to clean up session + * and creds. + */ + sshpam_authenticated = 0; + sshpam_account_status = -1; + + sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, NULL); + if (sshpam_err != PAM_SUCCESS) + debug3("Cannot remove PAM conv"); /* a warning only */ +#else /* We already have a PAM context; check if the user matches */ if ((sshpam_err = check_pam_user(authctxt)) != PAM_SUCCESS) fatal("PAM user mismatch"); return 0; +#endif } +#ifdef PAM_ENHANCEMENT + debug("PAM: initializing for \"%s\" with service \"%s\"", user, svc); + debug3("Starting PAM service %s for user %s method %s", svc, user, + authctxt->authmethod_name); + sshpam_err = + pam_start(svc, user, &store_conv, &sshpam_handle); + free(svc); +#else debug("PAM: initializing for \"%s\" with service \"%s\"", user, options.pam_service_name); sshpam_err = pam_start(options.pam_service_name, user, &store_conv, &sshpam_handle); +#endif sshpam_initial_user = xstrdup(user); sshpam_authctxt = authctxt; diff -wpruN --no-dereference '--exclude=*.orig' a~/auth.h a/auth.h --- a~/auth.h 1970-01-01 00:00:00 +++ a/auth.h 1970-01-01 00:00:00 @@ -95,6 +95,9 @@ struct Authctxt { /* Information exposed to session */ struct sshbuf *session_info; /* Auth info for environment */ +#ifdef PAM_ENHANCEMENT + char *authmethod_name; +#endif }; /* diff -wpruN --no-dereference '--exclude=*.orig' a~/auth2.c a/auth2.c --- a~/auth2.c 1970-01-01 00:00:00 +++ a/auth2.c 1970-01-01 00:00:00 @@ -313,9 +313,17 @@ input_userauth_request(int type, uint32_ #endif } #ifdef USE_PAM +#ifdef PAM_ENHANCEMENT + /* + * Start PAM here and once only, if each userauth does not + * has its own PAM service. + */ + if (options.use_pam && !options.pam_service_per_authmethod) +#else if (options.use_pam) +#endif /* PAM_ENHANCEMENT */ mm_start_pam(ssh); -#endif +#endif /* USE_PAM */ ssh_packet_set_log_preamble(ssh, "%suser %s", authctxt->valid ? "authenticating " : "invalid ", user); setproctitle("%s [net]", authctxt->valid ? user : "unknown"); @@ -348,6 +356,17 @@ input_userauth_request(int type, uint32_ /* try to authenticate user */ m = authmethod_lookup(authctxt, method); if (m != NULL && authctxt->failures < options.max_authtries) { +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT) + /* start PAM service for each userauth */ + if (options.use_pam && options.pam_service_per_authmethod) { + extern void mm_inform_authmethod(char *); + if (authctxt->authmethod_name != NULL) + free(authctxt->authmethod_name); + authctxt->authmethod_name = xstrdup(method); + mm_inform_authmethod(method); + mm_start_pam(ssh); + } +#endif debug2("input_userauth_request: try method %s", method); authenticated = m->userauth(ssh, method); } @@ -373,6 +392,10 @@ userauth_finish(struct ssh *ssh, int aut char *methods; int r, partial = 0; +#ifdef PAM_ENHANCEMENT + debug3("%s: entering", __func__); +#endif + if (authenticated) { if (!authctxt->valid) { fatal("INTERNAL ERROR: authenticated invalid user %s", @@ -396,6 +419,31 @@ userauth_finish(struct ssh *ssh, int aut } if (authenticated && options.num_auth_methods != 0) { +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT) + /* + * If each userauth has its own PAM service, then PAM needs to + * perform the account check for this service. + */ + if (options.use_pam && options.pam_service_per_authmethod) { + int r, success = mm_do_pam_account(); + + /* If PAM returned a message, send it to the user. */ + if (sshbuf_len(loginmsg) > 0) { + if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) + fatal("%s: buffer error: %s", + __func__, ssh_err(r)); + userauth_send_banner(ssh, sshbuf_ptr(loginmsg)); + if ((r = ssh_packet_write_wait(ssh)) != 0) { + sshpkt_fatal(ssh, r, + "%s: send PAM banner", __func__); + } + } + if (!success) { + fatal("Access denied for user %s by PAM " + "account configuration", authctxt->user); + } + } +#endif if (!auth2_update_methods_lists(authctxt, method, submethod)) { authenticated = 0; partial = 1; @@ -413,7 +461,19 @@ userauth_finish(struct ssh *ssh, int aut return; #ifdef USE_PAM +#ifdef PAM_ENHANCEMENT + /* + * PAM needs to perform account checks after auth. However, if each + * userauth has its own PAM service and options.num_auth_methods != 0, + * then no need to perform account checking, because it was done + * already. + */ + if (options.use_pam && authenticated && + !(options.num_auth_methods != 0 && + options.pam_service_per_authmethod)) { +#else if (options.use_pam && authenticated) { +#endif /* PAM_ENHANCEMENT */ int r, success = mm_do_pam_account(); /* If PAM returned a message, send it to the user. */ diff -wpruN --no-dereference '--exclude=*.orig' a~/monitor.c a/monitor.c --- a~/monitor.c 1970-01-01 00:00:00 +++ a/monitor.c 1970-01-01 00:00:00 @@ -111,6 +111,9 @@ int mm_answer_sign(struct ssh *, int, st int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); int mm_answer_authserv(struct ssh *, int, struct sshbuf *); +#ifdef PAM_ENHANCEMENT +int mm_answer_authmethod(struct ssh *, int, struct sshbuf *); +#endif int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); @@ -188,10 +191,17 @@ struct mon_table mon_dispatch_proto20[] {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, +#ifdef PAM_ENHANCEMENT + {MONITOR_REQ_AUTHMETHOD, MON_ISAUTH, mm_answer_authmethod}, +#endif {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM +#ifdef PAM_ENHANCEMENT + {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start}, +#else {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, +#endif {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx}, {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query}, @@ -305,6 +315,23 @@ monitor_child_preauth(struct ssh *ssh, s /* Special handling for multiple required authentications */ if (options.num_auth_methods != 0) { +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT) + /* + * If each userauth has its own PAM service, then PAM + * need to perform account check for this service. + */ + if (options.use_pam && authenticated && + options.pam_service_per_authmethod) { + struct sshbuf *m; + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + mm_request_receive_expect(pmonitor->m_sendfd, + MONITOR_REQ_PAM_ACCOUNT, m); + authenticated = mm_answer_pam_account(ssh, + pmonitor->m_sendfd, m); + sshbuf_free(m); + } +#endif if (authenticated && !auth2_update_methods_lists(authctxt, auth_method, auth_submethod)) { @@ -322,8 +349,21 @@ monitor_child_preauth(struct ssh *ssh, s !auth_root_allowed(ssh, auth_method)) authenticated = 0; #ifdef USE_PAM +#ifdef PAM_ENHANCEMENT + /* + * PAM needs to perform account checks after auth. + * However, if each userauth has its own PAM service + * and options.num_auth_methods != 0, then no need to + * perform account checking, because it was done + * already. + */ + if (options.use_pam && authenticated && + !(options.num_auth_methods != 0 && + options.pam_service_per_authmethod)) { +#else /* PAM needs to perform account checks after auth */ if (options.use_pam && authenticated) { +#endif struct sshbuf *m; if ((m = sshbuf_new()) == NULL) @@ -933,6 +973,10 @@ mm_answer_pwnamallow(struct ssh *ssh, in /* Allow service/style information on the auth context */ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); +#ifdef PAM_ENHANCEMENT + /* Allow authmethod information on the auth context */ + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHMETHOD, 1); +#endif #ifdef USE_PAM if (options.use_pam) @@ -957,6 +1001,27 @@ int mm_answer_auth2_read_banner(struct s return (0); } +#ifdef PAM_ENHANCEMENT +int +mm_answer_authmethod(struct ssh *ssh, int sock, struct sshbuf *m) +{ + Authctxt *authctxt = ssh->authctxt; + + monitor_permit_authentications(1); + /*sshbuf_dump(m, stderr);*/ + sshbuf_get_cstring(m, &authctxt->authmethod_name, NULL); + debug3("%s: authmethod_name=%s", __func__, authctxt->authmethod_name); + + if (authctxt->authmethod_name && + strlen(authctxt->authmethod_name) == 0) { + free(authctxt->authmethod_name); + authctxt->authmethod_name = NULL; + } + + return (0); +} +#endif + int mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m) { diff -wpruN --no-dereference '--exclude=*.orig' a~/monitor.h a/monitor.h --- a~/monitor.h 1970-01-01 00:00:00 +++ a/monitor.h 1970-01-01 00:00:00 @@ -64,6 +64,9 @@ enum monitor_reqtype { MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, +#ifdef PAM_ENHANCEMENT + MONITOR_REQ_AUTHMETHOD = 114, +#endif }; diff -wpruN --no-dereference '--exclude=*.orig' a~/monitor_wrap.c a/monitor_wrap.c --- a~/monitor_wrap.c 1970-01-01 00:00:00 +++ a/monitor_wrap.c 1970-01-01 00:00:00 @@ -440,6 +440,24 @@ mm_inform_authserv(char *service, char * sshbuf_free(m); } +#ifdef PAM_ENHANCEMENT +/* Inform the privileged process about the authentication method */ +void +mm_inform_authmethod(char *authmethod) +{ + struct sshbuf *m; + + debug3("%s entering", __func__); + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new", __func__); + sshbuf_put_cstring(m, authmethod); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHMETHOD, m); + + sshbuf_free(m); +} +#endif /* PAM_ENHANCEMENT */ + /* Do the password authentication */ int mm_auth_password(struct ssh *ssh, char *password) diff -wpruN --no-dereference '--exclude=*.orig' a~/servconf.c a/servconf.c --- a~/servconf.c 1970-01-01 00:00:00 +++ a/servconf.c 1970-01-01 00:00:00 @@ -161,6 +161,15 @@ initialize_server_options(ServerOptions options->subsystem_args = NULL; #define init_timingsecret(options) \ options->timing_secret = 0; +#ifdef PAM_ENHANCEMENT +/* + * Each userauth method will have its own PAM service by default. However, + * if PAMServiceName is specified then there will be only one PAM service + * for the entire user authentication. + */ +#define init_pamserviceperauthmethod(options) \ + options->pam_service_per_authmethod = 1; +#endif SSHD_CONFIG_ENTRIES @@ -180,6 +189,9 @@ initialize_server_options(ServerOptions #undef init_rekeylimit #undef init_subsystem #undef init_timingsecret +#ifdef PAM_ENHANCEMENT +#undef init_pamserviceperauthmethod +#endif #undef SSHCONF_INT #undef SSHCONF_INTFLAG #undef SSHCONF_STRING @@ -305,9 +317,14 @@ fill_default_server_options(ServerOption #undef SSHCONF_ALIAS #ifdef USE_PAM +#ifdef PAM_ENHANCEMENT + if (options->pam_service_prefix == NULL) + options->pam_service_prefix = xstrdup(SSHD_PAM_SERVICE); +#else if (options->pam_service_name == NULL) options->pam_service_name = xstrdup(SSHD_PAM_SERVICE); #endif +#endif if (options->num_host_key_files == 0) { /* fill default hostkeys */ @@ -1180,6 +1197,21 @@ process_server_config_line_depth(ServerO intptr = &options->use_pam; goto parse_flag; #endif +#ifdef PAM_ENHANCEMENT + case sPAMServicePrefix: + charptr = &options->pam_service_prefix; + arg = argv_next(&ac, &av); + if (!arg || *arg == '\0') { + fatal("%s line %d: missing argument.", + filename, linenum); + } + if (options->pam_service_name != NULL) + fatal("%s line %d: PAMServiceName and PAMServicePrefix" + " are mutually exclusive.", filename, linenum); + if (*charptr == NULL) + *charptr = xstrdup(arg); + break; +#endif /* PAM_ENHANCEMENT */ case sPAMServiceName: charptr = &options->pam_service_name; arg = argv_next(&ac, &av); @@ -1187,8 +1219,20 @@ process_server_config_line_depth(ServerO fatal("%s line %d: missing argument.", filename, linenum); } +#ifdef PAM_ENHANCEMENT + if (options->pam_service_prefix != NULL) + fatal("%s line %d: PAMServiceName and PAMServicePrefix" + " are mutually exclusive.", filename, linenum); +#endif /* PAM_ENHANCEMENT */ if (*activep && *charptr == NULL) *charptr = xstrdup(arg); +#ifdef PAM_ENHANCEMENT + /* + * When this option is specified, we will not have + * PAM service for each auth method. + */ + options->pam_service_per_authmethod = 0; +#endif break; #endif @@ -3072,6 +3116,22 @@ serialise_timingsecret(const ServerOptio return 0; } +#ifdef PAM_ENHANCEMENT +static int +serialise_pamserviceperauthmethod(const ServerOptions *options, + struct sshbuf *buf) +{ + int r; + + if ((r = serialise_s32(buf, + options->pam_service_per_authmethod)) != 0) { + error_fr(r, "serialise"); + return r; + } + return 0; +} +#endif /* PAM_ENHANCEMENT */ + int serialise_server_options(const ServerOptions *options, struct sshbuf **bufp) @@ -3606,6 +3666,22 @@ deserialise_timingsecret(ServerOptions * return 0; } +#ifdef PAM_ENHANCEMENT +static int +deserialise_pamserviceperauthmethod(ServerOptions *options, + struct sshbuf *buf) +{ + int r; + + if ((r = deserialise_s32(buf, + &options->pam_service_per_authmethod)) != 0) { + error_fr(r, "deserialise"); + return r; + } + return 0; +} +#endif /* PAM_ENHANCEMENT */ + int deserialise_server_options(struct sshbuf *buf, ServerOptions *options) { @@ -3769,6 +3845,9 @@ free_server_options(ServerOptions *optio #define free_persourcepenalties(options) #define free_rekeylimit(options) #define free_timingsecret(options) +#ifdef PAM_ENHANCEMENT +#define free_pamserviceperauthmethod(options) +#endif SSHD_CONFIG_ENTRIES @@ -3784,6 +3863,9 @@ free_server_options(ServerOptions *optio #undef free_persourcepenalties #undef free_rekeylimit #undef free_timingsecret +#ifdef PAM_ENHANCEMENT +#undef free_pamserviceperauthmethod +#endif #undef SSHCONF_INT #undef SSHCONF_INTFLAG @@ -4195,6 +4277,9 @@ dump_config(ServerOptions *o) #ifdef USE_PAM dump_cfg_fmtint(sUsePAM, o->use_pam); dump_cfg_string(sPAMServiceName, o->pam_service_name); +#ifdef PAM_ENHANCEMENT + dump_cfg_string(sPAMServicePrefix, o->pam_service_prefix); +#endif #endif dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); diff -wpruN --no-dereference '--exclude=*.orig' a~/servconf.h a/servconf.h --- a~/servconf.h 1970-01-01 00:00:00 +++ a/servconf.h 1970-01-01 00:00:00 @@ -272,14 +272,23 @@ SSHCONF_ALIAS(KeepAlive, TCPKeepAlive, S SSHD_CONFIG_ENTRIES_LASTLOG #ifdef USE_PAM +#ifdef PAM_ENHANCEMENT +#define SSHD_CONFIG_ENTRIES_PAM \ +SSHCONF_INTFLAG(use_pam, UsePAM, SSHCFG_GLOBAL, 1, SSHCFG_COPY_NONE) \ +SSHCONF_STRING(pam_service_name, PAMServiceName, SSHCFG_ALL, SSHCFG_COPY_NONE) \ +SSHCONF_STRING(pam_service_prefix, PAMServicePrefix, SSHCFG_GLOBAL, SSHCFG_COPY_NONE) \ +SSHCONF_NONCONF(pamserviceperauthmethod) +#else /* PAM_ENHANCEMENT */ #define SSHD_CONFIG_ENTRIES_PAM \ SSHCONF_INTFLAG(use_pam, UsePAM, SSHCFG_GLOBAL, 1, SSHCFG_COPY_NONE) \ SSHCONF_STRING(pam_service_name, PAMServiceName, SSHCFG_ALL, SSHCFG_COPY_NONE) -#else +#endif /* PAM_ENHANCEMENT */ +#else /* USE_PAM */ #define SSHD_CONFIG_ENTRIES_PAM \ SSHCONF_UNSUPPORTED_INT(use_pam, UsePAM, SSHCFG_GLOBAL) \ -SSHCONF_UNSUPPORTED_STRING(pam_service_name, PAMServiceName, SSHCFG_ALL) -#endif +SSHCONF_UNSUPPORTED_STRING(pam_service_name, PAMServiceName, SSHCFG_ALL) \ +SSHCONF_UNSUPPORTED_STRING(pam_service_prefix, PAMServicePrefix, SSHCFG_GLOBAL) +#endif /* USE_PAM */ #ifdef DISABLE_LASTLOG #define SSHD_CONFIG_ENTRIES_LASTLOG \ @@ -400,6 +409,10 @@ typedef struct ServerOptions { int rekey_interval; /* Passed by config but not keyword for this */ uint64_t timing_secret; +#ifdef PAM_ENHANCEMENT + /* Set as a side-effect of PAMServiceName */ + int pam_service_per_authmethod; +#endif } ServerOptions; #undef SSHCONF_INT #undef SSHCONF_INTFLAG diff -wpruN --no-dereference '--exclude=*.orig' a~/sshd.8 a/sshd.8 --- a~/sshd.8 1970-01-01 00:00:00 +++ a/sshd.8 1970-01-01 00:00:00 @@ -1024,6 +1024,31 @@ concurrently for different ports, this c started last). The content of this file is not sensitive; it can be world-readable. .El +.Sh SECURITY +sshd uses pam(3PAM) for password and keyboard-interactive methods as well as +for account management, session management, and the password management for all +authentication methods. +.Pp +Each SSHv2 userauth type has its own PAM service name: + +.Bd -literal -offset 3n + +----------------------------------------------- +| SSHv2 Userauth | PAM Service Name | +----------------------------------------------- +| none | sshd-none | +----------------------------------------------- +| password | sshd-password | +----------------------------------------------- +| keyboard-interactive | sshd-kbdint | +----------------------------------------------- +| pubkey | sshd-pubkey | +----------------------------------------------- +| hostbased | sshd-hostbased | +----------------------------------------------- +| gssapi-with-mic | sshd-gssapi | +----------------------------------------------- +.Ed .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , diff -wpruN --no-dereference '--exclude=*.orig' a~/sshd_config.5 a/sshd_config.5 --- a~/sshd_config.5 1970-01-01 00:00:00 +++ a/sshd_config.5 1970-01-01 00:00:00 @@ -1355,6 +1355,7 @@ Available keywords are .Cm MaxAuthTries , .Cm MaxSessions , .Cm PAMServiceName , +.Cm PAMServicePrefix , .Cm PasswordAuthentication , .Cm PermitEmptyPasswords , .Cm PermitListen , @@ -1423,12 +1424,34 @@ key exchange methods. The default is .Pa /etc/moduli . .It Cm PAMServiceName -Specifies the service name used for Pluggable Authentication Modules (PAM) -authentication, authorisation and session controls when -.Cm UsePAM -is enabled. -The default is -.Cm sshd . +Specifies the PAM service name for the PAM session. +The +.Cm PAMServiceName +and +.Cm PAMServicePrefix +options are mutually exclusive and if both are set, sshd does not start. +If this option is set the service name is the same for all user authentication +methods. +The option has no default value. +See +.Cm PAMServicePrefix +for more information. +.It Cm PAMServicePrefix +Specifies the PAM service name prefix for service names used for individual +user authentication methods. +The default is sshd. +The +.Cm PAMServiceName +and +.Cm PAMServicePrefix +options are mutually exclusive and if both are set, sshd does not start. +.Pp +For example, if this option is set to +.Cm admincli , +the service name for the keyboard-interactive authentication method is +.Sy admincli-kbdint +instead of the default +.Sy sshd-kbdint . .It Cm PasswordAuthentication Specifies whether password authentication is allowed. The default is @@ -2095,8 +2118,7 @@ If is enabled, you will not be able to run .Xr sshd 8 as a non-root user. -The default is -.Cm no . +On OmniOS, the option is always enabled. .It Cm VersionAddendum Optionally specifies additional text to append to the SSH protocol banner sent by the server upon connection.