Bug 2408 - Expose authentication information to PAM
Summary: Expose authentication information to PAM
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: PAM support (show other bugs)
Version: -current
Hardware: Other Linux
: P5 enhancement
Assignee: Damien Miller
URL:
Keywords:
: 2712 2934 (view as bug list)
Depends on:
Blocks: V_7_8
  Show dependency treegraph
 
Reported: 2015-06-03 17:47 AEST by György Demarcsek
Modified: 2021-04-23 15:09 AEST (History)
9 users (show)

See Also:


Attachments
Expose successful auth methods via environments (pam and shell) (8.13 KB, patch)
2015-11-20 08:43 AEDT, Vincent Brillault
no flags Details | Diff
Expose successful auth methods via environments (pam and shell) (9.52 KB, patch)
2016-02-24 02:47 AEDT, Vincent Brillault
no flags Details | Diff
Expose successful auth methods via environments (pam and shell) (11.46 KB, patch)
2016-02-24 21:50 AEDT, Vincent Brillault
no flags Details | Diff
Also add a configuration option to control the exposure (6.36 KB, patch)
2016-05-03 00:14 AEST, Vincent Brillault
no flags Details | Diff
Expose successful auth methods via environments (pam and shell) (16.63 KB, patch)
2016-07-01 22:26 AEST, Vincent Brillault
no flags Details | Diff
Refactor authctxt information, provide SSH_USER_AUTH (27.25 KB, patch)
2017-05-16 12:15 AEST, Damien Miller
no flags Details | Diff
add ExposeAuthInfo option (29.92 KB, patch)
2017-05-17 11:10 AEST, Damien Miller
no flags Details | Diff
expose to PAM (864 bytes, patch)
2017-06-24 23:24 AEST, Damien Miller
no flags Details | Diff
Expose SSH_AUTH_INFO_0 environment to both session and accounting modules (3.15 KB, patch)
2017-07-28 14:55 AEST, Damien Miller
dtucker: ok+
Details | Diff
expose SSH_AUTH_INFO_0 to PAM auth (17.84 KB, patch)
2017-11-23 07:40 AEDT, Radoslaw Ejsmont
no flags Details | Diff
Expose SSH_AUTH_INFO_0 to PAM auth (1.67 KB, patch)
2017-11-24 18:52 AEDT, Radoslaw Ejsmont
dtucker: ok+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description György Demarcsek 2015-06-03 17:47:35 AEST
It would be beneficial if sshd could expose details about the previously successful authentications to the loaded PAM modules when PAM authentication is used (typically the last method in the chain). E.g. sshd could set a PAM environment variable that holds the useful information, like this:

SSH_USER_AUTH=hostbased RSA SHA256:Iw75Ex+Re8WyIjqHEukxHtwz2weTFTBLPD2J9doYEfU, publickey CA ED25519 SHA256:rLKEbjpoN2+kuMQB7EiPqaeHut65ZfSe/z1EaWtKEmk Cert ID djm@mindrot.org Serial 27908739, password

This way, a smart PAM stack could make decisions based upon the previously successful authentication methods and/or the supplied credentials. For example, one might want to invoke different PAM modules when the user has been successfully authenticated via GSS-API than otherwise. (For more detailed description of my particular use case, please check out: http://serverfault.com/questions/690038/openssh-two-factor-authentication-combined-with-kerberos-public-key)

You can also find some rudimental, PoC code that shows what I've been playing with as a start: https://github.com/dgyuri92/openssh-portable/tree/f/pam_auth_list

For further questions about the idea, please feel free to contact me via e-mail. Thanks a lot.
Comment 1 Vincent Brillault 2015-11-20 08:43:00 AEDT
Created attachment 2754 [details]
Expose successful auth methods via environments (pam and shell)

The attached patch exposes the authentication methods that were successful during the authentication to PAM via a PAM environment variable and to the child shell via an environment variable.

It is inspired from the PoC written by György Demarcsek and the comments he received but uses a different architecture:
- Any Authmethod can fill a "last_details" variable in the Authctxt in case of success. It should fill it with details about the credentials (e.g. RSA fingerprint)
- After each success, userauth_finish@auth2.c aggregate the method used plus, if existing, this data into a "auth_details" variable in the Authctxt
- When creating a new PAM session, export "auth_details" as "SSH_USER_AUTH"
- When creating a shell session, export "auth_details" as "SSH_USER_AUTH", overriding if necessary the value coming from PAM
- Support Privilege Separation (in a somehow degraded form)

I've in fact written 8 atomic patches (aggregated into this one). They are available, with some comments in the commit, on Github: https://github.com/openssh/openssh-portable/compare/master...Feandil:master

This patch have been tested on a openssh-7.1p1 with the publickey and keyboard-interactive methods and considering the following Privilege Separation cases: Off, On, Sandbox (seccomp).

Some improvement could be build on top of this patch:
- Under Privilege Separation, expose details from key authentication
- In auth2-gss (in particular gss-serv-krb5) expose details about the credentials (e.g. the kerberos principal)

However these improvement seem more complex and could maybe be added in a later patch?
Comment 2 Johan 2016-02-19 18:08:33 AEDT
Hi,

just want to +1 for this feature, as this is something I'm looking for as well.
In my case I'd like to use pam_google_authenticator for certain public keys only.

Johan
Comment 3 Vincent Brillault 2016-02-24 02:47:21 AEDT
Created attachment 2791 [details]
Expose successful auth methods via environments (pam and shell)

New version of my patch:
- Rebased on latest openssh sources
- Fix a memory leak in pubkey_auth_info
- Rename/move the newly created function pubkey_format@auth.h to sshkey_format_oneline@sshkey.h as it does not depend on auth.h at all but is simply a sshkey function (added an argument for the fingerprint hash)
- When using PrivSep, expose details from key authentication (by extracting it from mm_answer_keyverify and using sshkey_format_oneline@sshkey.h)

This new version makes the patch behave similarly with and without privilege separation.
Comment 4 Vincent Brillault 2016-02-24 21:50:51 AEDT
Created attachment 2792 [details]
Expose successful auth methods via environments (pam and shell)

Dear all,

Sorry for the spamming, but I just realized that it is possible to expose the 'displayname" of gssapi authentication without a big modification. This new patch now exposes it but unfortunately I was only able to test a port of this patch on Centos sources and not this one directly as the only kerberos-enabled system I have is a Centos system.

This patch is now feature-complete with the feature I was thinking about, but if you see an authentication method that I missed and could also expose relevant information, please tell me.

In the end this patch creates two new functions, both returning  a char* which needs to be freed:
- ssh_gssapi_get_displayname to get the displayname from a gssapi session
- sshkey_format_oneline to format a ssh key as it was formated in pubkey_auth_info
I'm not really good at naming and if anyone has better names for these function, your advice would be appreciated.

Thanks in advance,
Vincent Brillault

PS: individual patches can be found on github: https://github.com/openssh/openssh-portable/compare/master...CERN-CERT:master
Comment 5 Jakub Jelen 2016-04-14 21:36:24 AEST
This seems to be a reasonable way to communicate authentication details with PAM and missing piece in the troublesome two factor authentication in SSH. I didn't find any problem with this patch.

The only thought coming to my mind is possible disclosure of user data to running application(s). I would also consider adding some knob to turn this export off (ExportUserauthEnvironment ?) and turn it off by default. Still, using 2FA is not too common in SSH deployment.
Comment 6 Vincent Brillault 2016-05-03 00:14:53 AEST
Created attachment 2812 [details]
Also add a configuration option to control the exposure

Sorry for the delay. Adding an option to control the exposure of the authentication methods (and its details) to both PAM and the final shell session is a very good idea.

I've attached a new patch which should add that option, but I didn't have time to test it yet. I will port it to our centos-based release and test it.

This patch introduce a new option, ExposeAuthenticationMethods which has 3 valid values:
- never: never expose the successful authentication methods
- pam-only: expose them (in details) to pam only, remove them from the final environment (DEFAULT)
- pam-and-env: in addition to pam, expose them in the final session

Feel free to propose a better name or better values, they currently sound awful (esp. "pam-and-env")
Comment 7 Jakub Jelen 2016-06-10 17:59:35 AEST
Few more notes about the patch:

	{ "exposeauthenticationmethods", sExposeAuthenticationMethods, SSHCFG_GLOBAL },

This should probably say SSHCFG_ALL to allow fine-grained control also in the Match blocks.

	if (options->expose_auth_methods == -1)
		options->expose_auth_methods = EXPOSE_AUTHMETH_PAMONLY;

I would vote for default EXPOSE_AUTHMETH_NEVER (on existing systems). Also in the manual page.
Comment 8 Vincent Brillault 2016-07-01 22:26:04 AEST
Created attachment 2846 [details]
Expose successful auth methods via environments (pam and shell)

Sorry for the delay.

Here is a new version of the patch:
- Defining the parameter as SSHCFG_ALL, to be used in a Match block
- Setting default value to EXPOSE_AUTHMETH_NEVER (I don't have a strong opinion on the default, 'pam-only' would simply the transition for me, but I can adapt)

I'm adding a new version of the patch here in the ticket tracker, but all the atomic patches are available on our Github repo (https://github.com/CERN-CERT/openssh-portable) and the associated PR: https://github.com/openssh/openssh-portable/pull/47

For Redhat/Centos 7 based openssh versions, we also have adapted patches (used internally): https://github.com/CERN-CERT/pam_2fa/tree/gh-pages/atomic
Comment 9 Damien Miller 2017-05-16 12:15:32 AEST
Created attachment 2978 [details]
Refactor authctxt information, provide SSH_USER_AUTH

There's a few overlapping pieces of information already managed via authctxt - strings for auth_log() and the list of already-attempted keys, etc. and I wanted to make the code less confusion and brittle.

So this refactors what's there and uses that refactoring to implement SSH_USER_AUTH in the user and PAM environments. I haven't included a sshd_config knob to control it. I don't think that it's necessary to restrict its visibility to PAM at all, but I might add something to control it ending up in the user environment. Note that I've added filtering of the PAM environment copied back into the user's environment to ensure that SSH_USER_AUTH doesn't "leak" if/when I do add such a knob.

The contents of SSH_USER_AUTH are a bit different to Vincent's patch. The environment variable gets filled with a \n separated list of:

method[/submethod] [extra info]

For each authentication method that succeeded partially or completely. Note that this might include authentication methods that didn't actually contribute to the final success (e.g. if you had "AuthenticationMethods publickey,password hostbased,password" and then authenticated using publickey, hostbased, then password), but I don't think this is a big problem.

For GSSAPI, the "extra info" is the displayname - identical to Vincent's patch.

For public key and hostbased authentication it's the full key(s) used. I figure that this is more general than fingerprints, since you can get all of those via ssh-keygen anyway if you need them. In particular, it permits the use of custom certificate extensions that can be read out using "ssh-keygen -L" that would otherwise have been invisible.

Password and kbd-int have no extra information at present (though kbd-int may set a /submethod).
Comment 10 Damien Miller 2017-05-17 11:10:12 AEST
Created attachment 2980 [details]
add ExposeAuthInfo option

This adds a knob (default=off) to control exposing SSH_AUTH_INFO via the environment. It's still unconditionally sent to PAM though - are there any cases where this would be harmful?
Comment 11 Damien Miller 2017-06-24 23:24:15 AEST
Created attachment 2999 [details]
expose to PAM

User authentication information is now available via SSH_USER_AUTH when sshd_config ExposeAuthInfo is enabled. The design drifted a little from the last patch: the environment variable now points to a file that contains the information rather than including it directly.

This patch implements the PAM part. The authentication information is exposed to PAM session modules by a PAM environment variable SSH_USER_AUTH_0, the "0" being a version number in case we ever need to change the format.
Comment 12 Damien Miller 2017-06-24 23:25:25 AEST
BTW the non-PAM part was committed in https://anongit.mindrot.org/openssh.git/commit/?id=8f574959272ac7fe9239c4f5d10fd913f8920ab0
Comment 13 Damien Miller 2017-07-28 14:55:14 AEST
Created attachment 3022 [details]
Expose SSH_AUTH_INFO_0 environment to both session and accounting modules

This exposes SSH_AUTH_INFO_0 to PAM accounting modules as well as session modules.

It also filters SSH_AUTH_INFO_0 from the PAM environment when reading it back into the session environment to ensure it doesn't leak.
Comment 14 Darren Tucker 2017-07-28 15:00:32 AEST
Comment on attachment 3022 [details]
Expose SSH_AUTH_INFO_0 environment to both session and accounting modules

>+	 * The enviornment variable is versioned. Please increment the

s/enviornment/environment/

otherwise ok.
Comment 15 Damien Miller 2017-07-28 15:03:51 AEST
Patch applied. This will be in OpenSSH 7.6
Comment 16 Radoslaw Ejsmont 2017-11-21 22:18:45 AEDT
Hi,

I took a look at the original patch proposed by György and sources of 7.6 release. While the proposed patches expose auth info to PAM for session and accounting modules, reading OPs sources and his use case (https://cern-cert.github.io/pam_2fa/) I recon that the proposed patch does not solve OPs problem. The initial idea behind this patch was to allow PAM to detect successful authentication performed by openssh own methods and decide which additional authentication methods were required. The design was to allow users to log-in using PAM keyboard-interactive (passwd, mysql, ldap, whatever) getting a proper password prompt and 2FA (google, yubico, whatever) or using openssh own mechanism (pubkey, gssapi), avoid password prompt and jump directly to 2FA prompt.  This use case requires exposure of SSH_AUTH_INFO within auth module, not session or accounting.

Could György please comment on that?


Best,

Radek
Comment 17 Radoslaw Ejsmont 2017-11-23 07:40:58 AEDT
Created attachment 3089 [details]
expose SSH_AUTH_INFO_0 to PAM auth
Comment 18 Damien Miller 2017-11-24 13:56:55 AEDT
I don't understand that patch at all. It seems to add another option and a heap of parallel infrastructure to track information that sshd already has in authctxt->session_info
Comment 19 Radoslaw Ejsmont 2017-11-24 18:52:30 AEDT
Created attachment 3091 [details]
Expose SSH_AUTH_INFO_0 to PAM auth

I have no doubt you did not understand the point of that patch. I uploaded the wrong file! Sorry! My bsd :) Here is the correct one.
Comment 20 Damien Miller 2017-11-24 22:56:58 AEDT
Hah :)

Have you checked whether this patch works? IIRC there was some difficulty in exposing it to auth modules in some cases, possibly for the keyboard-interactive case.
Comment 21 Radoslaw Ejsmont 2017-11-25 01:45:30 AEDT
Hi!

I have tested it with publickey,keyboard-interactive:pam and keyboard-interactive:pam on ubuntu xenial (compiled from patched Sid source package). Works like a charm. Tested with pam_exec to see if it's set and with a patched version (updated variable name) of cern-cert pam_ssh_user_auth (https://github.com/CERN-CERT/pam_2fa). Worked just fine.
Comment 22 Vincent Brillault 2017-12-22 21:12:59 AEDT
Dear all,

Sorry for the long absence of comment.

We (CERN) have been using RedHat's patch (see e.g. https://git.centos.org/blob/rpms!openssh.git/c7/SOURCES!openssh-7.4p1-expose-pam.patch) and it's working perfectly for us (I need to update the github page). I had seen yours commits in June (which made sense but I didn't have time to review then) but completely missed your commits in July, thanks for both and sorry for the absence of reply/review.

I've tried to take a look at the patches right now.

I understand that you have added "expose_authinfo" calls to the do_pam_session & do_pam_account function to make sure that the data is up to date at these points in time. I think this was missing in the patch I submitted, thanks! However, as Radek found out, one important step is missed: the authentication part of pam.

What is important for the 2FA case is that this variable is set when calling pam_authenticate, to allow pam modules to make a choice depending on what already happened. In my case (CERN), it's simply skipping the standard password authentication part if there was a successful authentication). Calling "expose_authinfo" just before the pam thread is started, as proposed by Radek, should resolve this problem. I have not tested it, but this is what my patch was doing (see e.g. https://bugzilla.mindrot.org/attachment.cgi?id=2846&action=diff#a/auth-pam.c_sec1) and what RedHat is doing (https://git.centos.org/blob/rpms!openssh.git/c7/SOURCES!openssh-7.4p1-expose-pam.patch#L184).

Sorry again and thanks for all your work,
Vincent
Comment 23 Damien Miller 2018-02-10 17:05:48 AEDT
Comment on attachment 3091 [details]
Expose SSH_AUTH_INFO_0 to PAM auth

Looks ok to me. Darren?
Comment 24 Darren Tucker 2018-02-10 17:15:25 AEDT
Comment on attachment 3091 [details]
Expose SSH_AUTH_INFO_0 to PAM auth

>+	 * The enviornment variable is versioned.

typo enviornment -> environment

otherwise OK.
Comment 25 Damien Miller 2018-04-06 14:09:25 AEST
*** Bug 2712 has been marked as a duplicate of this bug. ***
Comment 26 Damien Miller 2018-04-06 14:13:27 AEST
Radoslaw's patch is applied and will be in OpenSSH 7.8.
Comment 27 Damien Miller 2018-11-26 12:32:14 AEDT
*** Bug 2934 has been marked as a duplicate of this bug. ***
Comment 28 Damien Miller 2021-04-23 15:09:18 AEST
closing resolved bugs as of 8.6p1 release