[Openvpn-devel] Insert client connection data into PAM environment

Message ID 20191001120652.31898-1-wardragon78@gmail.com
State New
Headers show
Series
  • [Openvpn-devel] Insert client connection data into PAM environment
Related show

Commit Message

Paolo Cerrito Oct. 1, 2019, 12:06 p.m.
From: paolo <paolo.cerrito@uniroma2.it>

---
 src/plugins/auth-pam/auth-pam.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

Comments

Antonio Quartulli Oct. 1, 2019, 4:58 p.m. | #1
Hi Paolo,

On 01/10/2019 14:06, Paolo Cerrito wrote:
> From: paolo <paolo.cerrito@uniroma2.it>

On June 27th another patch with the same subject was sent by you to this
mailing list. Is this new patch any different?

If so, it should bear a "v2" in the subject and the differences should
be explicitly mentioned to ease the review.

On top of that I commented your original patch with the following:

> Why do we need this change?
> What benefit does it give us?
> How can it be used?

> IMHO it would be nice to add these pieces of information to the commit
> message (right now it feels .. "empty"  )

But it seems that none of this information has been added to the commit
message (and it is still empty).
Could you please take care of that, so to make the review easier for who
is not deep into those lines of code you have changed?

Thanks a lot.
Regards,
Selva Nair Oct. 1, 2019, 5:25 p.m. | #2
Hi,

Its useful to set PAM_RHOSTS which will allow use of
pam_access for access control etc. So feature ACK.

I would like to see a more precise commit message header like:
"Insert remote IP address into PAM environment"

On Tue, Oct 1, 2019 at 8:25 AM Paolo Cerrito <wardragon78@gmail.com> wrote:

> From: paolo <paolo.cerrito@uniroma2.it>
>
> ---
>  src/plugins/auth-pam/auth-pam.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/src/plugins/auth-pam/auth-pam.c
> b/src/plugins/auth-pam/auth-pam.c
> index 88b53204..9d8dfb95 100644
> --- a/src/plugins/auth-pam/auth-pam.c
> +++ b/src/plugins/auth-pam/auth-pam.c
> @@ -115,6 +115,7 @@ struct user_pass {
>      char password[128];
>      char common_name[128];
>      char response[128];
> +    char remote[128];
>
>      const struct name_value_list *name_value_list;
>  };
> @@ -517,13 +518,15 @@ openvpn_plugin_func_v1(openvpn_plugin_handle_t
> handle, const int type, const cha
>          const char *username = get_env("username", envp);
>          const char *password = get_env("password", envp);
>          const char *common_name = get_env("common_name", envp) ?
> get_env("common_name", envp) : "";
> +        const char *remote = get_env("untrusted_ip", envp) ?
> get_env("untrusted_ip", envp) : get_env("untrusted_ip6", envp);
>

Ensure that remote can't be NULL, like:

if (!remote)
{
    remote = "";
}

Though get_env() is unlikely to return NULL in this case,
safer not to rely on that and risk a NULL dereferencing later.


>          if (username && strlen(username) > 0 && password)
>          {
>              if (send_control(context->foreground_fd, COMMAND_VERIFY) == -1
>                  || send_string(context->foreground_fd, username) == -1
>                  || send_string(context->foreground_fd, password) == -1
> -                || send_string(context->foreground_fd, common_name) == -1)
> +                || send_string(context->foreground_fd, common_name) == -1
> +                || send_string(context->foreground_fd, remote) == -1)
>              {
>                  fprintf(stderr, "AUTH-PAM: Error sending auth info to
> background process\n");
>              }
> @@ -750,8 +753,16 @@ pam_auth(const char *service, const struct user_pass
> *up)
>      status = pam_start(service, name_value_list_provided ? NULL :
> up->username, &conv, &pamh);
>      if (status == PAM_SUCCESS)
>      {
> +        /* Set PAM_RHOST environment variable */
> +        if (*(up->remote))
> +        {
> +            status = pam_set_item(pamh, PAM_RHOST, up->remote);
> +        }
>          /* Call PAM to verify username/password */
> -        status = pam_authenticate(pamh, 0);
> +        if (status == PAM_SUCCESS)
> +        {
> +            status = pam_authenticate(pamh, 0);
> +        }
>          if (status == PAM_SUCCESS)
>          {
>              status = pam_acct_mgmt(pamh, 0);
> @@ -839,7 +850,8 @@ pam_server(int fd, const char *service, int verb,
> const struct name_value_list *
>              case COMMAND_VERIFY:
>                  if (recv_string(fd, up.username, sizeof(up.username)) ==
> -1
>                      || recv_string(fd, up.password, sizeof(up.password))
> == -1
> -                    || recv_string(fd, up.common_name,
> sizeof(up.common_name)) == -1)
> +                    || recv_string(fd, up.common_name,
> sizeof(up.common_name)) == -1
> +                    || recv_string(fd, up.remote, sizeof(up.remote)) ==
> -1)
>                  {
>                      fprintf(stderr, "AUTH-PAM: BACKGROUND: read error on
> command channel: code=%d, exiting\n",
>                              command);
> @@ -853,6 +865,7 @@ pam_server(int fd, const char *service, int verb,
> const struct name_value_list *
>                              up.username, up.password);
>  #else
>                      fprintf(stderr, "AUTH-PAM: BACKGROUND: USER: %s\n",
> up.username);
> +                    fprintf(stderr, "AUTH-PAM: BACKGROUND: REMOTE: %s\n",
> up.remote);
>

Just for the record: we have to replace all these xprintf()'s by
plugin_log/plugin_vlog callbacks but that's beyond the scope here.

 #endif
>                  }
>

Looks good otherwise.

Selva
<div dir="ltr"><div dir="ltr"><div>Hi,</div><div><br></div><div>Its useful to set PAM_<span id="m_-8358678940876167294m_712506079045984063:8dn.1">RHOSTS</span> which will allow use of</div><div><span id="m_-8358678940876167294m_712506079045984063:8dn.2">pam</span>_access for access control etc. So feature <span id="m_-8358678940876167294m_712506079045984063:8dn.3">ACK</span>.<br></div></div><div><br></div><div>I would like to see a more precise commit message header like:</div><div>&quot;Insert remote <span id="m_-8358678940876167294m_712506079045984063:8dn.4">IP</span> address into PAM environment&quot;<br></div><div><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 1, 2019 at 8:25 AM Paolo <span id="m_-8358678940876167294m_712506079045984063:8dn.5">Cerrito</span> &lt;<a href="mailto:wardragon78@gmail.com" target="_blank">wardragon78@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: paolo &lt;<a href="mailto:paolo.cerrito@uniroma2.it" target="_blank">paolo.cerrito@uniroma2.it</a>&gt;<br>
<br>
---<br>
 src/plugins/auth-pam/auth-pam.c | 19 ++++++++++++++++---<br>
 1 file changed, 16 insertions(+), 3 deletions(-)<br>
<br>
diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c<br>
index 88b53204..9d8dfb95 100644<br>
--- a/src/plugins/auth-pam/auth-pam.c<br>
+++ b/src/plugins/auth-pam/auth-pam.c<br>
@@ -115,6 +115,7 @@ struct user_pass {<br>
     char password[128];<br>
     char common_name[128];<br>
     char response[128];<br>
+    char remote[128];<br>
<br>
     const struct name_value_list *name_value_list;<br>
 };<br>
@@ -517,13 +518,15 @@ openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const cha<br>
         const char *username = get_env(&quot;username&quot;, envp);<br>
         const char *password = get_env(&quot;password&quot;, envp);<br>
         const char *common_name = get_env(&quot;common_name&quot;, envp) ? get_env(&quot;common_name&quot;, envp) : &quot;&quot;;<br>
+        const char *remote = get_env(&quot;untrusted_ip&quot;, envp) ? get_env(&quot;untrusted_ip&quot;, envp) : get_env(&quot;untrusted_ip6&quot;, envp);<br></blockquote><br></div><div class="gmail_quote">Ensure that remote can&#39;t be NULL, like:<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">if (!remote) <br></div><div class="gmail_quote">{</div><div class="gmail_quote">    remote = &quot;&quot;;</div><div class="gmail_quote">}</div><div class="gmail_quote"><br></div><div class="gmail_quote">Though get_<span id="m_-8358678940876167294m_712506079045984063:8dn.6">env</span>() is unlikely to return NULL in this case,</div>safer not to rely on that and risk a NULL <span id="m_-8358678940876167294m_712506079045984063:8dn.7">dereferencing</span> later.<div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
         if (username &amp;&amp; strlen(username) &gt; 0 &amp;&amp; password)<br>
         {<br>
             if (send_control(context-&gt;foreground_fd, COMMAND_VERIFY) == -1<br>
                 || send_string(context-&gt;foreground_fd, username) == -1<br>
                 || send_string(context-&gt;foreground_fd, password) == -1<br>
-                || send_string(context-&gt;foreground_fd, common_name) == -1)<br>
+                || send_string(context-&gt;foreground_fd, common_name) == -1<br>
+                || send_string(context-&gt;foreground_fd, remote) == -1)<br>
             {<br>
                 fprintf(stderr, &quot;AUTH-PAM: Error sending auth info to background process\n&quot;);<br>
             }<br>
@@ -750,8 +753,16 @@ pam_auth(const char *service, const struct user_pass *up)<br>
     status = pam_start(service, name_value_list_provided ? NULL : up-&gt;username, &amp;conv, &amp;pamh);<br>
     if (status == PAM_SUCCESS)<br>
     {<br>
+        /* Set PAM_RHOST environment variable */<br>
+        if (*(up-&gt;remote))<br>
+        {<br>
+            status = pam_set_item(pamh, PAM_RHOST, up-&gt;remote);<br>
+        }<br>
         /* Call PAM to verify username/password */<br>
-        status = pam_authenticate(pamh, 0);<br>
+        if (status == PAM_SUCCESS)<br>
+        {<br>
+            status = pam_authenticate(pamh, 0);<br>
+        }<br>
         if (status == PAM_SUCCESS)<br>
         {<br>
             status = pam_acct_mgmt(pamh, 0);<br>
@@ -839,7 +850,8 @@ pam_server(int fd, const char *service, int verb, const struct name_value_list *<br>
             case COMMAND_VERIFY:<br>
                 if (recv_string(fd, up.username, sizeof(up.username)) == -1<br>
                     || recv_string(fd, up.password, sizeof(up.password)) == -1<br>
-                    || recv_string(fd, up.common_name, sizeof(up.common_name)) == -1)<br>
+                    || recv_string(fd, up.common_name, sizeof(up.common_name)) == -1<br>
+                    || recv_string(fd, up.remote, sizeof(up.remote)) == -1)<br>
                 {<br>
                     fprintf(stderr, &quot;AUTH-PAM: BACKGROUND: read error on command channel: code=%d, exiting\n&quot;,<br>
                             command);<br>
@@ -853,6 +865,7 @@ pam_server(int fd, const char *service, int verb, const struct name_value_list *<br>
                             up.username, up.password);<br>
 #else<br>
                     fprintf(stderr, &quot;AUTH-PAM: BACKGROUND: USER: %s\n&quot;, up.username);<br>
+                    fprintf(stderr, &quot;AUTH-PAM: BACKGROUND: REMOTE: %s\n&quot;, up.remote);<br></blockquote><div><br></div><div>Just for the record: we have to replace all these <span id="m_-8358678940876167294m_712506079045984063:8dn.8">xprintf</span>()&#39;s by<br></div><div><span id="m_-8358678940876167294m_712506079045984063:8dn.9">plugin</span>_log/<span id="m_-8358678940876167294m_712506079045984063:8dn.10">plugin</span>_<span id="m_-8358678940876167294m_712506079045984063:8dn.11">vlog</span> callbacks but that&#39;s beyond the scope here.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
 #endif<br>
                 }<br></blockquote><div><br></div><div>Looks good otherwise.</div><div><br></div><div><span id="m_-8358678940876167294m_712506079045984063:8dn.12">Selva</span></div></div></div>
Selva Nair Oct. 1, 2019, 5:47 p.m. | #3
Hi,

On Tue, Oct 1, 2019 at 1:02 PM Antonio Quartulli <a@unstable.cc> wrote:

> Hi Paolo,
>
> On 01/10/2019 14:06, Paolo Cerrito wrote:
> > From: paolo <paolo.cerrito@uniroma2.it>
>
> On June 27th another patch with the same subject was sent by you to this
> mailing list. Is this new patch any different?
>
> If so, it should bear a "v2" in the subject and the differences should
> be explicitly mentioned to ease the review.
>
> On top of that I commented your original patch with the following:
>
> > Why do we need this change?
> > What benefit does it give us?
> > How can it be used?
>
> > IMHO it would be nice to add these pieces of information to the commit
> > message (right now it feels .. "empty"  )
>
> But it seems that none of this information has been added to the commit
> message (and it is still empty).
> Could you please take care of that, so to make the review easier for who
> is not deep into those lines of code you have changed?
>

Aha, I missed the previous thread. Looks like this one is the same
patch as the previous one.

Paolo: please improve on the commit message, address the comments,
and submit a v2 with the message-id of this one in --in-reply-to.

Selva
<div dir="ltr"><div dir="ltr"><br></div><div>Hi,</div><div><br></div><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Oct 1, 2019 at 1:02 PM Antonio Quartulli &lt;a@unstable.cc&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Paolo,<br>
<br>
On 01/10/2019 14:06, Paolo Cerrito wrote:<br>
&gt; From: paolo &lt;<a href="mailto:paolo.cerrito@uniroma2.it" target="_blank">paolo.cerrito@uniroma2.it</a>&gt;<br>
<br>
On June 27th another patch with the same subject was sent by you to this<br>
mailing list. Is this new patch any different?<br>
<br>
If so, it should bear a &quot;v2&quot; in the subject and the differences should<br>
be explicitly mentioned to ease the review.<br>
<br>
On top of that I commented your original patch with the following:<br>
<br>
&gt; Why do we need this change?<br>
&gt; What benefit does it give us?<br>
&gt; How can it be used?<br>
<br>
&gt; IMHO it would be nice to add these pieces of information to the commit<br>
&gt; message (right now it feels .. &quot;empty&quot;  )<br>
<br>
But it seems that none of this information has been added to the commit<br>
message (and it is still empty).<br>
Could you please take care of that, so to make the review easier for who<br>
is not deep into those lines of code you have changed?<br></blockquote><div><br></div><div>Aha, I missed the previous thread. Looks like this one is the same</div><div>patch as the previous one.</div><div><br></div><div>Paolo: please improve on the commit message, address the comments,<br></div><div>and submit a v2 with the message-id of this one in --in-reply-to.</div><div><br></div><div>Selva<br></div></div></div></div>
David Sommerseth Oct. 4, 2019, 6:09 p.m. | #4
Hi Paolo,

Thank you very much for this patch.  Selva has already given this a
feature-ack, which I agree to.  So lets continue here.

First of all, it is really important that the commit message is good on
patches.  Please read this really good blog post on this topic:
<https://chris.beams.io/posts/git-commit/>

And as an example of a reasonably good commit message in OpenVPN is for
example this one:
<https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17870.html>

The keypoints in a commit message are:

 - Subject line
   A straight to the point what this change is about

 - Commit message:
   Explain *why* this change is needed, *what* does change this give us.
   Don't describe how, as that need to be clear in the commit diff below the
   commit message.

   And having the "Signed-off-by: " line in the commit message is also really
   important.

Secondly, when you next time submit a patch, please ensure it has a proper
version identifier if you update a patch you have already sent.

And now ... the review of your patch, please follow in between the diff lines
below.

On 01/10/2019 14:06, Paolo Cerrito wrote:
> From: paolo <paolo.cerrito@uniroma2.it>
> 
> ---
>  src/plugins/auth-pam/auth-pam.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c
> index 88b53204..9d8dfb95 100644
> --- a/src/plugins/auth-pam/auth-pam.c
> +++ b/src/plugins/auth-pam/auth-pam.c
> @@ -115,6 +115,7 @@ struct user_pass {
>      char password[128];
>      char common_name[128];
>      char response[128];
> +    char remote[128];

Why 128 bytes?  Unless I'm mistaken, an IPv6 address can be up to 39
characters and an IPv4 will never be longer than 15 characters.  So having 40
bytes should be reasonable enough, as that give space for a \0 terminator too.

>      const struct name_value_list *name_value_list;
>  };
> @@ -517,13 +518,15 @@ openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const cha
>          const char *username = get_env("username", envp);
>          const char *password = get_env("password", envp);
>          const char *common_name = get_env("common_name", envp) ? get_env("common_name", envp) : "";
> +        const char *remote = get_env("untrusted_ip", envp) ? get_env("untrusted_ip", envp) : get_env("untrusted_ip6", envp);

I know we don't do this in the get_env() lines below, but we should really try
to restrict the number of bytes we extract from the env table.

This isn't functionally important in this code here, but more a generic and
common way.  IPv6 is generally preferred over IPv4 by the OS, so you should
check if untrusted_ip6 is present and then only extract the IPv4 address if
there is no IPv6 address.


>          if (username && strlen(username) > 0 && password)
>          {
>              if (send_control(context->foreground_fd, COMMAND_VERIFY) == -1
>                  || send_string(context->foreground_fd, username) == -1
>                  || send_string(context->foreground_fd, password) == -1
> -                || send_string(context->foreground_fd, common_name) == -1)
> +                || send_string(context->foreground_fd, common_name) == -1
> +                || send_string(context->foreground_fd, remote) == -1)
>              {
>                  fprintf(stderr, "AUTH-PAM: Error sending auth info to background process\n");
>              }
> @@ -750,8 +753,16 @@ pam_auth(const char *service, const struct user_pass *up)
>      status = pam_start(service, name_value_list_provided ? NULL : up->username, &conv, &pamh);
>      if (status == PAM_SUCCESS)
>      {
> +        /* Set PAM_RHOST environment variable */
> +        if (*(up->remote))
> +        {
> +            status = pam_set_item(pamh, PAM_RHOST, up->remote);
> +        }
>          /* Call PAM to verify username/password */
> -        status = pam_authenticate(pamh, 0);
> +        if (status == PAM_SUCCESS)
> +        {
> +            status = pam_authenticate(pamh, 0);
> +        }

I understand the importance of this call.  But can this break anything for
existing configurations already using auth-pam?  I think this check should be
enabled by an option given to the auth-pam module in the 'plugin' OpenVPN
statement.  You will see that argument in the char **argv array pointer found
in struct openvpn_plugin_args_open_in in the openvpn_plugin_open_v3()
function.  I suggest an option as simple as "call-pam-auth" or something like
that.

>          if (status == PAM_SUCCESS)
>          {
>              status = pam_acct_mgmt(pamh, 0);
> @@ -839,7 +850,8 @@ pam_server(int fd, const char *service, int verb, const struct name_value_list *
>              case COMMAND_VERIFY:
>                  if (recv_string(fd, up.username, sizeof(up.username)) == -1
>                      || recv_string(fd, up.password, sizeof(up.password)) == -1
> -                    || recv_string(fd, up.common_name, sizeof(up.common_name)) == -1)
> +                    || recv_string(fd, up.common_name, sizeof(up.common_name)) == -1
> +                    || recv_string(fd, up.remote, sizeof(up.remote)) == -1)
>                  {
>                      fprintf(stderr, "AUTH-PAM: BACKGROUND: read error on command channel: code=%d, exiting\n",
>                              command);
> @@ -853,6 +865,7 @@ pam_server(int fd, const char *service, int verb, const struct name_value_list *
>                              up.username, up.password);
>  #else
>                      fprintf(stderr, "AUTH-PAM: BACKGROUND: USER: %s\n", up.username);
> +                    fprintf(stderr, "AUTH-PAM: BACKGROUND: REMOTE: %s\n", up.remote);

Two things.  I think it would be good to have the up.remote in the same line
as up.username.   But you it should probably be empty ("") if up.remote is
NULL.  And I suggest using the same format as found in other parts of the
OpenVPN logging ... "USERNAME/IP-ADDRESS".   If IP address is not available,
use just "USERNAME".

If you have any questions or comments, feel free to reach out.  And also feel
free to join the #openvpn-devel IRC channel on FreeNode; there are several of
us community and corporate developers there so it is a chance to get quicker
replies there (most of us are in the EU time zones).

Patch

diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c
index 88b53204..9d8dfb95 100644
--- a/src/plugins/auth-pam/auth-pam.c
+++ b/src/plugins/auth-pam/auth-pam.c
@@ -115,6 +115,7 @@  struct user_pass {
     char password[128];
     char common_name[128];
     char response[128];
+    char remote[128];
 
     const struct name_value_list *name_value_list;
 };
@@ -517,13 +518,15 @@  openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const cha
         const char *username = get_env("username", envp);
         const char *password = get_env("password", envp);
         const char *common_name = get_env("common_name", envp) ? get_env("common_name", envp) : "";
+        const char *remote = get_env("untrusted_ip", envp) ? get_env("untrusted_ip", envp) : get_env("untrusted_ip6", envp);
 
         if (username && strlen(username) > 0 && password)
         {
             if (send_control(context->foreground_fd, COMMAND_VERIFY) == -1
                 || send_string(context->foreground_fd, username) == -1
                 || send_string(context->foreground_fd, password) == -1
-                || send_string(context->foreground_fd, common_name) == -1)
+                || send_string(context->foreground_fd, common_name) == -1
+                || send_string(context->foreground_fd, remote) == -1)
             {
                 fprintf(stderr, "AUTH-PAM: Error sending auth info to background process\n");
             }
@@ -750,8 +753,16 @@  pam_auth(const char *service, const struct user_pass *up)
     status = pam_start(service, name_value_list_provided ? NULL : up->username, &conv, &pamh);
     if (status == PAM_SUCCESS)
     {
+        /* Set PAM_RHOST environment variable */
+        if (*(up->remote))
+        {
+            status = pam_set_item(pamh, PAM_RHOST, up->remote);
+        }
         /* Call PAM to verify username/password */
-        status = pam_authenticate(pamh, 0);
+        if (status == PAM_SUCCESS)
+        {
+            status = pam_authenticate(pamh, 0);
+        }
         if (status == PAM_SUCCESS)
         {
             status = pam_acct_mgmt(pamh, 0);
@@ -839,7 +850,8 @@  pam_server(int fd, const char *service, int verb, const struct name_value_list *
             case COMMAND_VERIFY:
                 if (recv_string(fd, up.username, sizeof(up.username)) == -1
                     || recv_string(fd, up.password, sizeof(up.password)) == -1
-                    || recv_string(fd, up.common_name, sizeof(up.common_name)) == -1)
+                    || recv_string(fd, up.common_name, sizeof(up.common_name)) == -1
+                    || recv_string(fd, up.remote, sizeof(up.remote)) == -1)
                 {
                     fprintf(stderr, "AUTH-PAM: BACKGROUND: read error on command channel: code=%d, exiting\n",
                             command);
@@ -853,6 +865,7 @@  pam_server(int fd, const char *service, int verb, const struct name_value_list *
                             up.username, up.password);
 #else
                     fprintf(stderr, "AUTH-PAM: BACKGROUND: USER: %s\n", up.username);
+                    fprintf(stderr, "AUTH-PAM: BACKGROUND: REMOTE: %s\n", up.remote);
 #endif
                 }