1 --- hpn-ssh-hpn-18.4.2/auth-pam.c.orig
2 +++ hpn-ssh-hpn-18.4.2/auth-pam.c
7 +#ifdef PAM_ENHANCEMENT
9 +derive_pam_service_name(Authctxt *authctxt)
11 + char *svcname = xmalloc(BUFSIZ);
14 + * If PamServiceName is set we use that for everything, including
17 + if (options.pam_service_name != NULL) {
18 + (void) strlcpy(svcname, options.pam_service_name, BUFSIZ);
22 + char *method_name = authctxt->authmethod_name;
25 + fatal("Userauth method unknown while starting PAM");
28 + * For SSHv2 we use "sshd-<userauth name>
29 + * The "sshd" prefix can be changed via the PAMServicePrefix
30 + * sshd_config option.
32 + if (strcmp(method_name, "none") == 0) {
33 + snprintf(svcname, BUFSIZ, "%s-none",
34 + options.pam_service_prefix);
36 + if (strcmp(method_name, "password") == 0) {
37 + snprintf(svcname, BUFSIZ, "%s-password",
38 + options.pam_service_prefix);
40 + if (strcmp(method_name, "keyboard-interactive") == 0) {
41 + /* "keyboard-interactive" is too long, shorten it */
42 + snprintf(svcname, BUFSIZ, "%s-kbdint",
43 + options.pam_service_prefix);
45 + if (strcmp(method_name, "publickey") == 0) {
46 + /* "publickey" is too long, shorten it */
47 + snprintf(svcname, BUFSIZ, "%s-pubkey",
48 + options.pam_service_prefix);
50 + if (strcmp(method_name, "hostbased") == 0) {
51 + snprintf(svcname, BUFSIZ, "%s-hostbased",
52 + options.pam_service_prefix);
54 + if (strncmp(method_name, "gssapi-", 7) == 0) {
56 + * Although OpenSSH only supports "gssapi-with-mic"
57 + * for now. We will still map any userauth method
58 + * prefixed with "gssapi-" to the gssapi PAM service.
60 + snprintf(svcname, BUFSIZ, "%s-gssapi",
61 + options.pam_service_prefix);
65 +#endif /* PAM_ENHANCEMENT */
68 sshpam_init(struct ssh *ssh, Authctxt *authctxt)
71 fatal("Username too long from %s port %d",
72 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
75 +#ifdef PAM_ENHANCEMENT
76 + const char *pam_service;
77 + const char **ptr_pam_service = &pam_service;
80 + svc = derive_pam_service_name(authctxt);
81 + debug3("PAM service is %s", svc);
84 if (sshpam_handle == NULL) {
86 fatal("%s: called initially with no "
87 "packet context", __func__);
89 } if (sshpam_handle != NULL) {
90 +#ifdef PAM_ENHANCEMENT
91 + /* get the pam service name */
92 + sshpam_err = pam_get_item(sshpam_handle,
93 + PAM_SERVICE, (sshpam_const void **)ptr_pam_service);
94 + if (sshpam_err != PAM_SUCCESS)
95 + fatal("Failed to get the PAM service name");
96 + debug3("Previous pam_service is %s", pam_service ?
97 + pam_service : "NULL");
99 + /* get the pam user name */
100 + sshpam_err = pam_get_item(sshpam_handle,
101 + PAM_USER, (sshpam_const void **)ptr_pam_user);
104 + * only need to re-start if either user or service is
107 + if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0
108 + && strncmp(svc, pam_service, strlen(svc)) == 0) {
114 + * Clean up previous PAM state. No need to clean up session
117 + sshpam_authenticated = 0;
118 + sshpam_account_status = -1;
120 + sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, NULL);
121 + if (sshpam_err != PAM_SUCCESS)
122 + debug3("Cannot remove PAM conv"); /* a warning only */
123 +#else /* Original */
124 /* We already have a PAM context; check if the user matches */
125 sshpam_err = pam_get_item(sshpam_handle,
126 PAM_USER, (sshpam_const void **)ptr_pam_user);
127 if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
129 +#endif /* PAM_ENHANCEMENT */
130 pam_end(sshpam_handle, sshpam_err);
131 sshpam_handle = NULL;
133 debug("PAM: initializing for \"%s\"", user);
134 +#ifdef PAM_ENHANCEMENT
135 + debug3("Starting PAM service %s for user %s method %s", svc, user,
136 + authctxt->authmethod_name);
138 + pam_start(svc, user, &store_conv, &sshpam_handle);
140 +#else /* Original */
142 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
144 sshpam_authctxt = authctxt;
146 if (sshpam_err != PAM_SUCCESS) {
147 --- hpn-ssh-hpn-18.4.2/auth.h.orig
148 +++ hpn-ssh-hpn-18.4.2/auth.h
151 /* Information exposed to session */
152 struct sshbuf *session_info; /* Auth info for environment */
153 +#ifdef PAM_ENHANCEMENT
154 + char *authmethod_name;
159 --- hpn-ssh-hpn-18.4.2/auth2.c.orig
160 +++ hpn-ssh-hpn-18.4.2/auth2.c
165 +#ifdef PAM_ENHANCEMENT
167 + * Start PAM here and once only, if each userauth does not
168 + * has its own PAM service.
170 + if (options.use_pam && !options.pam_service_per_authmethod)
173 +#endif /* PAM_ENHANCEMENT */
174 PRIVSEP(start_pam(ssh));
176 +#endif /* USE_PAM */
177 ssh_packet_set_log_preamble(ssh, "%suser %s",
178 authctxt->valid ? "authenticating " : "invalid ", user);
179 setproctitle("%s%s", authctxt->valid ? user : "unknown",
181 /* try to authenticate user */
182 m = authmethod_lookup(authctxt, method);
183 if (m != NULL && authctxt->failures < options.max_authtries) {
185 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
186 + /* start PAM service for each userauth */
187 + if (options.use_pam && options.pam_service_per_authmethod) {
188 + if (authctxt->authmethod_name != NULL)
189 + free(authctxt->authmethod_name);
190 + authctxt->authmethod_name = xstrdup(method);
192 + mm_inform_authmethod(method);
193 + PRIVSEP(start_pam(authctxt));
196 debug2("input_userauth_request: try method %s", method);
197 authenticated = m->userauth(ssh, method);
203 +#ifdef PAM_ENHANCEMENT
204 + debug3("%s: entering", __func__);
208 if (!authctxt->valid) {
209 fatal("INTERNAL ERROR: authenticated invalid user %s",
213 if (authenticated && options.num_auth_methods != 0) {
215 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
217 + * If each userauth has its own PAM service, then PAM needs to
218 + * perform the account check for this service.
220 + if (options.use_pam && options.pam_service_per_authmethod &&
221 + !PRIVSEP(do_pam_account())) {
222 + /* if PAM returned a message, send it to the user */
223 + if (sshbuf_len(loginmsg) > 0) {
224 + sshbuf_put(loginmsg, "\0", 1);
225 + userauth_send_banner(ssh, sshbuf_ptr(loginmsg));
226 + ssh_packet_write_wait(ssh);
229 + fatal("Access denied for user %s by PAM account "
230 + "configuration", authctxt->user);
233 if (!auth2_update_methods_lists(authctxt, method, submethod)) {
240 +#ifdef PAM_ENHANCEMENT
242 + * PAM needs to perform account checks after auth. However, if each
243 + * userauth has its own PAM service and options.num_auth_methods != 0,
244 + * then no need to perform account checking, because it was done
247 + if (options.use_pam && authenticated &&
248 + !(options.num_auth_methods != 0 &&
249 + options.pam_service_per_authmethod)) {
251 if (options.use_pam && authenticated) {
253 int r, success = PRIVSEP(do_pam_account());
255 /* If PAM returned a message, send it to the user. */
256 --- hpn-ssh-hpn-18.4.2/monitor.c.orig
257 +++ hpn-ssh-hpn-18.4.2/monitor.c
259 int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
260 int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
261 int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
262 +#ifdef PAM_ENHANCEMENT
263 +int mm_answer_authmethod(struct ssh *, int, struct sshbuf *);
265 int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
266 int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
267 int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
268 @@ -190,10 +193,17 @@
269 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
270 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
271 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
272 +#ifdef PAM_ENHANCEMENT
273 + {MONITOR_REQ_AUTHMETHOD, MON_ISAUTH, mm_answer_authmethod},
275 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
276 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
278 +#ifdef PAM_ENHANCEMENT
279 + {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start},
281 {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
283 {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
284 {MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx},
285 {MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query},
288 /* Special handling for multiple required authentications */
289 if (options.num_auth_methods != 0) {
291 +#if defined(USE_PAM) && defined(PAM_ENHANCEMENT)
293 + * If each userauth has its own PAM service, then PAM
294 + * need to perform account check for this service.
296 + if (options.use_pam && authenticated &&
297 + options.pam_service_per_authmethod) {
299 + if ((m = sshbuf_new()) == NULL)
300 + fatal("%s: sshbuf_new", __func__);
301 + mm_request_receive_expect(pmonitor->m_sendfd,
302 + MONITOR_REQ_PAM_ACCOUNT, m);
303 + authenticated = mm_answer_pam_account(ssh,
304 + pmonitor->m_sendfd, m);
310 !auth2_update_methods_lists(authctxt,
311 auth_method, auth_submethod)) {
313 !auth_root_allowed(ssh, auth_method))
316 +#ifdef PAM_ENHANCEMENT
318 + * PAM needs to perform account checks after auth.
319 + * However, if each userauth has its own PAM service
320 + * and options.num_auth_methods != 0, then no need to
321 + * perform account checking, because it was done
324 + if (options.use_pam && authenticated &&
325 + !(options.num_auth_methods != 0 &&
326 + options.pam_service_per_authmethod)) {
328 /* PAM needs to perform account checks after auth */
329 if (options.use_pam && authenticated) {
333 if ((m = sshbuf_new()) == NULL)
335 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
336 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
338 +#ifdef PAM_ENHANCEMENT
339 + /* Allow authmethod information on the auth context */
340 + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHMETHOD, 1);
345 monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
350 +#ifdef PAM_ENHANCEMENT
352 +mm_answer_authmethod(struct ssh *ssh, int sock, struct sshbuf *m)
354 + Authctxt *authctxt = ssh->authctxt;
356 + monitor_permit_authentications(1);
357 + /*sshbuf_dump(m, stderr);*/
358 + sshbuf_get_cstring(m, &authctxt->authmethod_name, NULL);
359 + debug3("%s: authmethod_name=%s", __func__, authctxt->authmethod_name);
361 + if (authctxt->authmethod_name &&
362 + strlen(authctxt->authmethod_name) == 0) {
363 + free(authctxt->authmethod_name);
364 + authctxt->authmethod_name = NULL;
372 mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
374 --- hpn-ssh-hpn-18.4.2/monitor.h.orig
375 +++ hpn-ssh-hpn-18.4.2/monitor.h
377 MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
378 MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
380 +#ifdef PAM_ENHANCEMENT
381 + MONITOR_REQ_AUTHMETHOD = 114,
386 --- hpn-ssh-hpn-18.4.2/monitor_wrap.c.orig
387 +++ hpn-ssh-hpn-18.4.2/monitor_wrap.c
392 +#ifdef PAM_ENHANCEMENT
393 +/* Inform the privileged process about the authentication method */
395 +mm_inform_authmethod(char *authmethod)
399 + debug3("%s entering", __func__);
400 + if ((m = sshbuf_new()) == NULL)
401 + fatal("%s: sshbuf_new", __func__);
402 + sshbuf_put_cstring(m, authmethod);
404 + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHMETHOD, m);
410 /* Do the password authentication */
412 mm_auth_password(struct ssh *ssh, char *password)
413 --- hpn-ssh-hpn-18.4.2/servconf.c.orig
414 +++ hpn-ssh-hpn-18.4.2/servconf.c
416 options->channel_timeouts = NULL;
417 options->num_channel_timeouts = 0;
418 options->unused_connection_timeout = -1;
419 +#ifdef PAM_ENHANCEMENT
420 + options->pam_service_name = NULL;
421 + options->pam_service_prefix = NULL;
424 + * Each user method will have its own PAM service by default.
425 + * However, if PAMServiceName is specified
426 + * then there will be only one PAM service for the
427 + * entire user authentication.
429 + options->pam_service_per_authmethod = 1;
433 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
435 options->ip_qos_bulk = IPTOS_DSCP_CS1;
436 if (options->version_addendum == NULL)
437 options->version_addendum = xstrdup("");
439 +#ifdef PAM_ENHANCEMENT
440 + if (options->pam_service_prefix == NULL)
441 + options->pam_service_prefix = _SSH_PAM_SERVICE_PREFIX;
444 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
445 options->fwd_opts.streamlocal_bind_mask = 0177;
446 if (options->fwd_opts.streamlocal_bind_unlink == -1)
448 sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
449 sUsePrivilegeSeparation, sAllowAgentForwarding,
450 sHostCertificate, sInclude,
451 +#ifdef PAM_ENHANCEMENT
452 + sPAMServicePrefix, sPAMServiceName,
454 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
455 sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
456 sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
458 { "forcecommand", sForceCommand, SSHCFG_ALL },
459 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
460 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
461 +#ifdef PAM_ENHANCEMENT
462 + { "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL },
463 + { "pamservicename", sPAMServiceName, SSHCFG_GLOBAL },
465 { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
466 { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
467 { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
468 @@ -2649,6 +2674,37 @@
472 + case sPAMServicePrefix:
473 + arg = strdelim(&str);
474 + if (!arg || *arg == '\0')
475 + fatal("%s line %d: Missing argument.",
476 + filename, linenum);
477 + if (options->pam_service_name != NULL)
478 + fatal("%s line %d: PAMServiceName and PAMServicePrefix"
479 + " are mutually exclusive.", filename, linenum);
480 + if (options->pam_service_prefix == NULL)
481 + options->pam_service_prefix = xstrdup(arg);
484 + case sPAMServiceName:
485 + arg = strdelim(&str);
486 + if (!arg || *arg == '\0')
487 + fatal("%s line %d: Missing argument.",
488 + filename, linenum);
489 + if (options->pam_service_prefix != NULL)
490 + fatal("%s line %d: PAMServiceName and PAMServicePrefix"
491 + " are mutually exclusive.", filename, linenum);
492 + if (options->pam_service_name == NULL) {
493 + options->pam_service_name = xstrdup(arg);
496 + * When this option is specified, we will not have
497 + * PAM service for each auth method.
499 + options->pam_service_per_authmethod = 0;
506 --- hpn-ssh-hpn-18.4.2/servconf.h.orig
507 +++ hpn-ssh-hpn-18.4.2/servconf.h
509 struct addrinfo *addrs;
512 +#ifdef PAM_ENHANCEMENT
513 +#define _SSH_PAM_SERVICE_PREFIX "sshd"
518 u_int ports_from_cmdline;
520 u_int num_auth_methods;
523 +#ifdef PAM_ENHANCEMENT
524 + char *pam_service_prefix;
525 + char *pam_service_name;
526 + int pam_service_per_authmethod;
529 int fingerprint_hash;
530 int expose_userauth_info;
531 u_int64_t timing_secret;
532 --- hpn-ssh-hpn-18.4.2/hpnsshd.8.orig
533 +++ hpn-ssh-hpn-18.4.2/hpnsshd.8
534 @@ -1017,6 +1017,33 @@
536 The content of this file is not sensitive; it can be world-readable.
540 +sshd uses pam(3PAM) for password and keyboard-interactive methods as well as
541 +for account management, session management, and the password management for all
542 +authentication methods.
544 +Each SSHv2 userauth type has its own PAM service name:
546 +.Bd -literal -offset 3n
548 +-----------------------------------------------
549 +| SSHv2 Userauth | PAM Service Name |
550 +-----------------------------------------------
551 +| none | sshd-none |
552 +-----------------------------------------------
553 +| password | sshd-password |
554 +-----------------------------------------------
555 +| keyboard-interactive | sshd-kbdint |
556 +-----------------------------------------------
557 +| pubkey | sshd-pubkey |
558 +-----------------------------------------------
559 +| hostbased | sshd-hostbased |
560 +-----------------------------------------------
561 +| gssapi-with-mic | sshd-gssapi |
562 +-----------------------------------------------
568 --- hpn-ssh-hpn-18.4.2/hpnsshd_config.5.orig
569 +++ hpn-ssh-hpn-18.4.2/hpnsshd_config.5
570 @@ -1400,6 +1400,35 @@
571 protection against man-in-the-middle attacks. As with NoneEnabled all authentication
572 remains encrypted and integrity is ensured. Default is
574 +.It Cm PAMServiceName
575 +Specifies the PAM service name for the PAM session.
579 +.Cm PAMServicePrefix
580 +options are mutually exclusive and if both are set, sshd does not start.
581 +If this option is set the service name is the same for all user authentication
583 +The option has no default value.
585 +.Cm PAMServicePrefix
586 +for more information.
587 +.It Cm PAMServicePrefix
588 +Specifies the PAM service name prefix for service names used for individual
589 +user authentication methods.
590 +The default is sshd.
594 +.Cm PAMServicePrefix
595 +options are mutually exclusive and if both are set, sshd does not start.
597 +For example, if this option is set to
599 +the service name for the keyboard-interactive authentication method is
601 +instead of the default
603 .It Cm PasswordAuthentication
604 Specifies whether password authentication is allowed.
606 @@ -1950,8 +1979,7 @@
607 is enabled, you will not be able to run
612 +On OpenIndiana, the option is always enabled.
613 .It Cm VersionAddendum
614 Optionally specifies additional text to append to the SSH protocol banner
615 sent by the server upon connection.