threerings / openvpn-auth-ldap

Implements username/password authentication via LDAP for OpenVPN 2.x.
Other
135 stars 62 forks source link

Support for OpenVPN Challenge/Response protocol #63

Closed guywyers closed 5 years ago

guywyers commented 6 years ago

As discussed in ticket #62, this patch adds support for the OpenVPN Challenge/Response protocol.

The implementation consists of adding an additional field to the config, PasswordIsCR (in the Auth section of the file):

   # Uncomment and set to true to support OpenVPN Challenge/Response
   #PasswordIsCR    false

If this flag is present and set to true the plugin will expect the password to be in the special Challenge/Response format and will parse and extract the password from there.

The typical usage scenario would be to use the openvpn-auth-ldap and openvpn-otp plug-ins together and be able to offer LDAP authentication enriched with an extra layer of security of one time passwords.

Guy Wyers

guywyers commented 6 years ago

Thanks for catching this. Checked in a fix: https://github.com/threerings/openvpn-auth-ldap/pull/63/commits/f06effecc42b26cb9432edb218453882e9d242bf

On Tue, Nov 28, 2017 at 2:42 AM, Kenneth notifications@github.com wrote:

@kenske commented on this pull request.

In src/TRAuthLDAPConfig.m https://github.com/threerings/openvpn-auth-ldap/pull/63#discussion_r153374633 :

@@ -78,6 +78,9 @@ LF_GROUP_MEMBER_ATTRIBUTE, / Group Membership Attribute / LF_GROUP_MEMBER_RFC2307BIS, / Look for full DN for user in attribute /

  • / OpenVPN Challenge/Response /
  • LF_AUTH_PASSOWRD_CR, / Password is in challenge/repsonse format /

Typo

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/threerings/openvpn-auth-ldap/pull/63#pullrequestreview-79369705, or mute the thread https://github.com/notifications/unsubscribe-auth/AK7Q25DIwzPK1tUg6X2OJGHhle-E81Umks5s62TpgaJpZM4QLCOP .

copumpkin commented 6 years ago

I'd love to see this get merged @raygreenwell @samskivert @Thaliant @zellski (just highlighting people in threerings organization, not really sure how governance works here)

samskivert commented 5 years ago

We haven't used this code at Three Rings in a very long time, and indeed Three Rings is no longer even in existence any longer. Landon, the original author, has been off doing his own thing for many years and doesn't (AFAIK) seem interested in maintaining the code. The rest of us don't really know enough about it to maintain it even out of the goodness of our hearts.

I've merged or made some trivial changes over the years, but it would be really great if someone else would step up to maintain the code. I'd be happy to transfer the repo to viable volunteers, or grant them commit access here, whatever they prefer.

In the meanwhile, I can merge this PR, but just beware that I'm doing this with effectively zero oversight.

k0ste commented 5 years ago

Resolve #62

k0ste commented 5 years ago

Resolve #64

urisso commented 4 years ago

Hello everyone, I am having a problem when I try to use the AUTH LDAP + OTP plugins both at the same time, I am getting the following error stating that the password field is being sent empty:

ldap_bind with zero-length password is forbidden.

Some information from my system:

Note: While I am only using AUTH LDAP I have no problem authenticating my username and password, only when using in conjunction with the OTP plugin.

Server Configuration:

cat /usr/local/etc/openvpn/openvpn.conf | grep -vE '#|^$'

local 10.0.2.51 port 1194 mode server proto udp dev tap ca /usr/local/etc/openvpn/keys/ca.crt cert /usr/local/etc/openvpn/keys/server.crt key /usr/local/etc/openvpn/keys/server.key dh /usr/local/etc/openvpn/keys/dh1024.pem tls-server tls-auth /usr/local/etc/openvpn/tls-auth.key 0 key-direction 0 topology net30 duplicate-cn --management 127.0.0.1 7505 tls-version-min 1.2 tls-cipher TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 server 10.0.0.0 255.255.252.0 keepalive 3 8 status /var/log/openvpn-status.log 5 log /var/log/openvpn.log client-config-dir /usr/local/etc/openvpn/ccd ifconfig-pool-persist /usr/local/etc/openvpn/ipp.txt 0 comp-lzo yes script-security 2 client-connect /usr/local/etc/openvpn/scripts/openvpn_server_client_connect.sh client-disconnect /usr/local/etc/openvpn/scripts/openvpn_server_client_disconect.sh ping-timer-rem persist-key persist-tun mute 20 verb 4 username-as-common-name tmp-dir /usr/local/seczone/tmp/openvpn plugin /usr/local/lib/openvpn-auth-ldap.so /usr/local/etc/openvpn/auth-ldap.conf plugin /usr/local/lib/openvpn/plugins/openvpn-otp.so "debug=1 password_is_cr=1 otp_secrets=/usr/local/etc/openvpn/otp-secrets"

cat /usr/local/etc/openvpn/auth-ldap.conf | grep -vE '#|^$'

\<LDAP> URL ldap://ldap.mycompany.local:389,ldap://ldap2.mycompany.local:389 Timeout 15 TLSEnable no FollowReferrals yes TLSCACertFile /usr/local/etc/ssl/ca.pem TLSCACertDir /etc/ssl/certs TLSCertFile /usr/local/etc/ssl/client-cert.pem TLSKeyFile /usr/local/etc/ssl/client-key.pem \</LDAP> \<Authorization> BaseDN "cn=users,dc=MyCompany" SearchFilter "(&(uid=%u))" RequireGroup false PasswordIsCR true \<Group> BaseDN "cn=group,dc=MyCompany" SearchFilter "(&(uid=%u))" MemberAttribute MemberUid \</Group> \</Authorization>

cat /usr/local/etc/openvpn/otp-secrets | grep -vE '#|^$'

MyUserName test totp:sha1:base32:JBSWY3DPEHPK3PXP::xxx *

Client Configuration:

cat /usr/local/etc/openvpn/openvpn_client.conf | grep -vE '#|^$'

client remote 10.0.2.51 port 1194 dev tap nobind proto udp comp-lzo yes auth-nocache ca /usr/local/etc/openvpn/keys/client_ca.crt cert /usr/local/etc/openvpn/keys/client_cert.crt key /usr/local/etc/openvpn/keys/client_key.key group nobody verb 7 auth-user-pass /usr/local/etc/openvpn/account_client.txt tls-client tls-auth /usr/local/etc/openvpn/client_tls-auth.key 1 key-direction 1 status /var/log/openvpn-status_client.log 5 log /var/log/openvpn_client.log keepalive 1 5 ping-timer-rem persist-key persist-tun mute 20 static-challenge "Enter Google Authenticator Token: " 1

cat /usr/local/etc/openvpn/account_cliente.txt

MyUserName 123456654321

Below the server logs with failed user authentication:

Wed Nov 6 18:24:46 2019 us=980306 MULTI: multi_create_instance called Wed Nov 6 18:24:46 2019 us=980458 10.0.2.51:52614 Re-using SSL/TLS context Wed Nov 6 18:24:46 2019 us=980538 10.0.2.51:52614 LZO compression initializing Wed Nov 6 18:24:46 2019 us=980836 10.0.2.51:52614 Control Channel MTU parms [ L:1654 D:1184 EF:66 EB:0 ET:0 EL:3 ] Wed Nov 6 18:24:46 2019 us=980908 10.0.2.51:52614 Data Channel MTU parms [ L:1654 D:1450 EF:122 EB:411 ET:32 EL:3 ] Wed Nov 6 18:24:46 2019 us=981103 10.0.2.51:52614 Local Options String (VER=V4): 'V4,dev-type tap,link-mtu 1574,tun-mtu 1532,proto UDPv4,comp-lzo,keydir 0,cipher BF-CBC,auth SHA1,keysize 128,tls-auth,key-method 2,tls-server' Wed Nov 6 18:24:46 2019 us=981172 10.0.2.51:52614 Expected Remote Options String (VER=V4): 'V4,dev-type tap,link-mtu 1574,tun-mtu 1532,proto UDPv4,comp-lzo,keydir 1,cipher BF-CBC,auth SHA1,keysize 128,tls-auth,key-method 2,tls-client' Wed Nov 6 18:24:46 2019 us=981287 10.0.2.51:52614 TLS: Initial packet from [AF_INET]10.0.2.51:52614, sid=78917175 be9ce7ab Wed Nov 6 18:24:46 2019 us=991875 10.0.2.51:52614 VERIFY OK: depth=1, C=US, ST=FL, L=Miami, O=MyCompany Inc., OU=SecZone, CN=MyCompany Inc. CA, emailAddress=dev@mycompany.com Wed Nov 6 18:24:46 2019 us=992257 10.0.2.51:52614 VERIFY OK: depth=0, C=US, ST=FL, L=Miami, O=MyCompany Inc., OU=SecZone, CN=dev, emailAddress=dev@mycompany.com Wed Nov 6 18:24:46 2019 us=994224 10.0.2.51:52614 peer info: IV_VER=2.4.7 Wed Nov 6 18:24:46 2019 us=994335 10.0.2.51:52614 peer info: IV_PLAT=freebsd Wed Nov 6 18:24:46 2019 us=994401 10.0.2.51:52614 peer info: IV_PROTO=2 Wed Nov 6 18:24:46 2019 us=994494 10.0.2.51:52614 peer info: IV_NCP=2 Wed Nov 6 18:24:46 2019 us=994747 10.0.2.51:52614 peer info: IV_LZ4=1 Wed Nov 6 18:24:46 2019 us=994932 10.0.2.51:52614 peer info: IV_LZ4v2=1 Wed Nov 6 18:24:46 2019 us=995001 10.0.2.51:52614 peer info: IV_LZO=1 Wed Nov 6 18:24:46 2019 us=995062 10.0.2.51:52614 peer info: IV_COMP_STUB=1 Wed Nov 6 18:24:46 2019 us=995120 10.0.2.51:52614 peer info: IV_COMP_STUBv2=1 Wed Nov 6 18:24:46 2019 us=995457 10.0.2.51:52614 peer info: IV_TCPNL=1 ldap_bind with zero-length password is forbidden. Incorrect password supplied for LDAP DN "uid=MyUserName,cn=users,dc=MyCompany". Wed Nov 6 18:24:47 2019 us=14898 10.0.2.51:52614 PLUGIN_CALL: POST /usr/local/lib/openvpn-auth-ldap.so/PLUGIN_AUTH_USER_PASS_VERIFY status=1 Wed Nov 6 18:24:47 2019 us=14995 10.0.2.51:52614 PLUGIN_CALL: plugin function PLUGIN_AUTH_USER_PASS_VERIFY failed with status 1: /usr/local/lib/openvpn-auth-ldap.so OTP-AUTH: trying to authenticate username 'MyUserName' zero-length password is forbidden. in '/usr/local/etc/openvpn/otp-secrets' correct password supplied for LDAP DN "uid=MyUserName,cn=users,dc=MyCompany". dmin', server_secret='869120' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='148221', server_username='MyUserName', server_secret='269466' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='148221', server_username='MyUserName', server_secret='767889' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='148221', server_username='MyUserName', server_secret='308787' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='148221', server_username='MyUserName', server_secret='653005' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='148221', server_username='MyUserName', server_secret='487270' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='148221', server_username='MyUserName', server_secret='148221' OTP-AUTH: auth ok for method='totp', client_username='MyUserName', client_secret='148221' OTP-AUTH: authentication succeeded for username 'MyUserName', remote 10.0.2.51:52614 Wed Nov 6 18:24:47 2019 us=17117 10.0.2.51:52614 PLUGIN_CALL: POST /usr/local/lib/openvpn/plugins/openvpn-otp.so/PLUGIN_AUTH_USER_PASS_VERIFY status=0 Wed Nov 6 18:24:47 2019 us=17466 10.0.2.51:52614 TLS Auth Error: Auth Username/Password verification failed for peer Wed Nov 6 18:24:47 2019 us=19138 10.0.2.51:52614 Control Channel: TLSv1.2, cipher TLSv1/SSLv3 ECDHE-RSA-AES128-GCM-SHA256, 1024 bit RSA Wed Nov 6 18:24:47 2019 us=19243 10.0.2.51:52614 [dev] Peer Connection Initiated with [AF_INET]10.0.2.51:52614 Wed Nov 6 18:24:48 2019 us=214252 10.0.2.51:52614 PUSH: Received control message: 'PUSH_REQUEST' Wed Nov 6 18:24:48 2019 us=214388 10.0.2.51:52614 Delayed exit in 5 seconds Wed Nov 6 18:24:48 2019 us=214463 10.0.2.51:52614 SENT CONTROL [dev]: 'AUTH_FAILED' (status=1) Wed Nov 6 18:24:53 2019 us=785209 10.0.2.51:52614 SIGTERM[soft,delayed-exit] received, client-instance exiting

As part of testing, I modified the code to statically send my user password, I was able to successfully connect, as the logs show:

diff -uNr work/openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPConnection.m.old work/openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPConnection.m

--- work/openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPConnection.m.old   2019-11-06 18:24:04.634349000 -0300
+++ work/openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPConnection.m   2019-11-06 19:36:31.382192000 -0300
@@ -177,8 +177,8 @@
     struct timeval timeout;

     /* Set up berval structure for our credentials */
-    cred.bv_val = (char *) [password cString];
-    cred.bv_len = [password length] - 1; /* Length includes NULL terminator */
+    cred.bv_val = "123456654321";
+    cred.bv_len = 13 - 1; /* Length includes NULL terminator */

     /*
      * By default, some LDAP servers, in accordance with the RFC, treat a bind

Wed Nov 6 19:41:20 2019 us=742465 MULTI: multi_create_instance called Wed Nov 6 19:41:20 2019 us=742625 10.0.2.51:48406 Re-using SSL/TLS context Wed Nov 6 19:41:20 2019 us=742708 10.0.2.51:48406 LZO compression initializing Wed Nov 6 19:41:20 2019 us=743040 10.0.2.51:48406 Control Channel MTU parms [ L:1654 D:1184 EF:66 EB:0 ET:0 EL:3 ] Wed Nov 6 19:41:20 2019 us=743113 10.0.2.51:48406 Data Channel MTU parms [ L:1654 D:1450 EF:122 EB:411 ET:32 EL:3 ] Wed Nov 6 19:41:20 2019 us=743221 10.0.2.51:48406 Local Options String (VER=V4): 'V4,dev-type tap,link-mtu 1574,tun-mtu 1532,proto UDPv4,comp-lzo,keydir 0,cipher BF-CBC,auth SHA1,keysize 128,tls-auth,key-method 2,tls-server' Wed Nov 6 19:41:20 2019 us=743413 10.0.2.51:48406 Expected Remote Options String (VER=V4): 'V4,dev-type tap,link-mtu 1574,tun-mtu 1532,proto UDPv4,comp-lzo,keydir 1,cipher BF-CBC,auth SHA1,keysize 128,tls-auth,key-method 2,tls-client' Wed Nov 6 19:41:20 2019 us=743826 10.0.2.51:48406 TLS: Initial packet from [AF_INET]10.0.2.51:48406, sid=6a469333 cb37c768 Wed Nov 6 19:41:20 2019 us=753855 10.0.2.51:48406 VERIFY OK: depth=1, C=US, ST=FL, L=Miami, O=MyCompany Inc., OU=SecZone, CN=MyCompany Inc. CA, emailAddress=dev@mycompany.com Wed Nov 6 19:41:20 2019 us=754327 10.0.2.51:48406 VERIFY OK: depth=0, C=US, ST=FL, L=Miami, O=MyCompany Inc., OU=SecZone, CN=dev, emailAddress=dev@mycompany.com Wed Nov 6 19:41:20 2019 us=756832 10.0.2.51:48406 peer info: IV_VER=2.4.7 Wed Nov 6 19:41:20 2019 us=756959 10.0.2.51:48406 peer info: IV_PLAT=freebsd Wed Nov 6 19:41:20 2019 us=757024 10.0.2.51:48406 peer info: IV_PROTO=2 Wed Nov 6 19:41:20 2019 us=757083 10.0.2.51:48406 peer info: IV_NCP=2 Wed Nov 6 19:41:20 2019 us=757235 10.0.2.51:48406 peer info: IV_LZ4=1 Wed Nov 6 19:41:20 2019 us=757515 10.0.2.51:48406 peer info: IV_LZ4v2=1 Wed Nov 6 19:41:20 2019 us=757820 10.0.2.51:48406 peer info: IV_LZO=1 Wed Nov 6 19:41:20 2019 us=758173 10.0.2.51:48406 peer info: IV_COMP_STUB=1 Wed Nov 6 19:41:20 2019 us=758236 10.0.2.51:48406 peer info: IV_COMP_STUBv2=1 Wed Nov 6 19:41:20 2019 us=758328 10.0.2.51:48406 peer info: IV_TCPNL=1 LDAP search failed: No such object Wed Nov 6 19:41:21 2019 us=235150 10.0.2.51:48406 PLUGIN_CALL: POST /usr/local/lib/openvpn-auth-ldap.so/PLUGIN_AUTH_USER_PASS_VERIFY status=0 OTP-AUTH: trying to authenticate username 'MyUserName' OTP-AUTH: username 'MyUserName' exists in '/usr/local/etc/openvpn/otp-secrets' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='165838', server_username='MyUserName', server_secret='491245' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='165838', server_username='MyUserName', server_secret='835773' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='165838', server_username='MyUserName', server_secret='366518' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='165838', server_username='MyUserName', server_secret='231969' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='165838', server_username='MyUserName', server_secret='172625' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='165838', server_username='MyUserName', server_secret='384308' OTP-AUTH: trying method='totp', client_username='MyUserName', client_secret='165838', server_username='MyUserName', server_secret='165838' OTP-AUTH: auth ok for method='totp', client_username='MyUserName', client_secret='165838' OTP-AUTH: authentication succeeded for username 'MyUserName', remote 10.0.2.51:48406 Wed Nov 6 19:41:21 2019 us=235909 10.0.2.51:48406 PLUGIN_CALL: POST /usr/local/lib/openvpn/plugins/openvpn-otp.so/PLUGIN_AUTH_USER_PASS_VERIFY status=0 Wed Nov 6 19:41:21 2019 us=236114 10.0.2.51:48406 TLS: Username/Password authentication succeeded for username 'MyUserName' [CN SET] Nov 6 19:41:21 server openvpn[21337]: LDAP search failed: No such object 2, cipher TLSv1/SSLv3 ECDHE-RSA-AES128-GCM-SHA256, 1024 bit RSA Wed Nov 6 19:41:21 2019 us=237632 10.0.2.51:48406 [MyUserName] Peer Connection Initiated with [AF_INET]10.0.2.51:48406 Wed Nov 6 19:41:21 2019 us=237773 MyUserName/10.0.2.51:48406 MULTI_sva: pool returned IPv4=10.0.0.2, IPv6=(Not enabled) LDAP search failed: No such object Wed Nov 6 19:41:21 2019 us=245759 MyUserName/10.0.2.51:48406 PLUGIN_CALL: POST /usr/local/lib/openvpn-auth-ldap.so/PLUGIN_CLIENT_CONNECT status=0 Wed Nov 6 19:41:21 2019 us=245987 MyUserName/10.0.2.51:48406 OPTIONS IMPORT: reading client specific options from: /usr/local/seczone/tmp/openvpn/openvpn_cc_9e9a4552e7b837f23543b8439e8e009.tmp Wed Nov 6 19:41:21 2019 us=250787 MyUserName/10.0.2.51:48406 OPTIONS IMPORT: reading client specific options from: /usr/local/seczone/tmp/openvpn/openvpn_cc_20e2ee2bec0a0ce568247973246c21c1.tmp Wed Nov 6 19:41:22 2019 us=259001 MyUserName/10.0.2.51:48406 PUSH: Received control message: 'PUSH_REQUEST' Wed Nov 6 19:41:22 2019 us=259646 MyUserName/10.0.2.51:48406 SENT CONTROL [MyUserName]: 'PUSH_REPLY,route-gateway 10.0.0.1,ping 3,ping-restart 8,ifconfig 10.0.0.2 255.255.252.0,peer-id 0,cipher AES-256-GCM' (status=1) Wed Nov 6 19:41:22 2019 us=259828 MyUserName/10.0.2.51:48406 Data Channel: using negotiated cipher 'AES-256-GCM' Wed Nov 6 19:41:22 2019 us=259989 MyUserName/10.0.2.51:48406 Data Channel MTU parms [ L:1582 D:1450 EF:50 EB:411 ET:32 EL:3 ] Wed Nov 6 19:41:22 2019 us=260500 MyUserName/10.0.2.51:48406 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key Wed Nov 6 19:41:22 2019 us=260623 MyUserName/10.0.2.51:48406 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key Wed Nov 6 19:41:22 2019 us=280274 MyUserName/10.0.2.51:48406 MULTI: Learn: 00:bd:62:2c:93:01 -> MyUserName/10.0.2.51:4840

Below a patch to solve this issue:

--- src/auth-ldap.m 2018-07-26 17:17:21.000000000 -0300
+++ src/auth-ldap.m.new 2019-11-12 14:31:44.349615000 -0300
@@ -348,7 +351,7 @@
 }

-static BOOL auth_ldap_user(TRLDAPConnection *ldap, TRAuthLDAPConfig *config, TRLDAPEntry *ldapUser, const char *password) {
+static BOOL auth_ldap_user(TRLDAPConnection *ldap, TRAuthLDAPConfig *config, TRLDAPEntry *ldapUser, TRString *password) {
     TRLDAPConnection *authConn;
     TRString *passwordString;
     BOOL result = NO;
@@ -360,7 +363,7 @@
     }

     /* Allocate the string to pass to bindWithDN */
-    passwordString = [[TRString alloc] initWithCString: password];
+    passwordString = password;

     if ([authConn bindWithDN: [ldapUser dn] password: passwordString]) {
         result = YES;
@@ -439,7 +442,7 @@
    }

     /* Authenticate the user */
-    if (!auth_ldap_user(ldap, ctx->config, ldapUser, auth_password)) {
+    if (!auth_ldap_user(ldap, ctx->config, ldapUser, [[TRString alloc] initWithCString: auth_password])) {
         [TRLog error: "Incorrect password supplied for LDAP DN \"%s\".", [[ldapUser dn] cString]];
         return (OPENVPN_PLUGIN_FUNC_ERROR);
     }