EAP problem

classic Classic list List threaded Threaded
10 messages Options
| Threaded
Open this post in threaded view
|

EAP problem

Robert Graham
EAP problem

Hello list,

I have freeradius configured to authenicate users against active directory with ms-chap and can also do ldap group searches, all that is working great.  Now what I need to do is implement 802.1x port authenication on our foundry switches and I'm running into problems. This is our layout:


W2K Pro (using MD5-Challenge) -----> Foundry Switch -------> Freeradius --------> AD

I have read a lot of articles/post on the web and looked over the docs (I don't know how many times)  and I think I'm more confused than ever.  So the first question is:

Is this setup even possible?

I did get EAP to work when I supply the User-Password attribute in the users file, but I would like LDAP to fetch this if it is possible.  I came across a post suggesting this, but the answer was not very clear.  If I remove the User-Password attribute in the users file, the dubug out shows:  User-Password is required for EAP-MD5 authenitication.

Another question I would like to ask is:  When you configure the workstation (supplicant) for MD5-Challenge, it prompts you for:

Username
Password
Domain

If you supply all three values, the debug shows:

Identity does not match user-name

But if you leave the domain field blank, it works (providing that User-Password attribute is in the user file).

I hope these questions make sense and hopefully someone out there can help.

-Robert Graham



-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Alan DeKok
"Graham, Robert" <[hidden email]> wrote:
> Is this setup even possible?

  Do you mean EAP-MD5?  I'm not sure what MD5-Challenge is...

> I did get EAP to work when I supply the User-Password attribute in the
> users file, but I would like LDAP to fetch this if it is possible.

  If you're using LDAP, it should be doing that already.

> If I remove the User-Password attribute in the users file, the dubug out
> shows:  User-Password is required for EAP-MD5 authenitication.

  Are you getting the User-Password attribute from LDAP?  The debug
log should show this.

> Username
> Password
> Domain
>
> If you supply all three values, the debug shows:
>
> Identity does not match user-name

  You're re-writing the User-Name attribute somewhere.  Again, the
debug log will show this.

  Please read the debug log, or post it to the list.

  Alan DeKok.

-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Robert Graham
In reply to this post by Robert Graham
Re: EAP problem

I am still having an issue autheniticating a user with EAP.  I think Alan, has pointed out the issue in his previous reply, about LDAP not retrieving the User-Password from Active Directory.  My understanding (as little as it may be) of the ldap section of the radiusd.conf file is the password_attribute is responsible for retrieving the password.  Below is the ldap config section of radiusd.conf.

ldap {
                server = "mem-dc.mem-ins.com"
                basedn = "ou=mem users,dc=mem-ins,dc=com"
                    filter = "(sAMAccountName=%{Stripped-User-Name:-%{User-Name}})"
                identity = "cn=administrator,ou=admin,ou=mem users,dc=mem-ins,dc=com"
                password = {Secret}
                start_tls = no
                dictionary_mapping = ${raddbdir}/ldap.attrmap
                ldap_connections_number = 5
                password_attribute = userPassword
                groupname_attribute = cn
                groupmembership_filter = "(|(&(objectClass=GroupOfNames)(memberof=%{Ldap-UserDn}))(&(objectClass=Group)(member=%{Ldap-UserDn})))"

                groupmembership_attribute = radiusGroupName
                timeout = 4
                timelimit = 3
                net_timeout = 1
                access_attr_used_for_allow = yes
        }

but the output shows:


rad_recv: Access-Request packet from host 172.16.5.71:1645, id=144, length=85
        User-Name = "rgraham"
        Service-Type = Framed-User
        Framed-MTU = 1500
        NAS-IP-Address = 172.16.5.71
        NAS-Port = 24
        EAP-Message = 0x0200000c017267726168616d
        Message-Authenticator = 0xc96d75a58b5af7b632fc0f3cc91876c8
rad_lowerpair:  User-Name now 'rgraham'
  Processing the authorize section of radiusd.conf
modcall: entering group authorize for request 0
  modcall[authorize]: module "preprocess" returns ok for request 0
radius_xlat:  '/var/log/radius/radacct/172.16.5.71/auth-detail-20050630'
rlm_detail: /var/log/radius/radacct/%{Client-IP-Address}/auth-detail-%Y%m%d expands to /var/log/radius/radacct/172.16.5.71/auth-detail-20050630

  modcall[authorize]: module "auth_log" returns ok for request 0
  modcall[authorize]: module "attr_filter" returns noop for request 0
rlm_ldap: - authorize
rlm_ldap: performing user authorization for rgraham
radius_xlat:  '(sAMAccountName=rgraham)'
radius_xlat:  'ou=mem users,dc=mem-ins,dc=com'
rlm_ldap: ldap_get_conn: Checking Id: 0
rlm_ldap: ldap_get_conn: Got Id: 0
rlm_ldap: attempting LDAP reconnection
rlm_ldap: (re)connect to mem-dc.mem-ins.com:389, authentication 0
rlm_ldap: bind as cn=administrator,ou=admin,ou=mem users,dc=mem-ins,dc=com/{secret} to mem-dc.mem-ins.com:389
rlm_ldap: waiting for bind result ...
rlm_ldap: Bind was successful
rlm_ldap: performing search in ou=mem users,dc=mem-ins,dc=com, with filter (sAMAccountName=rgraham)
rlm_ldap: looking for check items in directory...
rlm_ldap: looking for reply items in directory...
rlm_ldap: user rgraham authorized to use remote access
rlm_ldap: ldap_release_conn: Release Id: 0
  modcall[authorize]: module "ldap" returns ok for request 0
  modcall[authorize]: module "chap" returns noop for request 0
  modcall[authorize]: module "mschap" returns noop for request 0
    rlm_realm: No '@' in User-Name = "rgraham", looking up realm NULL
    rlm_realm: No such realm "NULL"
  modcall[authorize]: module "suffix" returns noop for request 0
  rlm_eap: EAP packet type response id 0 length 12
  rlm_eap: No EAP Start, assuming it's an on-going EAP conversation
  modcall[authorize]: module "eap" returns updated for request 0
rlm_ldap: Entering ldap_groupcmp()
radius_xlat:  'ou=mem users,dc=mem-ins,dc=com'
radius_xlat:  '(|(&(objectClass=GroupOfNames)(memberof=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com))(&(objectClass=Group)(member=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com)))'

rlm_ldap: ldap_get_conn: Checking Id: 0
rlm_ldap: ldap_get_conn: Got Id: 0
rlm_ldap: performing search in cn=domain users,ou=groups,ou=mem users,dc=mem-ins,dc=com, with filter (|(&(objectClass=GroupOfNames)(memberof=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com))(&(objectClass=Group)(member=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com)))

rlm_ldap::ldap_groupcmp: User found in group cn=domain users,ou=groups,ou=mem users,dc=mem-ins,dc=com
rlm_ldap: ldap_release_conn: Release Id: 0
    users: Matched DEFAULT at 189
  modcall[authorize]: module "files" returns ok for request 0
modcall: group authorize returns updated for request 0
  rad_check_password:  Found Auth-Type EAP
auth: type "EAP"
  Processing the authenticate section of radiusd.conf
modcall: entering group authenticate for request 0
  rlm_eap: EAP Identity
  rlm_eap: processing type md5
rlm_eap_md5: Issuing Challenge
  modcall[authenticate]: module "eap" returns handled for request 0
modcall: group authenticate returns handled for request 0
Sending Access-Challenge of id 144 to 172.16.5.71:1645
        Service-Type = Framed-User
        Framed-Protocol = PPP
        EAP-Message = 0x0101001604102a7c39455a6ffe060c3a06f4b9677974
        Message-Authenticator = 0x00000000000000000000000000000000
        State = 0xcb7b91555ab2be2ca5f6ebc82b06f0ec
Finished request 0
Going to the next request
--- Walking the entire request list ---
Waking up in 6 seconds...
rad_recv: Access-Request packet from host 172.16.5.71:1645, id=145, length=120
        User-Name = "rgraham"
        Service-Type = Framed-User
        Framed-MTU = 1500
        NAS-IP-Address = 172.16.5.71
        NAS-Port = 24
        State = 0xcb7b91555ab2be2ca5f6ebc82b06f0ec
        EAP-Message = 0x0201001d0410db525b9aa0119fbbda00f3b61861beaf7267726168616d
        Message-Authenticator = 0x0751751a6adfd81ae56487289f42da9e
rad_lowerpair:  User-Name now 'rgraham'
  Processing the authorize section of radiusd.conf
modcall: entering group authorize for request 1
  modcall[authorize]: module "preprocess" returns ok for request 1
radius_xlat:  '/var/log/radius/radacct/172.16.5.71/auth-detail-20050630'
rlm_detail: /var/log/radius/radacct/%{Client-IP-Address}/auth-detail-%Y%m%d expands to /var/log/radius/radacct/172.16.5.71/auth-detail-20050630

  modcall[authorize]: module "auth_log" returns ok for request 1
  modcall[authorize]: module "attr_filter" returns noop for request 1
rlm_ldap: - authorize
rlm_ldap: performing user authorization for rgraham
radius_xlat:  '(sAMAccountName=rgraham)'
radius_xlat:  'ou=mem users,dc=mem-ins,dc=com'
rlm_ldap: ldap_get_conn: Checking Id: 0
rlm_ldap: ldap_get_conn: Got Id: 0
rlm_ldap: performing search in ou=mem users,dc=mem-ins,dc=com, with filter (sAMAccountName=rgraham)
rlm_ldap: looking for check items in directory...
rlm_ldap: looking for reply items in directory...
rlm_ldap: user rgraham authorized to use remote access
rlm_ldap: ldap_release_conn: Release Id: 0
  modcall[authorize]: module "ldap" returns ok for request 1
  modcall[authorize]: module "chap" returns noop for request 1
  modcall[authorize]: module "mschap" returns noop for request 1
    rlm_realm: No '@' in User-Name = "rgraham", looking up realm NULL
    rlm_realm: No such realm "NULL"
  modcall[authorize]: module "suffix" returns noop for request 1
  rlm_eap: EAP packet type response id 1 length 29
  rlm_eap: No EAP Start, assuming it's an on-going EAP conversation
  modcall[authorize]: module "eap" returns updated for request 1
rlm_ldap: Entering ldap_groupcmp()
radius_xlat:  'ou=mem users,dc=mem-ins,dc=com'
radius_xlat:  '(|(&(objectClass=GroupOfNames)(memberof=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com))(&(objectClass=Group)(member=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com)))'

rlm_ldap: ldap_get_conn: Checking Id: 0
rlm_ldap: ldap_get_conn: Got Id: 0
rlm_ldap: performing search in cn=domain users,ou=groups,ou=mem users,dc=mem-ins,dc=com, with filter (|(&(objectClass=GroupOfNames)(memberof=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com))(&(objectClass=Group)(member=CN=Rgraham,OU=Columbia,OU=MEM Users,DC=mem-ins,DC=com)))

rlm_ldap::ldap_groupcmp: User found in group cn=domain users,ou=groups,ou=mem users,dc=mem-ins,dc=com
rlm_ldap: ldap_release_conn: Release Id: 0
    users: Matched DEFAULT at 189
  modcall[authorize]: module "files" returns ok for request 1
modcall: group authorize returns updated for request 1
  rad_check_password:  Found Auth-Type EAP
auth: type "EAP"
  Processing the authenticate section of radiusd.conf
modcall: entering group authenticate for request 1
  rlm_eap: Request found, released from the list
  rlm_eap: EAP/md5
  rlm_eap: processing type md5
rlm_eap_md5: User-Password is required for EAP-MD5 authentication
 rlm_eap: Handler failed in EAP/md5
  rlm_eap: Failed in EAP select
  modcall[authenticate]: module "eap" returns invalid for request 1
modcall: group authenticate returns invalid for request 1
auth: Failed to validate the user.


shouldn't the section:

rlm_ldap: looking for check items in directory...
rlm_ldap: looking for reply items in directory...
rlm_ldap: user rgraham authorized to use remote access

have something that reflects userpassword retrieved (rlm_ldap: UserPassword retrieved, or sometjing like that)?

Thanks
Robert Graham




-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Alan DeKok
"Graham, Robert" <[hidden email]> wrote:
> shouldn't the section:
>
> rlm_ldap: looking for check items in directory...
> rlm_ldap: looking for reply items in directory...
> rlm_ldap: user rgraham authorized to use remote access
>
> have something that reflects userpassword retrieved (rlm_ldap:
> UserPassword retrieved, or sometjing like that)?

  Yes.

  Alan DeKok.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Robert Graham
In reply to this post by Robert Graham
Re: EAP problem

I'm I correct to state that the "password_attribute = userPassword" in the ldap section causes ldap to retrieve the user's password out Active Directory? and if so, what I am doing wrong.  The only thing that I can thing of is the mapping in the ldap.attrmap file which I have below:

checkItem       $GENERIC$                       radiusCheckItem
replyItem       $GENERIC$                       radiusReplyItem

checkItem       Auth-Type                       radiusAuthType
checkItem       Simultaneous-Use                radiusSimultaneousUse
checkItem       Called-Station-Id               radiusCalledStationId
checkItem       Calling-Station-Id              radiusCallingStationId
checkItem       LM-Password                     sambaLMPassword
checkItem       NT-Password                     sambaNTPassword
checkItem       SMB-Account-CTRL-TEXT           sambaAcctFlags
checkItem       Expiration                      radiusExpiration

replyItem       Service-Type                    radiusServiceType
replyItem       Framed-Protocol                 radiusFramedProtocol
replyItem       Framed-IP-Address               radiusFramedIPAddress
replyItem       Framed-IP-Netmask               radiusFramedIPNetmask
replyItem       Framed-Route                    radiusFramedRoute
replyItem       Framed-Routing                  radiusFramedRouting
replyItem       Filter-Id                       radiusFilterId
replyItem       Framed-MTU                      radiusFramedMTU
replyItem       Framed-Compression              radiusFramedCompression
replyItem       Login-IP-Host                   radiusLoginIPHost
replyItem       Login-Service                   radiusLoginService
replyItem       Login-TCP-Port                  radiusLoginTCPPort
replyItem       Callback-Number                 radiusCallbackNumber
replyItem       Callback-Id                     radiusCallbackId
replyItem       Framed-IPX-Network              radiusFramedIPXNetwork
replyItem       Class                           radiusClass
replyItem       Session-Timeout                 radiusSessionTimeout
replyItem       Idle-Timeout                    radiusIdleTimeout
replyItem       Termination-Action              radiusTerminationAction
replyItem       Login-LAT-Service               radiusLoginLATService
replyItem       Login-LAT-Node                  radiusLoginLATNode

Or I'm I completely off base?

-Robert


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Alan DeKok
"Graham, Robert" <[hidden email]> wrote:
> I'm I correct to state that the "password_attribute =3D userPassword" in
> the ldap section causes ldap to retrieve the user's password out Active
> Directory?

  No.  Messages in the past few days have said you can't get passwords
from AD.  It's impossible.

  You have to use ntlm_auth.  See radiusd.conf

  Alan DeKok.

-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Robert Graham
In reply to this post by Robert Graham
Re: EAP problem

> No.  Messages in the past few days have said you can't get passwords
>from AD.  It's impossible.

>  You have to use ntlm_auth.  See radiusd.conf

>  Alan DeKok.

This still doesn't make any since.  I have ntlm_auth enable, and it is working fine autheniticating our vpn users using ms-chap.


-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Michael Brown-6
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

You _cannot_ read the unicodePwd attribute (where the actual passwd
lies) from AD.  It can only be written to, and then only under certain
conditions (SSL/TLS connection, and if not written by an admin, then a
delete/add must be performed in the same operation).

This is why you should use ntlm_auth w/PEAP for AD auth.  You could be
able to auth against LDAP (PAP) in a TTLS situation (not tried that yet,
so I don't know how it would work), but you will never retrieve the
unicodePwd attribute.

Hope this helps.

Graham, Robert wrote:

>> No.  Messages in the past few days have said you can't get passwords
>>from AD.  It's impossible.
>
>>  You have to use ntlm_auth.  See radiusd.conf
>
>>  Alan DeKok.
>
> This still doesn't make any since.  I have ntlm_auth enable, and it is
> working fine autheniticating our vpn users using ms-chap.
>
>
> ------------------------------------------------------------------------
>
> -
> List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCxJoekeDzZCV99qsRAnQAAJ4rmfLNi26taKRiUAByJcXCFXPfYwCfbgn9
joaGdjaT02sbjRGDr0nT18E=
=p1sh
-----END PGP SIGNATURE-----
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Robert Graham
In reply to this post by Robert Graham
Re: EAP problem

>You _cannot_ read the unicodePwd attribute (where the actual passwd
>lies) from AD.  It can only be written to, and then only under certain
>conditions (SSL/TLS connection, and if not written by an admin, then a
>delete/add must be performed in the same operation).

>This is why you should use ntlm_auth w/PEAP for AD auth.  You could be
>able to auth against LDAP (PAP) in a TTLS situation (not tried that yet,
>so I don't know how it would work), but you will never retrieve the
>unicodePwd attribute.

>Hope this helps.


OK.  Back to the drawing board...  I looked at my options regarding the authenitication method on the W2K client and noticed that I can also used Protected EAP (PEAP).  So I switched the client to this.  When I tried the authenitication again, this time I get:

rlm_eap: Identity does not match User-Name, setting from EAP Identity

I did more searches on this error, and tried several suggestions, from using the hints file:

DEFAULT Prefix == "MEM\\", Strip-User-Name = Yes
        Hint = "MEM",
        Service-Type = Framed-User,
        Framed-Protocol = PPP


I also ensured that use_with_nt_hack was set to "no" in the preprocessor section.  I modified the proxy.conf file for the local domain:

realm  MEM {
       type            = radius
       authhost        = LOCAL
       accthost        = LOCAL
}

and no matter what I do I still get this error... 


There was a post on the mailing list that mentioned that some patches were applied to freeradius in Nov 2004,  I took a look at the freeradius version I was using on my Fedora Core 3 box and it shows:

radiusd: FreeRADIUS Version 1.0.1, for host , built on Oct  6 2004 at 05:25:02
Copyright (C) 2000-2003 The FreeRADIUS server project.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
You may redistribute copies of FreeRADIUS under the terms of the
GNU General Public License.
For more information about these matters, see the file named COPYRIGHT.

I wonder if this is now my problem.....



I have attached the debug output:


rad_recv: Access-Request packet from host 172.16.5.71:1645, id=235, length=93
        User-Name = "MEM\\RGraham"
        Service-Type = Framed-User
        Framed-MTU = 1500
        NAS-IP-Address = 172.16.5.71
        NAS-Port = 24
        EAP-Message = 0x02000010014d454d5c5247726168616d
        Message-Authenticator = 0xeeeaea4ed86a064f533da57687432cb4
rad_lowerpair:  User-Name now 'mem\rgraham'
  Processing the authorize section of radiusd.conf
modcall: entering group authorize for request 0
  hints: Matched DEFAULT at 41
  modcall[authorize]: module "preprocess" returns ok for request 0
radius_xlat:  '/var/log/radius/radacct/172.16.5.71/auth-detail-20050630'
rlm_detail: /var/log/radius/radacct/%{Client-IP-Address}/auth-detail-%Y%m%d expands to /var/log/radius/radacct/172.16.5.71/auth-detail-20050630

  modcall[authorize]: module "auth_log" returns ok for request 0
  modcall[authorize]: module "attr_filter" returns noop for request 0
  modcall[authorize]: module "chap" returns noop for request 0
  modcall[authorize]: module "mschap" returns noop for request 0
    rlm_realm: No '@' in User-Name = "rgraham", looking up realm NULL
    rlm_realm: No such realm "NULL"
  modcall[authorize]: module "suffix" returns noop for request 0
  rlm_eap: EAP packet type response id 0 length 16
  rlm_eap: No EAP Start, assuming it's an on-going EAP conversation
  modcall[authorize]: module "eap" returns updated for request 0
  modcall[authorize]: module "files" returns notfound for request 0
rlm_ldap: - authorize
rlm_ldap: performing user authorization for rgraham
radius_xlat:  '(sAMAccountName=rgraham)'
radius_xlat:  'ou=mem users,dc=mem-ins,dc=com'
rlm_ldap: ldap_get_conn: Checking Id: 0
rlm_ldap: ldap_get_conn: Got Id: 0
rlm_ldap: attempting LDAP reconnection
rlm_ldap: (re)connect to mem-dc.mem-ins.com:389, authentication 0
rlm_ldap: bind as cn=administrator,ou=admin,ou=mem users,dc=mem-ins,dc=com/{secret} to mem-dc.mem-ins.com:389
rlm_ldap: waiting for bind result ...
rlm_ldap: Bind was successful
rlm_ldap: performing search in ou=mem users,dc=mem-ins,dc=com, with filter (sAMAccountName=rgraham)
rlm_ldap: looking for check items in directory...
rlm_ldap: looking for reply items in directory...
rlm_ldap: user rgraham authorized to use remote access
rlm_ldap: ldap_release_conn: Release Id: 0
  modcall[authorize]: module "ldap" returns ok for request 0
modcall: group authorize returns updated for request 0
  rad_check_password:  Found Auth-Type EAP
auth: type "EAP"
  Processing the authenticate section of radiusd.conf
modcall: entering group authenticate for request 0
rlm_eap: Identity does not match User-Name, setting from EAP Identity.
  rlm_eap: Failed in handler
  modcall[authenticate]: module "eap" returns invalid for request 0
modcall: group authenticate returns invalid for request 0
auth: Failed to validate the user.
Delaying request 0 for 1 seconds
Finished request 0




-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
| Threaded
Open this post in threaded view
|

Re: EAP problem

Alan DeKok
"Graham, Robert" <[hidden email]> wrote:
> rlm_eap: Identity does not match User-Name, setting from EAP Identity
>
> I did more searches on this error, and tried several suggestions, from
> using the hints file:
>
> DEFAULT Prefix == "MEM\\", Strip-User-Name = Yes

  That would cause the problem.

  The default configuration of the server DOES NOT have rlm_eap
produce that message.  You've added something to create the problem.

  Start off with the default configuration of the server, and test it.
Make changes, test them, and repeat, until you have the configuration
you want.

> I have attached the debug output:
..
> rad_lowerpair:  User-Name now 'mem\rgraham'

  Why have you configured that?  It's causing the problem.

  The debug output is telling you that the User-Name doesn't match
something else, and it's ALSO telling you that you've configured it to
change the User-Name,

  So.... don't change the User-Name.

  Alan DeKok.
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html