Discussion:
Using 'ForceCommand' Option
(too old to reply)
Lesley Kimmel
2016-02-17 18:59:57 UTC
Permalink
I would like to implement an arbitrary script to be executed when logging
on via SSH. This is supposedly possible using the ForceCommand option to
sshd. However, as soon as I implement any script, even as simple as echoing
a string, clients can no longer connect to the server. Clients report only
that the connection was dropped by the server. The server, in debug mode,
shows:

Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: Starting session: forced-command
(config) '/tmp/s.sh' on pts/3 for kimmell from 198.253.183.24 port 55673
Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: debug3: mm_audit_run_command
entering command /tmp/s.sh
Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: debug3: mm_request_send
entering: type 114
Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: debug3:
mm_request_receive_expect entering: type 115
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: debug3: mm_request_receive
entering Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: debug3:
mm_request_receive entering
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: debug3: monitor_read: checking
request 114
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: debug3: mm_answer_audit_command
entering
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: fatal: mm_answer_audit_command:
error allocating a session Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]:
debug1: do_cleanup
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: debug1: PAM: cleanup Feb 17
16:14:01 is-rhsat-lv02 sshd[12985]: debug1: PAM: closing session
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: pam_unix(sshd:session): session
closed for user <user>
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: debug1: PAM: deleting
credentials
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: debug3: PAM:
sshpam_thread_cleanup entering
Feb 17 16:14:01 is-rhsat-lv02 sshd[12985]: debug1: session_pty_cleanup:
session 0 release /dev/pts/3 Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]:
debug1: do_cleanup
Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: debug3: PAM:
sshpam_thread_cleanup entering
Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: debug3: mm_request_send
entering: type 122
Feb 17 16:14:01 is-rhsat-lv02 sshd[13008]: fatal: mm_request_send: write:
Broken pipe

It may be important to note that this is on RHEL7.

Hopefully this is on-topic. I tried the general OpenSSH discussion list but
there seems to be no activity on that list.

Thanks,
-LJK
Gert Doering
2016-02-17 21:17:19 UTC
Permalink
Hi,
Post by Lesley Kimmel
I would like to implement an arbitrary script to be executed when logging
on via SSH.
I'd just do this in the PAM session handler.

ForceCommand means "run this command *and then exit*", so this is not
what you want.

gert
--
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany ***@greenie.muc.de
fax: +49-89-35655025 ***@net.informatik.tu-muenchen.de
Lesley Kimmel
2016-02-17 21:50:40 UTC
Permalink
Gert,

Thank you for the feedback. Can you give any further direction on where to
get more information on what you are describing?
Post by Gert Doering
Hi,
Post by Lesley Kimmel
I would like to implement an arbitrary script to be executed when logging
on via SSH.
I'd just do this in the PAM session handler.
ForceCommand means "run this command *and then exit*", so this is not
what you want.
gert
--
USENET is *not* the non-clickable part of WWW!
//
www.muc.de/~gert/
Gert Doering - Munich, Germany
fax: +49-89-35655025
Lesley Kimmel
2016-02-17 22:47:27 UTC
Permalink
So I probably shouldn't have said "arbitrary" script. What I really want to
do is to present a terms of service notice (/etc/issue). But I also want to
get the user to actually confirm (by typing 'y') that they accept. If they
try to exit or type anything other than 'y' they will be denied access. I'm
not sure a user can interact with a script being executed by PAM. Also, I
want to differentiate for SCP. It looks like OpenSSH will pass
SSH_ORIGINAL_COMMAND variable to the script so I can use that in the script
logic and not enforce input for SCP and/or SFTP. So it would seem to be
what I want. I found an example on the interwebs with something similar and
I built my script similarly but I can't seem to get any output. I guess I
was looking for help deciphering that DEBUG output.
Post by Lesley Kimmel
Gert,
Thank you for the feedback. Can you give any further direction on where to
get more information on what you are describing?
Post by Lesley Kimmel
Hi,
Post by Lesley Kimmel
I would like to implement an arbitrary script to be executed when
logging
Post by Lesley Kimmel
on via SSH.
I'd just do this in the PAM session handler.
ForceCommand means "run this command *and then exit*", so this is not
what you want.
gert
--
USENET is *not* the non-clickable part of WWW!
//
www.muc.de/~gert/
Gert Doering - Munich, Germany
fax: +49-89-35655025
Scott Neugroschl
2016-02-17 23:06:04 UTC
Permalink
So I probably shouldn't have said "arbitrary" script. What I really want to do
is to present a terms of service notice (/etc/issue). But I also want to get
the user to actually confirm (by typing 'y') that they accept. If they try to
exit or type anything other than 'y' they will be denied access.
For interactive sessions, at least, can't you just do this in /etc/profile?
Darren Tucker
2016-02-18 02:01:14 UTC
Permalink
On Thu, Feb 18, 2016 at 9:47 AM, Lesley Kimmel
[...] I'm not sure a user can interact with a script being executed by PAM.
It depends on what the PAM module running the script does, but probably not.

The PAM stack runs before the user has a tty, so writing to stdout or
stderr is a bad idea (sshd maps these to /dev/null so it won't crash
sshd, but it won't do anything useful either). Theoretically the PAM
module could read stdio and package up the content into PAM_TEXT_INFO
messages sent via the conversation function which sshd could then send
to the user, but I suspect it would be hard for the PAM module to know
whether or not the script was trying to read from stdin and do
something sensible in that case.

You might be able to construct what you want from pam_echo to send the
message and module that solicits a response and checks it (I don't
know of such a module but in theory it wouldn't be hard to write).
--
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69
Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.
Nico Kadel-Garcia
2016-02-18 03:17:29 UTC
Permalink
On Wed, Feb 17, 2016 at 5:47 PM, Lesley Kimmel
Post by Lesley Kimmel
So I probably shouldn't have said "arbitrary" script. What I really want to
do is to present a terms of service notice (/etc/issue). But I also want to
get the user to actually confirm (by typing 'y') that they accept. If they
try to exit or type anything other than 'y' they will be denied access. I'm
not sure a user can interact with a script being executed by PAM. Also, I
want to differentiate for SCP.
I think you're really, really trying to hurt yourself and burning
cycles better spent elsewhere on a non-enforcable service agreement.
Sun tried this with their Java installer, and it was loathed by
*everyone* who's had to cope with it.

If your scriptable operations for handling of specific keys are really
limited, such as only serving rsync, you might take a look at the
"validate-rsync.sh" script published in many places. But I suspect
you're simply going to make your user community hate you, since this
will break rsync over SSH, sftp, WinSCP based access to sftp or scp,
etc. etc. etc. Shoving personal text interactions into a well-defined
and very standard API is not a nice thing to do to your users.

Nico Kadel-Garcia <***@gmail.com>
Dag-Erling Smørgrav
2016-03-04 09:02:04 UTC
Permalink
Post by Lesley Kimmel
So I probably shouldn't have said "arbitrary" script. What I really
want to do is to present a terms of service notice (/etc/issue). But I
also want to get the user to actually confirm (by typing 'y') that
they accept. If they try to exit or type anything other than 'y' they
will be denied access.
It is relatively trivial to write a PAM module to do that.

DES
--
Dag-Erling Smørgrav - ***@des.no
Nico Kadel-Garcia
2016-03-05 00:06:26 UTC
Permalink
Post by Dag-Erling Smørgrav
Post by Lesley Kimmel
So I probably shouldn't have said "arbitrary" script. What I really
want to do is to present a terms of service notice (/etc/issue). But I
also want to get the user to actually confirm (by typing 'y') that
they accept. If they try to exit or type anything other than 'y' they
will be denied access.
It is relatively trivial to write a PAM module to do that.
DES
--
Which will have the relevant configuration overwritten and disabled
the next time you run "authconfig" on Red Hat based sysems. I'm not
sure if this occurs with other systems, but tuning PAM is like tuning
SELinux: it's a lot of extra work with little return-on-investment,
and in this case for a change that will irritate *every single user*
and break a number of API's. I can't recommend this approach.
Dag-Erling Smørgrav
2016-03-05 13:08:43 UTC
Permalink
Post by Nico Kadel-Garcia
Post by Dag-Erling Smørgrav
It is relatively trivial to write a PAM module to do that.
Which will have the relevant configuration overwritten and disabled
the next time you run "authconfig" on Red Hat based sysems. I'm not
sure if this occurs with other systems, but tuning PAM is like tuning
SELinux: it's a lot of extra work with little return-on-investment,
and in this case for a change that will irritate *every single user*
and break a number of API's. I can't recommend this approach.
It won't break any APIs, and have you considered that OP might not have
a choice? That this may be a legal requirement?

DES
--
Dag-Erling Smørgrav - ***@des.no
Nico Kadel-Garcia
2016-03-05 15:07:11 UTC
Permalink
Post by Dag-Erling Smørgrav
Post by Nico Kadel-Garcia
Post by Dag-Erling Smørgrav
It is relatively trivial to write a PAM module to do that.
Which will have the relevant configuration overwritten and disabled
the next time you run "authconfig" on Red Hat based sysems. I'm not
sure if this occurs with other systems, but tuning PAM is like tuning
SELinux: it's a lot of extra work with little return-on-investment,
and in this case for a change that will irritate *every single user*
and break a number of API's. I can't recommend this approach.
It won't break any APIs, and have you considered that OP might not have
a choice? That this may be a legal requirement?
DES
As described, it won't break the SSH API per ses. A careless version
could break rsync over SSH and tools that may rely on automatic
connections via SSH keys or shared authentication models such as
Kerberos. However, it's the API for tools that users run locally that
are most likely to break. Scripts that run remote commands
automatically and use "ssh -n" may break. And gods forbid, because it
would be foolish but I've seen it done, scripts that have the password
input and a full set of scripted command line interactions hardcoded
as part of a remote shell interaction, one prevously recorded with the
"script" command, will need to have an extra option added to handle
this "reply yes" requirement. A particular Perl command I just saw
with quite a complex little MySQL interaction leaps to mind and makes
me shudder in horror.

My concern for API's is basically that of an old XKCD cartoon,
https://xkcd.com/1172/ . It's easy to break people's workflows that
you never even realied existed.

As already pointed out, if necessary, this can be done basically in
/etc/profile (depending on the shells supported). That already
resolves the "don't run this on automated remote SSH scripts" to avoid
breaking non-interactive tools like rsync, and it gets you away from
having to support a binary module that doesn't exist upstream and
which is vulnerable to bog standard upgrade reconfigurations. I've run
into support issues with just such PAM integration, with a senios
sysadmin who wrote his own settings and couldn't be bothered to make
the PAM configuration tool idempotent, so it *kept appending the
required option* every time the configuration tool ran.
Dag-Erling Smørgrav
2016-03-05 15:25:40 UTC
Permalink
Post by Nico Kadel-Garcia
As described, it won't break the SSH API per ses. A careless version
could break rsync over SSH
No more so than asking for a password.

DES
--
Dag-Erling Smørgrav - ***@des.no
Loading...