2008-01-19 14:29:03 +03:00
/*
2002-11-24 11:32:03 +03:00
Unix SMB / CIFS implementation .
Winbind status program .
2004-04-06 20:44:24 +04:00
Copyright ( C ) Tim Potter 2000 - 2003
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2003 - 2004
2008-01-19 14:29:03 +03:00
Copyright ( C ) Francesco Chemolli < kinkie @ kame . usr . dsi . unimi . it > 2000
2006-08-19 05:04:54 +04:00
Copyright ( C ) Robert O ' Callahan 2006 ( added cached credential code ) .
2008-01-19 14:29:03 +03:00
Copyright ( C ) Kai Blin < kai @ samba . org > 2008
2002-11-24 11:32:03 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2002-11-24 11:32:03 +03:00
( at your option ) any later version .
2008-01-19 14:29:03 +03:00
2002-11-24 11:32:03 +03:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2008-01-19 14:29:03 +03:00
2002-11-24 11:32:03 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-11-24 11:32:03 +03:00
*/
# include "includes.h"
2010-08-05 12:49:53 +04:00
# include "popt_common.h"
2004-10-07 08:01:18 +04:00
# include "utils/ntlm_auth.h"
2009-03-16 13:27:58 +03:00
# include "../libcli/auth/libcli_auth.h"
2009-09-17 02:21:01 +04:00
# include "../libcli/auth/spnego.h"
2010-05-25 14:19:22 +04:00
# include "../libcli/auth/ntlmssp.h"
2009-11-27 17:52:57 +03:00
# include "smb_krb5.h"
2009-05-21 22:03:32 +04:00
# include <iniparser.h>
2010-05-18 02:16:40 +04:00
# include "../lib/crypto/arcfour.h"
2010-07-02 02:32:52 +04:00
# include "libads/kerberos_proto.h"
2010-08-18 14:42:49 +04:00
# include "nsswitch/winbind_client.h"
2010-09-16 11:31:10 +04:00
# include "librpc/gen_ndr/krb5pac.h"
2009-05-21 22:03:32 +04:00
# ifndef PAM_WINBIND_CONFIG_FILE
# define PAM_WINBIND_CONFIG_FILE " / etc / security / pam_winbind.conf"
# endif
# define WINBIND_KRB5_AUTH 0x00000080
2002-11-24 11:32:03 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2008-01-16 11:52:26 +03:00
# define INITIAL_BUFFER_SIZE 300
# define MAX_BUFFER_SIZE 630000
2002-11-24 11:32:03 +03:00
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
enum stdio_helper_mode {
2003-01-16 06:29:54 +03:00
SQUID_2_4_BASIC ,
2002-11-25 00:08:36 +03:00
SQUID_2_5_BASIC ,
2003-07-29 19:00:38 +04:00
SQUID_2_5_NTLMSSP ,
2003-12-30 11:52:46 +03:00
NTLMSSP_CLIENT_1 ,
2003-08-01 11:59:23 +04:00
GSS_SPNEGO ,
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
GSS_SPNEGO_CLIENT ,
2004-04-13 00:46:13 +04:00
NTLM_SERVER_1 ,
2006-07-13 13:29:25 +04:00
NTLM_CHANGE_PASSWORD_1 ,
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
NUM_HELPER_MODES
} ;
2008-01-18 12:37:16 +03:00
enum ntlm_auth_cli_state {
CLIENT_INITIAL = 0 ,
2008-01-16 16:45:22 +03:00
CLIENT_RESPONSE ,
CLIENT_FINISHED ,
2008-01-18 12:37:16 +03:00
CLIENT_ERROR
} ;
enum ntlm_auth_svr_state {
SERVER_INITIAL = 0 ,
2008-01-16 16:45:22 +03:00
SERVER_CHALLENGE ,
SERVER_FINISHED ,
SERVER_ERROR
} ;
struct ntlm_auth_state {
TALLOC_CTX * mem_ctx ;
enum stdio_helper_mode helper_mode ;
2008-01-18 12:37:16 +03:00
enum ntlm_auth_cli_state cli_state ;
enum ntlm_auth_svr_state svr_state ;
2008-01-18 16:40:47 +03:00
struct ntlmssp_state * ntlmssp_state ;
uint32_t neg_flags ;
char * want_feature_list ;
2010-12-02 02:39:23 +03:00
char * spnego_mech ;
char * spnego_mech_oid ;
2008-01-18 16:40:47 +03:00
bool have_session_key ;
DATA_BLOB session_key ;
DATA_BLOB initial_message ;
2008-01-16 16:45:22 +03:00
} ;
2008-01-18 12:37:16 +03:00
typedef void ( * stdio_helper_function ) ( struct ntlm_auth_state * state , char * buf ,
int length ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
2008-01-18 12:37:16 +03:00
static void manage_squid_basic_request ( struct ntlm_auth_state * state ,
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
char * buf , int length ) ;
2008-01-18 12:37:16 +03:00
static void manage_squid_ntlmssp_request ( struct ntlm_auth_state * state ,
char * buf , int length ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
2008-01-18 12:37:16 +03:00
static void manage_client_ntlmssp_request ( struct ntlm_auth_state * state ,
char * buf , int length ) ;
2003-12-30 10:33:58 +03:00
2008-01-18 12:37:16 +03:00
static void manage_gss_spnego_request ( struct ntlm_auth_state * state ,
char * buf , int length ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
2008-01-18 12:37:16 +03:00
static void manage_gss_spnego_client_request ( struct ntlm_auth_state * state ,
char * buf , int length ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
2008-01-18 12:37:16 +03:00
static void manage_ntlm_server_1_request ( struct ntlm_auth_state * state ,
char * buf , int length ) ;
2004-04-13 00:46:13 +04:00
2008-01-18 12:37:16 +03:00
static void manage_ntlm_change_password_1_request ( struct ntlm_auth_state * state ,
char * buf , int length ) ;
2006-07-13 13:29:25 +04:00
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
static const struct {
enum stdio_helper_mode mode ;
const char * name ;
stdio_helper_function fn ;
} stdio_helper_protocols [ ] = {
{ SQUID_2_4_BASIC , " squid-2.4-basic " , manage_squid_basic_request } ,
{ SQUID_2_5_BASIC , " squid-2.5-basic " , manage_squid_basic_request } ,
{ SQUID_2_5_NTLMSSP , " squid-2.5-ntlmssp " , manage_squid_ntlmssp_request } ,
2003-12-30 11:52:46 +03:00
{ NTLMSSP_CLIENT_1 , " ntlmssp-client-1 " , manage_client_ntlmssp_request } ,
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
{ GSS_SPNEGO , " gss-spnego " , manage_gss_spnego_request } ,
{ GSS_SPNEGO_CLIENT , " gss-spnego-client " , manage_gss_spnego_client_request } ,
2004-04-13 00:46:13 +04:00
{ NTLM_SERVER_1 , " ntlm-server-1 " , manage_ntlm_server_1_request } ,
2006-07-13 13:29:25 +04:00
{ NTLM_CHANGE_PASSWORD_1 , " ntlm-change-password-1 " , manage_ntlm_change_password_1_request } ,
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
{ NUM_HELPER_MODES , NULL , NULL }
2002-11-25 00:08:36 +03:00
} ;
2004-04-12 18:19:48 +04:00
const char * opt_username ;
const char * opt_domain ;
const char * opt_workstation ;
const char * opt_password ;
2003-04-07 11:10:53 +04:00
static DATA_BLOB opt_challenge ;
static DATA_BLOB opt_lm_response ;
static DATA_BLOB opt_nt_response ;
2003-03-24 12:54:13 +03:00
static int request_lm_key ;
2004-04-12 14:17:48 +04:00
static int request_user_session_key ;
2006-08-19 05:04:54 +04:00
static int use_cached_creds ;
2002-11-24 11:32:03 +03:00
2004-04-06 20:44:24 +04:00
static const char * require_membership_of ;
2004-10-01 07:28:39 +04:00
static const char * require_membership_of_sid ;
2009-05-21 22:03:32 +04:00
static const char * opt_pam_winbind_conf ;
2002-11-24 11:32:03 +03:00
static char winbind_separator ( void )
{
struct winbindd_response response ;
2007-10-19 04:40:25 +04:00
static bool got_sep ;
2002-11-24 11:32:03 +03:00
static char sep ;
if ( got_sep )
return sep ;
ZERO_STRUCT ( response ) ;
/* Send off request */
2005-06-25 00:25:18 +04:00
if ( winbindd_request_response ( WINBINDD_INFO , NULL , & response ) ! =
2002-11-24 11:32:03 +03:00
NSS_STATUS_SUCCESS ) {
d_printf ( " could not obtain winbind separator! \n " ) ;
2004-04-12 14:17:48 +04:00
return * lp_winbind_separator ( ) ;
2002-11-24 11:32:03 +03:00
}
sep = response . data . info . winbind_separator ;
got_sep = True ;
if ( ! sep ) {
d_printf ( " winbind separator was NULL! \n " ) ;
2004-04-12 14:17:48 +04:00
return * lp_winbind_separator ( ) ;
2002-11-24 11:32:03 +03:00
}
2008-01-19 14:29:03 +03:00
2002-11-24 11:32:03 +03:00
return sep ;
}
2004-04-12 18:19:48 +04:00
const char * get_winbind_domain ( void )
2002-11-24 11:32:03 +03:00
{
struct winbindd_response response ;
static fstring winbind_domain ;
2003-01-16 06:29:54 +03:00
if ( * winbind_domain ) {
return winbind_domain ;
}
2002-11-24 11:32:03 +03:00
ZERO_STRUCT ( response ) ;
/* Send off request */
2005-06-25 00:25:18 +04:00
if ( winbindd_request_response ( WINBINDD_DOMAIN_NAME , NULL , & response ) ! =
2002-11-24 11:32:03 +03:00
NSS_STATUS_SUCCESS ) {
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
DEBUG ( 0 , ( " could not obtain winbind domain name! \n " ) ) ;
2004-04-12 14:17:48 +04:00
return lp_workgroup ( ) ;
2002-11-24 11:32:03 +03:00
}
fstrcpy ( winbind_domain , response . data . domain_name ) ;
return winbind_domain ;
}
2004-04-12 18:19:48 +04:00
const char * get_winbind_netbios_name ( void )
2003-01-16 06:29:54 +03:00
{
struct winbindd_response response ;
static fstring winbind_netbios_name ;
if ( * winbind_netbios_name ) {
return winbind_netbios_name ;
}
ZERO_STRUCT ( response ) ;
/* Send off request */
2005-06-25 00:25:18 +04:00
if ( winbindd_request_response ( WINBINDD_NETBIOS_NAME , NULL , & response ) ! =
2003-01-16 06:29:54 +03:00
NSS_STATUS_SUCCESS ) {
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
DEBUG ( 0 , ( " could not obtain winbind netbios name! \n " ) ) ;
2004-04-12 14:17:48 +04:00
return global_myname ( ) ;
2003-01-16 06:29:54 +03:00
}
fstrcpy ( winbind_netbios_name , response . data . netbios_name ) ;
return winbind_netbios_name ;
}
2004-04-12 18:19:48 +04:00
DATA_BLOB get_challenge ( void )
{
static DATA_BLOB chal ;
if ( opt_challenge . length )
return opt_challenge ;
2010-01-09 22:26:46 +03:00
2004-04-12 18:19:48 +04:00
chal = data_blob ( NULL , 8 ) ;
2004-07-14 08:36:01 +04:00
generate_random_buffer ( chal . data , chal . length ) ;
2004-04-12 18:19:48 +04:00
return chal ;
}
2004-04-06 20:44:24 +04:00
/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
form DOMAIN / user into a domain and a user */
2007-10-19 04:40:25 +04:00
static bool parse_ntlm_auth_domain_user ( const char * domuser , fstring domain ,
2004-04-06 20:44:24 +04:00
fstring user )
{
char * p = strchr ( domuser , winbind_separator ( ) ) ;
if ( ! p ) {
return False ;
}
2010-01-09 22:26:46 +03:00
2004-04-06 20:44:24 +04:00
fstrcpy ( user , p + 1 ) ;
fstrcpy ( domain , domuser ) ;
domain [ PTR_DIFF ( p , domuser ) ] = 0 ;
strupper_m ( domain ) ;
return True ;
}
2007-10-19 04:40:25 +04:00
static bool get_require_membership_sid ( void ) {
2004-04-06 20:44:24 +04:00
struct winbindd_request request ;
struct winbindd_response response ;
if ( ! require_membership_of ) {
return True ;
}
2004-10-01 07:28:39 +04:00
if ( require_membership_of_sid ) {
2004-04-06 20:44:24 +04:00
return True ;
}
/* Otherwise, ask winbindd for the name->sid request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( ! parse_ntlm_auth_domain_user ( require_membership_of ,
request . data . name . dom_name ,
request . data . name . name ) ) {
DEBUG ( 0 , ( " Could not parse %s into seperate domain/name parts! \n " ,
require_membership_of ) ) ;
return False ;
}
2005-06-25 00:25:18 +04:00
if ( winbindd_request_response ( WINBINDD_LOOKUPNAME , & request , & response ) ! =
2004-04-06 20:44:24 +04:00
NSS_STATUS_SUCCESS ) {
DEBUG ( 0 , ( " Winbindd lookupname failed to resolve %s into a SID! \n " ,
require_membership_of ) ) ;
return False ;
}
2004-12-07 21:25:53 +03:00
require_membership_of_sid = SMB_STRDUP ( response . data . sid . sid ) ;
2004-04-06 20:44:24 +04:00
2004-10-01 07:28:39 +04:00
if ( require_membership_of_sid )
2004-04-06 20:44:24 +04:00
return True ;
return False ;
}
2009-05-21 22:03:32 +04:00
/*
* Get some configuration from pam_winbind . conf to see if we
* need to contact trusted domain
*/
int get_pam_winbind_config ( )
{
int ctrl = 0 ;
dictionary * d = NULL ;
2010-01-09 22:26:46 +03:00
2009-05-21 22:03:32 +04:00
if ( ! opt_pam_winbind_conf | | ! * opt_pam_winbind_conf ) {
opt_pam_winbind_conf = PAM_WINBIND_CONFIG_FILE ;
}
d = iniparser_load ( CONST_DISCARD ( char * , opt_pam_winbind_conf ) ) ;
2010-01-09 22:26:46 +03:00
2009-05-21 22:03:32 +04:00
if ( ! d ) {
return 0 ;
}
2010-01-09 22:26:46 +03:00
2009-05-21 22:03:32 +04:00
if ( iniparser_getboolean ( d , CONST_DISCARD ( char * , " global:krb5_auth " ) , false ) ) {
ctrl | = WINBIND_KRB5_AUTH ;
}
iniparser_freedict ( d ) ;
2010-01-09 22:26:46 +03:00
2009-05-21 22:03:32 +04:00
return ctrl ;
}
2002-11-24 11:32:03 +03:00
/* Authenticate a user with a plaintext password */
2007-12-04 05:48:41 +03:00
static bool check_plaintext_auth ( const char * user , const char * pass ,
2007-10-19 04:40:25 +04:00
bool stdout_diagnostics )
2002-11-24 11:32:03 +03:00
{
struct winbindd_request request ;
struct winbindd_response response ;
NSS_STATUS result ;
2004-04-06 20:44:24 +04:00
if ( ! get_require_membership_sid ( ) ) {
return False ;
}
2002-11-24 11:32:03 +03:00
/* Send off request */
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
fstrcpy ( request . data . auth . user , user ) ;
fstrcpy ( request . data . auth . pass , pass ) ;
2007-12-04 05:48:41 +03:00
if ( require_membership_of_sid ) {
strlcpy ( request . data . auth . require_membership_of_sid ,
require_membership_of_sid ,
sizeof ( request . data . auth . require_membership_of_sid ) ) ;
}
2002-11-24 11:32:03 +03:00
2005-06-25 00:25:18 +04:00
result = winbindd_request_response ( WINBINDD_PAM_AUTH , & request , & response ) ;
2002-11-24 11:32:03 +03:00
/* Display response */
2007-12-04 05:48:41 +03:00
2002-11-24 11:32:03 +03:00
if ( stdout_diagnostics ) {
if ( ( result ! = NSS_STATUS_SUCCESS ) & & ( response . data . auth . nt_status = = 0 ) ) {
d_printf ( " Reading winbind reply failed! (0x01) \n " ) ;
}
2007-12-04 05:48:41 +03:00
d_printf ( " %s: %s (0x%x) \n " ,
response . data . auth . nt_status_string ,
response . data . auth . error_string ,
2002-11-24 11:32:03 +03:00
response . data . auth . nt_status ) ;
} else {
if ( ( result ! = NSS_STATUS_SUCCESS ) & & ( response . data . auth . nt_status = = 0 ) ) {
DEBUG ( 1 , ( " Reading winbind reply failed! (0x01) \n " ) ) ;
}
2007-12-04 05:48:41 +03:00
DEBUG ( 3 , ( " %s: %s (0x%x) \n " ,
response . data . auth . nt_status_string ,
2003-04-07 11:10:53 +04:00
response . data . auth . error_string ,
2007-12-04 05:48:41 +03:00
response . data . auth . nt_status ) ) ;
2002-11-24 11:32:03 +03:00
}
2007-12-04 05:48:41 +03:00
2002-11-24 11:32:03 +03:00
return ( result = = NSS_STATUS_SUCCESS ) ;
}
2003-04-07 11:10:53 +04:00
/* authenticate a user with an encrypted username/password */
2007-12-04 05:48:41 +03:00
NTSTATUS contact_winbind_auth_crap ( const char * username ,
const char * domain ,
2004-04-12 18:19:48 +04:00
const char * workstation ,
2007-12-04 05:48:41 +03:00
const DATA_BLOB * challenge ,
const DATA_BLOB * lm_response ,
const DATA_BLOB * nt_response ,
uint32 flags ,
uint8 lm_key [ 8 ] ,
uint8 user_session_key [ 16 ] ,
char * * error_string ,
char * * unix_name )
2003-01-16 06:29:54 +03:00
{
2003-04-07 11:10:53 +04:00
NTSTATUS nt_status ;
NSS_STATUS result ;
2003-01-16 06:29:54 +03:00
struct winbindd_request request ;
struct winbindd_response response ;
2003-04-07 11:10:53 +04:00
2004-04-06 20:44:24 +04:00
if ( ! get_require_membership_sid ( ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2003-01-16 06:29:54 +03:00
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2003-07-07 09:11:10 +04:00
request . flags = flags ;
2003-01-16 06:29:54 +03:00
2005-11-08 09:19:34 +03:00
request . data . auth_crap . logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT ;
2004-10-01 07:28:39 +04:00
if ( require_membership_of_sid )
fstrcpy ( request . data . auth_crap . require_membership_of_sid , require_membership_of_sid ) ;
2004-04-06 20:44:24 +04:00
2004-10-01 07:28:39 +04:00
fstrcpy ( request . data . auth_crap . user , username ) ;
fstrcpy ( request . data . auth_crap . domain , domain ) ;
2003-04-07 11:10:53 +04:00
2004-10-01 07:28:39 +04:00
fstrcpy ( request . data . auth_crap . workstation ,
workstation ) ;
2003-04-07 11:10:53 +04:00
memcpy ( request . data . auth_crap . chal , challenge - > data , MIN ( challenge - > length , 8 ) ) ;
2003-01-16 06:29:54 +03:00
2003-04-07 11:10:53 +04:00
if ( lm_response & & lm_response - > length ) {
2004-04-06 20:44:24 +04:00
memcpy ( request . data . auth_crap . lm_resp ,
lm_response - > data ,
MIN ( lm_response - > length , sizeof ( request . data . auth_crap . lm_resp ) ) ) ;
2003-04-07 11:10:53 +04:00
request . data . auth_crap . lm_resp_len = lm_response - > length ;
}
if ( nt_response & & nt_response - > length ) {
2008-11-07 11:13:26 +03:00
if ( nt_response - > length > sizeof ( request . data . auth_crap . nt_resp ) ) {
request . flags = request . flags | WBFLAG_BIG_NTLMV2_BLOB ;
request . extra_len = nt_response - > length ;
request . extra_data . data = SMB_MALLOC_ARRAY ( char , request . extra_len ) ;
if ( request . extra_data . data = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
memcpy ( request . extra_data . data , nt_response - > data ,
nt_response - > length ) ;
} else {
memcpy ( request . data . auth_crap . nt_resp ,
nt_response - > data , nt_response - > length ) ;
}
2003-04-07 11:10:53 +04:00
request . data . auth_crap . nt_resp_len = nt_response - > length ;
}
2010-01-09 22:26:46 +03:00
2005-06-25 00:25:18 +04:00
result = winbindd_request_response ( WINBINDD_PAM_AUTH_CRAP , & request , & response ) ;
2008-11-07 11:13:26 +03:00
SAFE_FREE ( request . extra_data . data ) ;
2003-01-16 06:29:54 +03:00
/* Display response */
if ( ( result ! = NSS_STATUS_SUCCESS ) & & ( response . data . auth . nt_status = = 0 ) ) {
2003-04-07 11:10:53 +04:00
nt_status = NT_STATUS_UNSUCCESSFUL ;
if ( error_string )
* error_string = smb_xstrdup ( " Reading winbind reply failed! " ) ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-04-07 11:10:53 +04:00
return nt_status ;
}
2010-01-09 22:26:46 +03:00
2003-04-07 11:10:53 +04:00
nt_status = ( NT_STATUS ( response . data . auth . nt_status ) ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
if ( error_string )
* error_string = smb_xstrdup ( response . data . auth . error_string ) ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-04-07 11:10:53 +04:00
return nt_status ;
2003-01-16 06:29:54 +03:00
}
2004-04-12 14:17:48 +04:00
if ( ( flags & WBFLAG_PAM_LMKEY ) & & lm_key ) {
2003-04-07 11:10:53 +04:00
memcpy ( lm_key , response . data . auth . first_8_lm_hash ,
2004-04-12 14:17:48 +04:00
sizeof ( response . data . auth . first_8_lm_hash ) ) ;
2003-04-07 11:10:53 +04:00
}
2004-04-12 14:17:48 +04:00
if ( ( flags & WBFLAG_PAM_USER_SESSION_KEY ) & & user_session_key ) {
memcpy ( user_session_key , response . data . auth . user_session_key ,
2004-04-06 12:11:16 +04:00
sizeof ( response . data . auth . user_session_key ) ) ;
2003-04-07 11:10:53 +04:00
}
2003-12-30 16:20:39 +03:00
if ( flags & WBFLAG_PAM_UNIX_NAME ) {
2008-02-28 15:29:47 +03:00
* unix_name = SMB_STRDUP ( response . data . auth . unix_username ) ;
2004-10-01 07:28:39 +04:00
if ( ! * unix_name ) {
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-12-31 01:27:33 +03:00
return NT_STATUS_NO_MEMORY ;
}
2003-12-30 16:20:39 +03:00
}
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2003-04-07 11:10:53 +04:00
return nt_status ;
}
2006-07-13 13:29:25 +04:00
/* contact server to change user password using auth crap */
static NTSTATUS contact_winbind_change_pswd_auth_crap ( const char * username ,
const char * domain ,
const DATA_BLOB new_nt_pswd ,
const DATA_BLOB old_nt_hash_enc ,
const DATA_BLOB new_lm_pswd ,
const DATA_BLOB old_lm_hash_enc ,
char * * error_string )
{
NTSTATUS nt_status ;
NSS_STATUS result ;
struct winbindd_request request ;
struct winbindd_response response ;
if ( ! get_require_membership_sid ( ) )
{
if ( error_string )
* error_string = smb_xstrdup ( " Can't get membership sid. " ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( username ! = NULL )
fstrcpy ( request . data . chng_pswd_auth_crap . user , username ) ;
if ( domain ! = NULL )
fstrcpy ( request . data . chng_pswd_auth_crap . domain , domain ) ;
if ( new_nt_pswd . length )
{
memcpy ( request . data . chng_pswd_auth_crap . new_nt_pswd , new_nt_pswd . data , sizeof ( request . data . chng_pswd_auth_crap . new_nt_pswd ) ) ;
request . data . chng_pswd_auth_crap . new_nt_pswd_len = new_nt_pswd . length ;
}
if ( old_nt_hash_enc . length )
{
memcpy ( request . data . chng_pswd_auth_crap . old_nt_hash_enc , old_nt_hash_enc . data , sizeof ( request . data . chng_pswd_auth_crap . old_nt_hash_enc ) ) ;
request . data . chng_pswd_auth_crap . old_nt_hash_enc_len = old_nt_hash_enc . length ;
}
if ( new_lm_pswd . length )
{
memcpy ( request . data . chng_pswd_auth_crap . new_lm_pswd , new_lm_pswd . data , sizeof ( request . data . chng_pswd_auth_crap . new_lm_pswd ) ) ;
request . data . chng_pswd_auth_crap . new_lm_pswd_len = new_lm_pswd . length ;
}
if ( old_lm_hash_enc . length )
{
memcpy ( request . data . chng_pswd_auth_crap . old_lm_hash_enc , old_lm_hash_enc . data , sizeof ( request . data . chng_pswd_auth_crap . old_lm_hash_enc ) ) ;
request . data . chng_pswd_auth_crap . old_lm_hash_enc_len = old_lm_hash_enc . length ;
}
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
result = winbindd_request_response ( WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP , & request , & response ) ;
/* Display response */
if ( ( result ! = NSS_STATUS_SUCCESS ) & & ( response . data . auth . nt_status = = 0 ) )
{
nt_status = NT_STATUS_UNSUCCESSFUL ;
if ( error_string )
* error_string = smb_xstrdup ( " Reading winbind reply failed! " ) ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2006-07-13 13:29:25 +04:00
return nt_status ;
}
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
nt_status = ( NT_STATUS ( response . data . auth . nt_status ) ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) )
{
if ( error_string )
* error_string = smb_xstrdup ( response . data . auth . error_string ) ;
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2006-07-13 13:29:25 +04:00
return nt_status ;
}
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & response ) ;
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
return nt_status ;
}
2010-09-16 08:37:20 +04:00
static NTSTATUS winbind_pw_check ( struct ntlmssp_state * ntlmssp_state , TALLOC_CTX * mem_ctx ,
DATA_BLOB * user_session_key , DATA_BLOB * lm_session_key )
2003-04-07 11:10:53 +04:00
{
2006-09-04 13:51:47 +04:00
static const char zeros [ 16 ] = { 0 , } ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
NTSTATUS nt_status ;
2009-02-13 13:17:42 +03:00
char * error_string = NULL ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
uint8 lm_key [ 8 ] ;
2004-04-12 14:17:48 +04:00
uint8 user_sess_key [ 16 ] ;
2009-02-10 00:25:59 +03:00
char * unix_name = NULL ;
2003-12-30 16:20:39 +03:00
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
nt_status = contact_winbind_auth_crap ( ntlmssp_state - > user , ntlmssp_state - > domain ,
2009-12-30 18:53:08 +03:00
ntlmssp_state - > client . netbios_name ,
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
& ntlmssp_state - > chal ,
& ntlmssp_state - > lm_resp ,
& ntlmssp_state - > nt_resp ,
2004-04-06 12:11:16 +04:00
WBFLAG_PAM_LMKEY | WBFLAG_PAM_USER_SESSION_KEY | WBFLAG_PAM_UNIX_NAME ,
2004-04-12 14:17:48 +04:00
lm_key , user_sess_key ,
2003-12-30 16:20:39 +03:00
& error_string , & unix_name ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
if ( memcmp ( lm_key , zeros , 8 ) ! = 0 ) {
2010-09-16 08:37:20 +04:00
* lm_session_key = data_blob_talloc ( mem_ctx , NULL , 16 ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
memcpy ( lm_session_key - > data , lm_key , 8 ) ;
memset ( lm_session_key - > data + 8 , ' \0 ' , 8 ) ;
}
2010-01-09 22:26:46 +03:00
2004-04-12 14:17:48 +04:00
if ( memcmp ( user_sess_key , zeros , 16 ) ! = 0 ) {
2010-09-16 08:37:20 +04:00
* user_session_key = data_blob_talloc ( mem_ctx , user_sess_key , 16 ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
}
2009-12-30 16:53:08 +03:00
ntlmssp_state - > callback_private = talloc_strdup ( ntlmssp_state ,
unix_name ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
} else {
DEBUG ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_ACCESS_DENIED ) ? 0 : 3 ,
( " Login for user [%s] \\ [%s]@[%s] failed due to [%s] \n " ,
2004-04-06 20:44:24 +04:00
ntlmssp_state - > domain , ntlmssp_state - > user ,
2009-12-30 18:53:08 +03:00
ntlmssp_state - > client . netbios_name ,
2004-04-06 20:44:24 +04:00
error_string ? error_string : " unknown error (NULL) " ) ) ;
2009-12-30 16:53:08 +03:00
ntlmssp_state - > callback_private = NULL ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
}
2009-02-10 00:25:59 +03:00
2009-02-13 12:06:14 +03:00
SAFE_FREE ( error_string ) ;
2009-02-10 00:25:59 +03:00
SAFE_FREE ( unix_name ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
return nt_status ;
2003-01-16 06:29:54 +03:00
}
2010-09-16 08:37:20 +04:00
static NTSTATUS local_pw_check ( struct ntlmssp_state * ntlmssp_state , TALLOC_CTX * mem_ctx ,
DATA_BLOB * user_session_key , DATA_BLOB * lm_session_key )
2003-12-30 10:33:58 +03:00
{
NTSTATUS nt_status ;
2009-04-06 16:56:13 +04:00
struct samr_Password lm_pw , nt_pw ;
2003-12-30 10:33:58 +03:00
2009-04-06 16:56:13 +04:00
nt_lm_owf_gen ( opt_password , nt_pw . hash , lm_pw . hash ) ;
2010-01-09 22:26:46 +03:00
2010-09-16 08:37:20 +04:00
nt_status = ntlm_password_check ( mem_ctx ,
2009-04-14 13:33:04 +04:00
true , true , 0 ,
2003-12-30 10:33:58 +03:00
& ntlmssp_state - > chal ,
& ntlmssp_state - > lm_resp ,
& ntlmssp_state - > nt_resp ,
ntlmssp_state - > user ,
ntlmssp_state - > user ,
ntlmssp_state - > domain ,
2009-04-14 13:33:04 +04:00
& lm_pw , & nt_pw , user_session_key , lm_session_key ) ;
2010-01-09 22:26:46 +03:00
2003-12-30 10:33:58 +03:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
2009-12-30 16:53:08 +03:00
ntlmssp_state - > callback_private = talloc_asprintf ( ntlmssp_state ,
2004-04-06 20:44:24 +04:00
" %s%c%s " , ntlmssp_state - > domain ,
* lp_winbind_separator ( ) ,
ntlmssp_state - > user ) ;
2003-12-30 10:33:58 +03:00
} else {
DEBUG ( 3 , ( " Login for user [%s] \\ [%s]@[%s] failed due to [%s] \n " ,
2009-12-30 18:53:08 +03:00
ntlmssp_state - > domain , ntlmssp_state - > user ,
ntlmssp_state - > client . netbios_name ,
2003-12-30 10:33:58 +03:00
nt_errstr ( nt_status ) ) ) ;
2009-12-30 16:53:08 +03:00
ntlmssp_state - > callback_private = NULL ;
2003-12-30 10:33:58 +03:00
}
return nt_status ;
}
2009-12-22 10:50:55 +03:00
static NTSTATUS ntlm_auth_start_ntlmssp_client ( struct ntlmssp_state * * client_ntlmssp_state )
2003-12-30 10:33:58 +03:00
{
NTSTATUS status ;
if ( ( opt_username = = NULL ) | | ( opt_domain = = NULL ) ) {
2005-09-30 21:13:37 +04:00
status = NT_STATUS_UNSUCCESSFUL ;
2003-12-30 10:33:58 +03:00
DEBUG ( 1 , ( " Need username and domain for NTLMSSP \n " ) ) ;
2004-10-01 07:28:39 +04:00
return NT_STATUS_INVALID_PARAMETER ;
2003-12-30 10:33:58 +03:00
}
2009-12-30 16:13:45 +03:00
status = ntlmssp_client_start ( NULL ,
global_myname ( ) ,
lp_workgroup ( ) ,
lp_client_ntlmv2_auth ( ) ,
client_ntlmssp_state ) ;
2003-12-30 10:33:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Could not start NTLMSSP client: %s \n " ,
nt_errstr ( status ) ) ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( * client_ntlmssp_state ) ;
2003-12-30 10:33:58 +03:00
return status ;
}
status = ntlmssp_set_username ( * client_ntlmssp_state , opt_username ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Could not set username: %s \n " ,
nt_errstr ( status ) ) ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( * client_ntlmssp_state ) ;
2003-12-30 10:33:58 +03:00
return status ;
}
status = ntlmssp_set_domain ( * client_ntlmssp_state , opt_domain ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Could not set domain: %s \n " ,
nt_errstr ( status ) ) ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( * client_ntlmssp_state ) ;
2003-12-30 10:33:58 +03:00
return status ;
}
2006-08-19 05:04:54 +04:00
if ( opt_password ) {
status = ntlmssp_set_password ( * client_ntlmssp_state , opt_password ) ;
2010-01-09 22:26:46 +03:00
2006-08-19 05:04:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Could not set password: %s \n " ,
nt_errstr ( status ) ) ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( * client_ntlmssp_state ) ;
2006-08-19 05:04:54 +04:00
return status ;
}
2003-12-30 10:33:58 +03:00
}
2006-08-19 05:04:54 +04:00
2003-12-30 10:33:58 +03:00
return NT_STATUS_OK ;
}
2009-12-22 10:50:55 +03:00
static NTSTATUS ntlm_auth_start_ntlmssp_server ( struct ntlmssp_state * * ntlmssp_state )
2003-12-30 10:33:58 +03:00
{
2009-12-30 13:55:23 +03:00
NTSTATUS status ;
const char * netbios_name ;
const char * netbios_domain ;
const char * dns_name ;
char * dns_domain ;
bool is_standalone = false ;
2010-01-09 22:26:46 +03:00
2009-12-30 13:55:23 +03:00
if ( opt_password ) {
netbios_name = global_myname ( ) ;
netbios_domain = lp_workgroup ( ) ;
} else {
netbios_name = get_winbind_netbios_name ( ) ;
netbios_domain = get_winbind_domain ( ) ;
}
/* This should be a 'netbios domain -> DNS domain' mapping */
dns_domain = get_mydnsdomname ( talloc_tos ( ) ) ;
if ( dns_domain ) {
strlower_m ( dns_domain ) ;
}
dns_name = get_mydnsfullname ( ) ;
status = ntlmssp_server_start ( NULL ,
is_standalone ,
netbios_name ,
netbios_domain ,
dns_name ,
dns_domain ,
ntlmssp_state ) ;
2003-12-30 10:33:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
DEBUG ( 1 , ( " Could not start NTLMSSP server: %s \n " ,
2003-12-30 10:33:58 +03:00
nt_errstr ( status ) ) ) ;
return status ;
}
/* Have we been given a local password, or should we ask winbind? */
if ( opt_password ) {
( * ntlmssp_state ) - > check_password = local_pw_check ;
} else {
( * ntlmssp_state ) - > check_password = winbind_pw_check ;
}
return NT_STATUS_OK ;
}
2006-08-19 05:04:54 +04:00
/*******************************************************************
2006-08-29 20:52:59 +04:00
Used by firefox to drive NTLM auth to IIS servers .
2006-08-19 05:04:54 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS do_ccache_ntlm_auth ( DATA_BLOB initial_msg , DATA_BLOB challenge_msg ,
DATA_BLOB * reply )
{
struct winbindd_request wb_request ;
struct winbindd_response wb_response ;
2009-05-21 22:03:32 +04:00
int ctrl = 0 ;
2006-08-19 05:04:54 +04:00
NSS_STATUS result ;
/* get winbindd to do the ntlmssp step on our behalf */
ZERO_STRUCT ( wb_request ) ;
ZERO_STRUCT ( wb_response ) ;
2009-05-21 22:03:32 +04:00
/*
* This is tricky here . If we set krb5_auth in pam_winbind . conf
* creds for users in trusted domain will be stored the winbindd
* child of the trusted domain . If we ask the primary domain for
* ntlm_ccache_auth , it will fail . So , we have to ask the trusted
* domain ' s child for ccache_ntlm_auth . that is to say , we have to
2010-09-13 13:56:48 +04:00
* set WBFLAG_PAM_CONTACT_TRUSTDOM in request . flags .
2009-05-21 22:03:32 +04:00
*/
ctrl = get_pam_winbind_config ( ) ;
if ( ctrl | WINBIND_KRB5_AUTH ) {
wb_request . flags | = WBFLAG_PAM_CONTACT_TRUSTDOM ;
}
2006-08-19 05:04:54 +04:00
fstr_sprintf ( wb_request . data . ccache_ntlm_auth . user ,
" %s%c%s " , opt_domain , winbind_separator ( ) , opt_username ) ;
wb_request . data . ccache_ntlm_auth . uid = geteuid ( ) ;
wb_request . data . ccache_ntlm_auth . initial_blob_len = initial_msg . length ;
wb_request . data . ccache_ntlm_auth . challenge_blob_len = challenge_msg . length ;
wb_request . extra_len = initial_msg . length + challenge_msg . length ;
if ( wb_request . extra_len > 0 ) {
wb_request . extra_data . data = SMB_MALLOC_ARRAY ( char , wb_request . extra_len ) ;
if ( wb_request . extra_data . data = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
memcpy ( wb_request . extra_data . data , initial_msg . data , initial_msg . length ) ;
memcpy ( wb_request . extra_data . data + initial_msg . length ,
challenge_msg . data , challenge_msg . length ) ;
}
result = winbindd_request_response ( WINBINDD_CCACHE_NTLMAUTH , & wb_request , & wb_response ) ;
SAFE_FREE ( wb_request . extra_data . data ) ;
if ( result ! = NSS_STATUS_SUCCESS ) {
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & wb_response ) ;
2006-08-19 05:04:54 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
if ( reply ) {
* reply = data_blob ( wb_response . extra_data . data ,
wb_response . data . ccache_ntlm_auth . auth_blob_len ) ;
if ( wb_response . data . ccache_ntlm_auth . auth_blob_len > 0 & &
reply - > data = = NULL ) {
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & wb_response ) ;
2006-08-19 05:04:54 +04:00
return NT_STATUS_NO_MEMORY ;
}
}
2007-09-14 11:07:59 +04:00
winbindd_free_response ( & wb_response ) ;
2006-08-19 05:04:54 +04:00
return NT_STATUS_MORE_PROCESSING_REQUIRED ;
}
2010-09-16 12:21:20 +04:00
static void manage_squid_ntlmssp_request_int ( struct ntlm_auth_state * state ,
char * buf , int length ,
TALLOC_CTX * mem_ctx ,
char * * response )
2003-01-16 06:29:54 +03:00
{
DATA_BLOB request , reply ;
NTSTATUS nt_status ;
2003-03-24 12:54:13 +03:00
if ( strlen ( buf ) < 2 ) {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " NTLMSSP query [%s] invalid \n " , buf ) ) ;
2010-09-16 12:21:20 +04:00
* response = talloc_strdup ( mem_ctx , " BH NTLMSSP query invalid " ) ;
2003-03-24 12:54:13 +03:00
return ;
}
2003-12-30 10:33:58 +03:00
if ( strlen ( buf ) > 3 ) {
2006-07-24 09:02:38 +04:00
if ( strncmp ( buf , " SF " , 3 ) = = 0 ) {
DEBUG ( 10 , ( " Setting flags to negotioate \n " ) ) ;
2008-01-19 14:29:03 +03:00
TALLOC_FREE ( state - > want_feature_list ) ;
state - > want_feature_list = talloc_strdup ( state - > mem_ctx ,
buf + 3 ) ;
2010-09-16 12:21:20 +04:00
* response = talloc_strdup ( mem_ctx , " OK " ) ;
2006-07-24 09:02:38 +04:00
return ;
}
2003-12-30 10:33:58 +03:00
request = base64_decode_data_blob ( buf + 3 ) ;
} else {
2007-05-14 16:16:20 +04:00
request = data_blob_null ;
2003-12-30 10:33:58 +03:00
}
if ( ( strncmp ( buf , " PW " , 3 ) = = 0 ) ) {
2008-01-19 14:29:03 +03:00
/* The calling application wants us to use a local password
* ( rather than winbindd ) */
2003-12-30 10:33:58 +03:00
2008-01-19 14:29:03 +03:00
opt_password = SMB_STRNDUP ( ( const char * ) request . data ,
request . length ) ;
2003-12-30 10:33:58 +03:00
if ( opt_password = = NULL ) {
DEBUG ( 1 , ( " Out of memory \n " ) ) ;
2010-09-16 12:21:20 +04:00
* response = talloc_strdup ( mem_ctx , " BH Out of memory " ) ;
2003-12-30 10:33:58 +03:00
data_blob_free ( & request ) ;
return ;
}
2010-09-16 12:21:20 +04:00
* response = talloc_strdup ( mem_ctx , " OK " ) ;
2003-12-30 10:33:58 +03:00
data_blob_free ( & request ) ;
return ;
}
2003-12-24 12:56:51 +03:00
if ( strncmp ( buf , " YR " , 2 ) = = 0 ) {
2010-09-14 02:02:01 +04:00
TALLOC_FREE ( state - > ntlmssp_state ) ;
2008-01-19 14:29:03 +03:00
state - > svr_state = SERVER_INITIAL ;
2003-12-24 12:56:51 +03:00
} else if ( strncmp ( buf , " KK " , 2 ) = = 0 ) {
2008-01-19 14:29:03 +03:00
/* No special preprocessing required */
2006-07-24 09:02:38 +04:00
} else if ( strncmp ( buf , " GF " , 2 ) = = 0 ) {
DEBUG ( 10 , ( " Requested negotiated NTLMSSP flags \n " ) ) ;
2008-01-19 14:29:03 +03:00
if ( state - > svr_state = = SERVER_FINISHED ) {
2010-09-16 12:21:20 +04:00
* response = talloc_asprintf ( mem_ctx , " GF 0x%08x " ,
state - > neg_flags ) ;
2008-01-19 14:29:03 +03:00
}
else {
2010-09-16 12:21:20 +04:00
* response = talloc_strdup ( mem_ctx , " BH \n " ) ;
2008-01-19 14:29:03 +03:00
}
2006-07-24 09:02:38 +04:00
data_blob_free ( & request ) ;
return ;
} else if ( strncmp ( buf , " GK " , 2 ) = = 0 ) {
DEBUG ( 10 , ( " Requested NTLMSSP session key \n " ) ) ;
2008-01-19 14:29:03 +03:00
if ( state - > have_session_key ) {
char * key64 = base64_encode_data_blob ( state - > mem_ctx ,
state - > session_key ) ;
2010-09-16 12:21:20 +04:00
* response = talloc_asprintf ( mem_ctx , " GK %s " ,
key64 ? key64 : " <NULL> " ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( key64 ) ;
2006-08-08 00:15:31 +04:00
} else {
2010-09-16 12:21:20 +04:00
* response = talloc_strdup ( mem_ctx , " BH " ) ;
2006-08-08 00:15:31 +04:00
}
2008-01-19 14:29:03 +03:00
2006-07-24 09:02:38 +04:00
data_blob_free ( & request ) ;
return ;
2003-03-24 12:54:13 +03:00
} else {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " NTLMSSP query [%s] invalid \n " , buf ) ) ;
2010-09-16 12:21:20 +04:00
* response = talloc_strdup ( mem_ctx , " BH NTLMSSP query invalid " ) ;
2003-03-24 12:54:13 +03:00
return ;
}
2008-01-19 14:29:03 +03:00
if ( ! state - > ntlmssp_state ) {
nt_status = ntlm_auth_start_ntlmssp_server (
& state - > ntlmssp_state ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2010-09-16 12:21:20 +04:00
* response = talloc_asprintf (
mem_ctx , " BH %s " , nt_errstr ( nt_status ) ) ;
2003-12-30 10:33:58 +03:00
return ;
}
2008-01-19 14:29:03 +03:00
ntlmssp_want_feature_list ( state - > ntlmssp_state ,
state - > want_feature_list ) ;
2003-01-16 06:29:54 +03:00
}
2003-03-24 12:54:13 +03:00
DEBUG ( 10 , ( " got NTLMSSP packet: \n " ) ) ;
2007-03-28 17:34:59 +04:00
dump_data ( 10 , request . data , request . length ) ;
2003-01-16 06:29:54 +03:00
2008-01-19 14:29:03 +03:00
nt_status = ntlmssp_update ( state - > ntlmssp_state , request , & reply ) ;
2003-01-16 06:29:54 +03:00
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
2008-01-19 14:29:03 +03:00
char * reply_base64 = base64_encode_data_blob ( state - > mem_ctx ,
2008-01-19 04:12:35 +03:00
reply ) ;
2010-09-16 12:21:20 +04:00
* response = talloc_asprintf ( mem_ctx , " TT %s " , reply_base64 ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( reply_base64 ) ;
2003-01-16 06:29:54 +03:00
data_blob_free ( & reply ) ;
2008-01-19 14:29:03 +03:00
state - > svr_state = SERVER_CHALLENGE ;
2003-03-24 12:54:13 +03:00
DEBUG ( 10 , ( " NTLMSSP challenge \n " ) ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
} else if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_ACCESS_DENIED ) ) {
2010-09-16 12:21:20 +04:00
* response = talloc_asprintf ( mem_ctx , " BH %s " ,
nt_errstr ( nt_status ) ) ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
DEBUG ( 0 , ( " NTLMSSP BH: %s \n " , nt_errstr ( nt_status ) ) ) ;
2003-12-30 10:33:58 +03:00
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( state - > ntlmssp_state ) ;
2003-01-16 06:29:54 +03:00
} else if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2010-09-16 12:21:20 +04:00
* response = talloc_asprintf ( mem_ctx , " NA %s " ,
nt_errstr ( nt_status ) ) ;
2003-03-24 12:54:13 +03:00
DEBUG ( 10 , ( " NTLMSSP %s \n " , nt_errstr ( nt_status ) ) ) ;
2003-01-16 06:29:54 +03:00
} else {
2010-09-16 12:21:20 +04:00
* response = talloc_asprintf (
mem_ctx , " AF %s " ,
( char * ) state - > ntlmssp_state - > callback_private ) ;
2003-03-24 12:54:13 +03:00
DEBUG ( 10 , ( " NTLMSSP OK! \n " ) ) ;
2008-01-19 14:29:03 +03:00
if ( state - > have_session_key )
data_blob_free ( & state - > session_key ) ;
state - > session_key = data_blob (
state - > ntlmssp_state - > session_key . data ,
state - > ntlmssp_state - > session_key . length ) ;
state - > neg_flags = state - > ntlmssp_state - > neg_flags ;
state - > have_session_key = true ;
state - > svr_state = SERVER_FINISHED ;
2003-01-16 06:29:54 +03:00
}
data_blob_free ( & request ) ;
}
2010-09-16 12:21:20 +04:00
static void manage_squid_ntlmssp_request ( struct ntlm_auth_state * state ,
char * buf , int length )
{
char * response ;
manage_squid_ntlmssp_request_int ( state , buf , length ,
talloc_tos ( ) , & response ) ;
if ( response = = NULL ) {
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
return ;
}
x_fprintf ( x_stdout , " %s \n " , response ) ;
TALLOC_FREE ( response ) ;
}
2008-01-18 12:37:16 +03:00
static void manage_client_ntlmssp_request ( struct ntlm_auth_state * state ,
char * buf , int length )
2003-12-30 10:33:58 +03:00
{
DATA_BLOB request , reply ;
NTSTATUS nt_status ;
2008-01-18 16:40:47 +03:00
2006-09-01 08:41:03 +04:00
if ( ! opt_username | | ! * opt_username ) {
x_fprintf ( x_stderr , " username must be specified! \n \n " ) ;
exit ( 1 ) ;
}
2003-12-30 10:33:58 +03:00
if ( strlen ( buf ) < 2 ) {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " NTLMSSP query [%s] invalid \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH NTLMSSP query invalid \n " ) ;
2003-12-30 10:33:58 +03:00
return ;
}
if ( strlen ( buf ) > 3 ) {
2006-07-24 09:02:38 +04:00
if ( strncmp ( buf , " SF " , 3 ) = = 0 ) {
DEBUG ( 10 , ( " Looking for flags to negotiate \n " ) ) ;
2008-01-18 16:40:47 +03:00
talloc_free ( state - > want_feature_list ) ;
state - > want_feature_list = talloc_strdup ( state - > mem_ctx ,
buf + 3 ) ;
2006-07-24 09:02:38 +04:00
x_fprintf ( x_stdout , " OK \n " ) ;
return ;
}
2003-12-30 10:33:58 +03:00
request = base64_decode_data_blob ( buf + 3 ) ;
} else {
2007-05-14 16:16:20 +04:00
request = data_blob_null ;
2003-12-30 10:33:58 +03:00
}
if ( strncmp ( buf , " PW " , 3 ) = = 0 ) {
/* We asked for a password and obviously got it :-) */
2008-01-18 16:40:47 +03:00
opt_password = SMB_STRNDUP ( ( const char * ) request . data ,
request . length ) ;
2003-12-30 10:33:58 +03:00
if ( opt_password = = NULL ) {
DEBUG ( 1 , ( " Out of memory \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
2003-12-30 10:33:58 +03:00
data_blob_free ( & request ) ;
return ;
}
x_fprintf ( x_stdout , " OK \n " ) ;
data_blob_free ( & request ) ;
return ;
}
2008-01-18 16:40:47 +03:00
if ( ! state - > ntlmssp_state & & use_cached_creds ) {
/* check whether cached credentials are usable. */
2007-05-14 16:16:20 +04:00
DATA_BLOB empty_blob = data_blob_null ;
2006-08-19 05:04:54 +04:00
nt_status = do_ccache_ntlm_auth ( empty_blob , empty_blob , NULL ) ;
if ( ! NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
/* failed to use cached creds */
use_cached_creds = False ;
}
}
if ( opt_password = = NULL & & ! use_cached_creds ) {
2003-12-30 10:33:58 +03:00
/* Request a password from the calling process. After
2008-01-18 16:40:47 +03:00
sending it , the calling process should retry asking for the
negotiate . */
2003-12-30 10:33:58 +03:00
DEBUG ( 10 , ( " Requesting password \n " ) ) ;
x_fprintf ( x_stdout , " PW \n " ) ;
return ;
}
if ( strncmp ( buf , " YR " , 2 ) = = 0 ) {
2010-09-14 02:02:01 +04:00
TALLOC_FREE ( state - > ntlmssp_state ) ;
2008-01-18 16:40:47 +03:00
state - > cli_state = CLIENT_INITIAL ;
2003-12-30 10:33:58 +03:00
} else if ( strncmp ( buf , " TT " , 2 ) = = 0 ) {
2008-01-18 16:40:47 +03:00
/* No special preprocessing required */
2006-07-24 09:02:38 +04:00
} else if ( strncmp ( buf , " GF " , 2 ) = = 0 ) {
DEBUG ( 10 , ( " Requested negotiated NTLMSSP flags \n " ) ) ;
2008-01-18 16:40:47 +03:00
if ( state - > cli_state = = CLIENT_FINISHED ) {
x_fprintf ( x_stdout , " GF 0x%08x \n " , state - > neg_flags ) ;
}
else {
x_fprintf ( x_stdout , " BH \n " ) ;
}
2006-07-24 09:02:38 +04:00
data_blob_free ( & request ) ;
return ;
} else if ( strncmp ( buf , " GK " , 2 ) = = 0 ) {
DEBUG ( 10 , ( " Requested session key \n " ) ) ;
2008-01-18 16:40:47 +03:00
if ( state - > cli_state = = CLIENT_FINISHED ) {
char * key64 = base64_encode_data_blob ( state - > mem_ctx ,
state - > session_key ) ;
2006-08-08 00:15:31 +04:00
x_fprintf ( x_stdout , " GK %s \n " , key64 ? key64 : " <NULL> " ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( key64 ) ;
2006-07-24 09:02:38 +04:00
}
else {
x_fprintf ( x_stdout , " BH \n " ) ;
}
data_blob_free ( & request ) ;
return ;
2003-12-30 10:33:58 +03:00
} else {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " NTLMSSP query [%s] invalid \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH NTLMSSP query invalid \n " ) ;
2003-12-30 10:33:58 +03:00
return ;
}
2008-01-18 16:40:47 +03:00
if ( ! state - > ntlmssp_state ) {
nt_status = ntlm_auth_start_ntlmssp_client (
& state - > ntlmssp_state ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2003-12-30 10:33:58 +03:00
x_fprintf ( x_stdout , " BH %s \n " , nt_errstr ( nt_status ) ) ;
return ;
}
2008-01-18 16:40:47 +03:00
ntlmssp_want_feature_list ( state - > ntlmssp_state ,
state - > want_feature_list ) ;
state - > initial_message = data_blob_null ;
2003-12-30 10:33:58 +03:00
}
DEBUG ( 10 , ( " got NTLMSSP packet: \n " ) ) ;
2007-03-28 17:34:59 +04:00
dump_data ( 10 , request . data , request . length ) ;
2003-12-30 10:33:58 +03:00
2008-01-18 16:40:47 +03:00
if ( use_cached_creds & & ! opt_password & &
( state - > cli_state = = CLIENT_RESPONSE ) ) {
nt_status = do_ccache_ntlm_auth ( state - > initial_message , request ,
& reply ) ;
2006-08-19 05:04:54 +04:00
} else {
2008-01-18 16:40:47 +03:00
nt_status = ntlmssp_update ( state - > ntlmssp_state , request ,
& reply ) ;
2006-08-19 05:04:54 +04:00
}
2008-01-18 16:40:47 +03:00
2003-12-30 10:33:58 +03:00
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
2008-01-18 16:40:47 +03:00
char * reply_base64 = base64_encode_data_blob ( state - > mem_ctx ,
2008-01-19 04:12:35 +03:00
reply ) ;
2008-01-18 16:40:47 +03:00
if ( state - > cli_state = = CLIENT_INITIAL ) {
2003-12-30 10:33:58 +03:00
x_fprintf ( x_stdout , " YR %s \n " , reply_base64 ) ;
2008-01-18 16:40:47 +03:00
state - > initial_message = reply ;
state - > cli_state = CLIENT_RESPONSE ;
2006-08-19 05:04:54 +04:00
} else {
2008-01-18 16:40:47 +03:00
x_fprintf ( x_stdout , " KK %s \n " , reply_base64 ) ;
2006-08-19 05:04:54 +04:00
data_blob_free ( & reply ) ;
}
2008-01-18 16:40:47 +03:00
TALLOC_FREE ( reply_base64 ) ;
2003-12-30 10:33:58 +03:00
DEBUG ( 10 , ( " NTLMSSP challenge \n " ) ) ;
} else if ( NT_STATUS_IS_OK ( nt_status ) ) {
2008-01-19 04:12:35 +03:00
char * reply_base64 = base64_encode_data_blob ( talloc_tos ( ) ,
reply ) ;
2005-09-30 21:13:37 +04:00
x_fprintf ( x_stdout , " AF %s \n " , reply_base64 ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( reply_base64 ) ;
2006-07-24 09:02:38 +04:00
2008-01-18 16:40:47 +03:00
if ( state - > have_session_key )
data_blob_free ( & state - > session_key ) ;
2006-07-24 09:02:38 +04:00
2008-01-18 16:40:47 +03:00
state - > session_key = data_blob (
state - > ntlmssp_state - > session_key . data ,
state - > ntlmssp_state - > session_key . length ) ;
state - > neg_flags = state - > ntlmssp_state - > neg_flags ;
state - > have_session_key = true ;
2006-07-24 09:02:38 +04:00
2003-12-30 10:33:58 +03:00
DEBUG ( 10 , ( " NTLMSSP OK! \n " ) ) ;
2008-01-18 16:40:47 +03:00
state - > cli_state = CLIENT_FINISHED ;
2010-09-14 02:02:01 +04:00
TALLOC_FREE ( state - > ntlmssp_state ) ;
2003-12-30 10:33:58 +03:00
} else {
x_fprintf ( x_stdout , " BH %s \n " , nt_errstr ( nt_status ) ) ;
DEBUG ( 0 , ( " NTLMSSP BH: %s \n " , nt_errstr ( nt_status ) ) ) ;
2008-01-18 16:40:47 +03:00
state - > cli_state = CLIENT_ERROR ;
2010-09-14 02:02:01 +04:00
TALLOC_FREE ( state - > ntlmssp_state ) ;
2003-12-30 10:33:58 +03:00
}
data_blob_free ( & request ) ;
}
2008-01-18 12:37:16 +03:00
static void manage_squid_basic_request ( struct ntlm_auth_state * state ,
char * buf , int length )
2003-01-16 06:29:54 +03:00
{
char * user , * pass ;
user = buf ;
2010-01-09 22:26:46 +03:00
2006-08-08 00:15:31 +04:00
pass = ( char * ) memchr ( buf , ' ' , length ) ;
2003-01-16 06:29:54 +03:00
if ( ! pass ) {
DEBUG ( 2 , ( " Password not found. Denying access \n " ) ) ;
2004-04-13 00:46:13 +04:00
x_fprintf ( x_stdout , " ERR \n " ) ;
2003-01-16 06:29:54 +03:00
return ;
}
* pass = ' \0 ' ;
pass + + ;
2010-01-09 22:26:46 +03:00
2008-01-18 12:37:16 +03:00
if ( state - > helper_mode = = SQUID_2_5_BASIC ) {
2003-01-16 06:29:54 +03:00
rfc1738_unescape ( user ) ;
rfc1738_unescape ( pass ) ;
}
2010-01-09 22:26:46 +03:00
2003-01-16 06:29:54 +03:00
if ( check_plaintext_auth ( user , pass , False ) ) {
x_fprintf ( x_stdout , " OK \n " ) ;
} else {
x_fprintf ( x_stdout , " ERR \n " ) ;
}
}
2003-07-29 19:00:38 +04:00
static void offer_gss_spnego_mechs ( void ) {
DATA_BLOB token ;
2009-09-17 02:21:01 +04:00
struct spnego_data spnego ;
2003-07-29 19:00:38 +04:00
ssize_t len ;
char * reply_base64 ;
2007-12-04 05:48:41 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
char * principal ;
char * myname_lower ;
2003-08-15 06:57:59 +04:00
2003-07-29 19:00:38 +04:00
ZERO_STRUCT ( spnego ) ;
2003-07-31 14:24:10 +04:00
2007-12-04 05:48:41 +03:00
myname_lower = talloc_strdup ( ctx , global_myname ( ) ) ;
if ( ! myname_lower ) {
return ;
}
2003-08-15 06:57:59 +04:00
strlower_m ( myname_lower ) ;
2007-12-04 05:48:41 +03:00
principal = talloc_asprintf ( ctx , " %s$@%s " , myname_lower , lp_realm ( ) ) ;
if ( ! principal ) {
return ;
}
2003-08-15 06:57:59 +04:00
2003-07-31 14:24:10 +04:00
/* Server negTokenInit (mech offerings) */
2003-07-29 19:00:38 +04:00
spnego . type = SPNEGO_NEG_TOKEN_INIT ;
2010-12-02 02:39:23 +03:00
spnego . negTokenInit . mechTypes = talloc_array ( ctx , const char * , 4 ) ;
2003-08-15 06:57:59 +04:00
# ifdef HAVE_KRB5
2010-03-26 00:22:56 +03:00
spnego . negTokenInit . mechTypes [ 0 ] = talloc_strdup ( ctx , OID_KERBEROS5_OLD ) ;
2010-12-02 02:39:23 +03:00
spnego . negTokenInit . mechTypes [ 1 ] = talloc_strdup ( ctx , OID_KERBEROS5 ) ;
spnego . negTokenInit . mechTypes [ 2 ] = talloc_strdup ( ctx , OID_NTLMSSP ) ;
spnego . negTokenInit . mechTypes [ 3 ] = NULL ;
2003-08-15 06:57:59 +04:00
# else
2010-03-26 00:22:56 +03:00
spnego . negTokenInit . mechTypes [ 0 ] = talloc_strdup ( ctx , OID_NTLMSSP ) ;
2003-07-31 14:24:10 +04:00
spnego . negTokenInit . mechTypes [ 1 ] = NULL ;
2003-08-15 06:57:59 +04:00
# endif
2003-07-29 19:00:38 +04:00
2003-08-15 06:57:59 +04:00
2010-03-26 00:22:56 +03:00
spnego . negTokenInit . mechListMIC = data_blob_talloc ( ctx , principal ,
2003-08-15 06:57:59 +04:00
strlen ( principal ) ) ;
2003-07-29 19:00:38 +04:00
2009-09-17 02:21:01 +04:00
len = spnego_write_data ( ctx , & token , & spnego ) ;
spnego_free_data ( & spnego ) ;
2003-07-29 19:00:38 +04:00
if ( len = = - 1 ) {
DEBUG ( 1 , ( " Could not write SPNEGO data blob \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Could not write SPNEGO data blob \n " ) ;
2003-07-29 19:00:38 +04:00
return ;
}
2008-01-19 04:12:35 +03:00
reply_base64 = base64_encode_data_blob ( talloc_tos ( ) , token ) ;
2003-08-01 11:59:23 +04:00
x_fprintf ( x_stdout , " TT %s * \n " , reply_base64 ) ;
2003-07-29 19:00:38 +04:00
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( reply_base64 ) ;
2003-07-29 19:00:38 +04:00
data_blob_free ( & token ) ;
DEBUG ( 10 , ( " sent SPNEGO negTokenInit \n " ) ) ;
return ;
}
2010-09-16 12:34:59 +04:00
bool spnego_parse_krb5_wrap ( TALLOC_CTX * ctx , DATA_BLOB blob , DATA_BLOB * ticket , uint8 tok_id [ 2 ] )
{
bool ret ;
ASN1_DATA * data ;
int data_remaining ;
data = asn1_init ( talloc_tos ( ) ) ;
if ( data = = NULL ) {
return false ;
}
asn1_load ( data , blob ) ;
asn1_start_tag ( data , ASN1_APPLICATION ( 0 ) ) ;
asn1_check_OID ( data , OID_KERBEROS5 ) ;
data_remaining = asn1_tag_remaining ( data ) ;
if ( data_remaining < 3 ) {
data - > has_error = True ;
} else {
asn1_read ( data , tok_id , 2 ) ;
data_remaining - = 2 ;
* ticket = data_blob_talloc ( ctx , NULL , data_remaining ) ;
asn1_read ( data , ticket - > data , ticket - > length ) ;
}
asn1_end_tag ( data ) ;
ret = ! data - > has_error ;
if ( data - > has_error ) {
data_blob_free ( ticket ) ;
}
asn1_free ( data ) ;
return ret ;
}
2008-01-18 12:37:16 +03:00
static void manage_gss_spnego_request ( struct ntlm_auth_state * state ,
char * buf , int length )
2003-07-29 19:00:38 +04:00
{
2009-09-17 02:21:01 +04:00
struct spnego_data request , response ;
2003-08-12 05:54:26 +04:00
DATA_BLOB token ;
2010-12-02 02:39:23 +03:00
DATA_BLOB raw_in_token = data_blob_null ;
DATA_BLOB raw_out_token = data_blob_null ;
2003-07-29 19:00:38 +04:00
NTSTATUS status ;
ssize_t len ;
2007-12-04 05:48:41 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-07-29 19:00:38 +04:00
2003-08-12 23:00:08 +04:00
char * user = NULL ;
char * domain = NULL ;
2003-08-01 11:59:23 +04:00
const char * reply_code ;
char * reply_base64 ;
2007-12-04 05:48:41 +03:00
char * reply_argument = NULL ;
2010-12-02 02:39:23 +03:00
char * supportedMech = NULL ;
2003-08-01 11:59:23 +04:00
2003-07-29 19:00:38 +04:00
if ( strlen ( buf ) < 2 ) {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " SPENGO query [%s] invalid \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH SPENGO query invalid \n " ) ;
2004-06-14 07:22:52 +04:00
return ;
}
2003-07-29 19:00:38 +04:00
2004-06-14 07:22:52 +04:00
if ( strncmp ( buf , " YR " , 2 ) = = 0 ) {
2010-12-02 02:39:23 +03:00
TALLOC_FREE ( state - > ntlmssp_state ) ;
TALLOC_FREE ( state - > spnego_mech ) ;
TALLOC_FREE ( state - > spnego_mech_oid ) ;
2004-06-14 07:22:52 +04:00
} else if ( strncmp ( buf , " KK " , 2 ) = = 0 ) {
2007-12-04 05:48:41 +03:00
;
2004-06-14 07:22:52 +04:00
} else {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " SPENGO query [%s] invalid \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH SPENGO query invalid \n " ) ;
2003-07-29 19:00:38 +04:00
return ;
}
2004-06-14 07:22:52 +04:00
if ( ( strlen ( buf ) = = 2 ) ) {
2003-07-29 19:00:38 +04:00
2004-06-14 07:22:52 +04:00
/* no client data, get the negTokenInit offering
2003-07-29 19:00:38 +04:00
mechanisms */
offer_gss_spnego_mechs ( ) ;
return ;
}
2004-06-14 07:22:52 +04:00
/* All subsequent requests have a blob. This might be negTokenInit or negTokenTarg */
2003-07-29 19:00:38 +04:00
2004-06-14 07:22:52 +04:00
if ( strlen ( buf ) < = 3 ) {
2003-07-29 19:00:38 +04:00
DEBUG ( 1 , ( " GSS-SPNEGO query [%s] invalid \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH GSS-SPNEGO query invalid \n " ) ;
2003-07-29 19:00:38 +04:00
return ;
}
2003-08-12 05:54:26 +04:00
token = base64_decode_data_blob ( buf + 3 ) ;
2010-09-16 12:22:00 +04:00
if ( ( token . length > = 7 )
& & ( strncmp ( ( char * ) token . data , " NTLMSSP " , 7 ) = = 0 ) ) {
char * reply ;
2010-12-01 07:50:59 +03:00
data_blob_free ( & token ) ;
2010-09-16 12:22:00 +04:00
DEBUG ( 10 , ( " Could not parse GSS-SPNEGO, trying raw "
" ntlmssp \n " ) ) ;
manage_squid_ntlmssp_request_int ( state , buf , length ,
talloc_tos ( ) , & reply ) ;
if ( reply = = NULL ) {
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
return ;
}
if ( strncmp ( reply , " AF " , 3 ) = = 0 ) {
x_fprintf ( x_stdout , " AF * %s \n " , reply + 3 ) ;
} else {
x_fprintf ( x_stdout , " %s * \n " , reply ) ;
}
TALLOC_FREE ( reply ) ;
return ;
}
2010-12-02 02:39:23 +03:00
ZERO_STRUCT ( request ) ;
2009-09-17 02:21:01 +04:00
len = spnego_read_data ( ctx , token , & request ) ;
2003-08-12 05:54:26 +04:00
data_blob_free ( & token ) ;
2003-07-29 19:00:38 +04:00
if ( len = = - 1 ) {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " GSS-SPNEGO query [%s] invalid \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH GSS-SPNEGO query invalid \n " ) ;
2003-07-29 19:00:38 +04:00
return ;
}
2003-08-12 05:54:26 +04:00
if ( request . type = = SPNEGO_NEG_TOKEN_INIT ) {
2010-12-02 02:39:23 +03:00
# ifdef HAVE_KRB5
int krb5_idx = - 1 ;
# endif
int ntlm_idx = - 1 ;
int used_idx = - 1 ;
int i ;
if ( state - > spnego_mech ) {
DEBUG ( 1 , ( " Client restarted SPNEGO with NegTokenInit "
" while mech[%s] was already negotiated \n " ,
state - > spnego_mech ) ) ;
x_fprintf ( x_stdout , " BH Client send NegTokenInit twice \n " ) ;
return ;
}
2003-07-29 19:00:38 +04:00
/* Second request from Client. This is where the
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
client offers its mechanism to use . */
2003-07-29 19:00:38 +04:00
2003-08-12 05:54:26 +04:00
if ( ( request . negTokenInit . mechTypes = = NULL ) | |
( request . negTokenInit . mechTypes [ 0 ] = = NULL ) ) {
2010-09-15 12:29:44 +04:00
DEBUG ( 1 , ( " Client did not offer any mechanism \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Client did not offer any "
" mechanism \n " ) ;
2003-07-29 19:00:38 +04:00
return ;
}
2005-09-30 21:13:37 +04:00
status = NT_STATUS_UNSUCCESSFUL ;
2010-12-02 02:39:23 +03:00
for ( i = 0 ; request . negTokenInit . mechTypes [ i ] ! = NULL ; i + + ) {
DEBUG ( 10 , ( " got mech[%d][%s] \n " ,
i , request . negTokenInit . mechTypes [ i ] ) ) ;
# ifdef HAVE_KRB5
if ( strcmp ( request . negTokenInit . mechTypes [ i ] , OID_KERBEROS5_OLD ) = = 0 ) {
krb5_idx = i ;
break ;
}
if ( strcmp ( request . negTokenInit . mechTypes [ i ] , OID_KERBEROS5 ) = = 0 ) {
krb5_idx = i ;
break ;
}
# endif
if ( strcmp ( request . negTokenInit . mechTypes [ i ] , OID_NTLMSSP ) = = 0 ) {
ntlm_idx = i ;
break ;
}
}
2003-08-12 23:00:08 +04:00
2010-12-02 02:39:23 +03:00
used_idx = ntlm_idx ;
# ifdef HAVE_KRB5
if ( krb5_idx ! = - 1 ) {
ntlm_idx = - 1 ;
used_idx = krb5_idx ;
}
# endif
if ( ntlm_idx > - 1 ) {
state - > spnego_mech = talloc_strdup ( state , " ntlmssp " ) ;
if ( state - > spnego_mech = = NULL ) {
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
2003-08-12 23:00:08 +04:00
return ;
}
2010-12-02 02:39:23 +03:00
if ( state - > ntlmssp_state ) {
2003-08-12 23:00:08 +04:00
DEBUG ( 1 , ( " Client wants a new NTLMSSP challenge, but "
" already got one \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Client wants a new "
" NTLMSSP challenge, but "
" already got one \n " ) ;
2010-12-02 02:39:23 +03:00
TALLOC_FREE ( state - > ntlmssp_state ) ;
2003-08-12 23:00:08 +04:00
return ;
}
2010-12-02 02:39:23 +03:00
status = ntlm_auth_start_ntlmssp_server ( & state - > ntlmssp_state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2003-12-30 10:33:58 +03:00
x_fprintf ( x_stdout , " BH %s \n " , nt_errstr ( status ) ) ;
return ;
}
2003-07-29 19:00:38 +04:00
}
2003-08-15 06:57:59 +04:00
# ifdef HAVE_KRB5
2010-12-02 02:39:23 +03:00
if ( krb5_idx > - 1 ) {
state - > spnego_mech = talloc_strdup ( state , " krb5 " ) ;
if ( state - > spnego_mech = = NULL ) {
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
2003-08-15 06:57:59 +04:00
return ;
}
2010-12-02 02:39:23 +03:00
}
# endif
if ( used_idx > - 1 ) {
state - > spnego_mech_oid = talloc_strdup ( state ,
request . negTokenInit . mechTypes [ used_idx ] ) ;
if ( state - > spnego_mech_oid = = NULL ) {
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
2010-09-16 12:34:59 +04:00
return ;
}
2010-12-02 02:39:23 +03:00
supportedMech = talloc_strdup ( ctx , state - > spnego_mech_oid ) ;
if ( supportedMech = = NULL ) {
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
return ;
2003-08-15 06:57:59 +04:00
}
2009-03-18 08:23:27 +03:00
2010-12-02 02:39:23 +03:00
status = NT_STATUS_MORE_PROCESSING_REQUIRED ;
} else {
status = NT_STATUS_NOT_SUPPORTED ;
}
if ( used_idx = = 0 ) {
status = NT_STATUS_OK ;
raw_in_token = request . negTokenInit . mechToken ;
2003-08-15 06:57:59 +04:00
}
2003-07-29 19:00:38 +04:00
} else {
2010-12-02 02:39:23 +03:00
if ( state - > spnego_mech = = NULL ) {
DEBUG ( 1 , ( " Got netTokenTarg without negTokenInit \n " ) ) ;
x_fprintf ( x_stdout , " BH Got a negTokenTarg without "
" negTokenInit \n " ) ;
return ;
}
2003-07-29 19:00:38 +04:00
2010-12-02 02:39:23 +03:00
if ( ( request . negTokenTarg . supportedMech ! = NULL ) & &
( strcmp ( request . negTokenTarg . supportedMech , state - > spnego_mech_oid ) ! = 0 ) ) {
DEBUG ( 1 , ( " Got a negTokenTarg with mech[%s] while [%s] was already negotiated \n " ,
request . negTokenTarg . supportedMech ,
state - > spnego_mech_oid ) ) ;
x_fprintf ( x_stdout , " BH Got a negTokenTarg with speficied mech \n " ) ;
2003-08-13 00:50:56 +04:00
return ;
}
2003-07-29 19:00:38 +04:00
2010-12-02 02:39:23 +03:00
status = NT_STATUS_OK ;
raw_in_token = request . negTokenTarg . responseToken ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* error or more processing */
} else if ( strcmp ( state - > spnego_mech , " ntlmssp " ) = = 0 ) {
DEBUG ( 10 , ( " got NTLMSSP packet: \n " ) ) ;
dump_data ( 10 , raw_in_token . data , raw_in_token . length ) ;
status = ntlmssp_update ( state - > ntlmssp_state ,
raw_in_token ,
& raw_out_token ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
user = talloc_strdup ( ctx , state - > ntlmssp_state - > user ) ;
domain = talloc_strdup ( ctx , state - > ntlmssp_state - > domain ) ;
}
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
TALLOC_FREE ( state - > ntlmssp_state ) ;
}
# ifdef HAVE_KRB5
} else if ( strcmp ( state - > spnego_mech , " krb5 " ) = = 0 ) {
char * principal ;
DATA_BLOB ap_rep ;
DATA_BLOB session_key ;
struct PAC_LOGON_INFO * logon_info = NULL ;
DATA_BLOB ticket ;
uint8_t tok_id [ 2 ] ;
if ( ! spnego_parse_krb5_wrap ( ctx , raw_in_token ,
& ticket , tok_id ) ) {
DEBUG ( 1 , ( " spnego_parse_krb5_wrap failed \n " ) ) ;
x_fprintf ( x_stdout , " BH spnego_parse_krb5_wrap failed \n " ) ;
2003-07-29 19:00:38 +04:00
return ;
}
2010-12-02 02:39:23 +03:00
status = ads_verify_ticket ( ctx , lp_realm ( ) , 0 ,
& ticket ,
& principal , & logon_info , & ap_rep ,
& session_key , True ) ;
2003-08-12 23:00:08 +04:00
2010-12-02 02:39:23 +03:00
/* Now in "principal" we have the name we are authenticated as. */
2003-08-13 00:50:56 +04:00
2003-08-12 23:00:08 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2010-12-02 02:39:23 +03:00
domain = strchr_m ( principal , ' @ ' ) ;
if ( domain = = NULL ) {
DEBUG ( 1 , ( " Did not get a valid principal "
" from ads_verify_ticket \n " ) ) ;
x_fprintf ( x_stdout , " BH Did not get a "
" valid principal from "
" ads_verify_ticket \n " ) ;
return ;
}
* domain + + = ' \0 ' ;
domain = talloc_strdup ( ctx , domain ) ;
user = talloc_strdup ( ctx , principal ) ;
if ( logon_info ) {
netsamlogon_cache_store (
user , & logon_info - > info3 ) ;
}
data_blob_free ( & ap_rep ) ;
data_blob_free ( & session_key ) ;
2003-08-12 23:00:08 +04:00
}
2010-12-02 02:39:23 +03:00
data_blob_free ( & ticket ) ;
# endif
2003-08-12 05:54:26 +04:00
}
2003-07-29 19:00:38 +04:00
2009-09-17 02:21:01 +04:00
spnego_free_data ( & request ) ;
2010-12-02 02:39:23 +03:00
ZERO_STRUCT ( response ) ;
response . type = SPNEGO_NEG_TOKEN_TARG ;
2003-07-29 19:00:38 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2010-12-02 02:39:23 +03:00
TALLOC_FREE ( state - > spnego_mech ) ;
TALLOC_FREE ( state - > spnego_mech_oid ) ;
2003-08-12 05:54:26 +04:00
response . negTokenTarg . negResult = SPNEGO_ACCEPT_COMPLETED ;
2010-12-02 02:39:23 +03:00
response . negTokenTarg . responseToken = raw_out_token ;
2003-08-01 11:59:23 +04:00
reply_code = " AF " ;
2007-12-04 05:48:41 +03:00
reply_argument = talloc_asprintf ( ctx , " %s \\ %s " , domain , user ) ;
2003-08-01 11:59:23 +04:00
} else if ( NT_STATUS_EQUAL ( status ,
NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
2010-12-02 02:39:23 +03:00
response . negTokenTarg . supportedMech = supportedMech ;
response . negTokenTarg . responseToken = raw_out_token ;
2003-08-12 05:54:26 +04:00
response . negTokenTarg . negResult = SPNEGO_ACCEPT_INCOMPLETE ;
2003-08-01 11:59:23 +04:00
reply_code = " TT " ;
2007-12-04 05:48:41 +03:00
reply_argument = talloc_strdup ( ctx , " * " ) ;
2003-08-01 11:59:23 +04:00
} else {
2010-12-02 02:39:23 +03:00
TALLOC_FREE ( state - > spnego_mech ) ;
TALLOC_FREE ( state - > spnego_mech_oid ) ;
data_blob_free ( & raw_out_token ) ;
2003-08-12 05:54:26 +04:00
response . negTokenTarg . negResult = SPNEGO_REJECT ;
2003-08-01 11:59:23 +04:00
reply_code = " NA " ;
2007-12-04 05:48:41 +03:00
reply_argument = talloc_strdup ( ctx , nt_errstr ( status ) ) ;
}
if ( ! reply_argument ) {
DEBUG ( 1 , ( " Could not write SPNEGO data blob \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Could not write SPNEGO data blob \n " ) ;
2010-12-02 02:39:23 +03:00
spnego_free_data ( & response ) ;
2007-12-04 05:48:41 +03:00
return ;
2003-07-29 19:00:38 +04:00
}
2009-09-17 02:21:01 +04:00
len = spnego_write_data ( ctx , & token , & response ) ;
spnego_free_data ( & response ) ;
2003-07-29 19:00:38 +04:00
if ( len = = - 1 ) {
DEBUG ( 1 , ( " Could not write SPNEGO data blob \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Could not write SPNEGO data blob \n " ) ;
2003-07-29 19:00:38 +04:00
return ;
}
2008-01-19 04:12:35 +03:00
reply_base64 = base64_encode_data_blob ( talloc_tos ( ) , token ) ;
2003-08-01 11:59:23 +04:00
x_fprintf ( x_stdout , " %s %s %s \n " ,
reply_code , reply_base64 , reply_argument ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( reply_base64 ) ;
2003-07-29 19:00:38 +04:00
data_blob_free ( & token ) ;
return ;
}
2009-12-22 10:50:55 +03:00
static struct ntlmssp_state * client_ntlmssp_state = NULL ;
2003-08-01 11:59:23 +04:00
2009-09-17 02:21:01 +04:00
static bool manage_client_ntlmssp_init ( struct spnego_data spnego )
2003-08-01 11:59:23 +04:00
{
NTSTATUS status ;
2007-05-14 16:16:20 +04:00
DATA_BLOB null_blob = data_blob_null ;
2003-08-01 11:59:23 +04:00
DATA_BLOB to_server ;
char * to_server_base64 ;
const char * my_mechs [ ] = { OID_NTLMSSP , NULL } ;
2009-09-17 02:21:01 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-08-01 11:59:23 +04:00
DEBUG ( 10 , ( " Got spnego negTokenInit with NTLMSSP \n " ) ) ;
if ( client_ntlmssp_state ! = NULL ) {
DEBUG ( 1 , ( " Request for initial SPNEGO request where "
" we already have a state \n " ) ) ;
2003-08-04 17:10:43 +04:00
return False ;
2003-08-01 11:59:23 +04:00
}
2003-12-30 10:33:58 +03:00
if ( ! client_ntlmssp_state ) {
if ( ! NT_STATUS_IS_OK ( status = ntlm_auth_start_ntlmssp_client ( & client_ntlmssp_state ) ) ) {
x_fprintf ( x_stdout , " BH %s \n " , nt_errstr ( status ) ) ;
return False ;
}
2003-08-01 11:59:23 +04:00
}
2003-12-30 10:33:58 +03:00
2003-08-01 11:59:23 +04:00
if ( opt_password = = NULL ) {
/* Request a password from the calling process. After
sending it , the calling process should retry with
the negTokenInit . */
DEBUG ( 10 , ( " Requesting password \n " ) ) ;
x_fprintf ( x_stdout , " PW \n " ) ;
2003-08-04 17:10:43 +04:00
return True ;
2003-08-01 11:59:23 +04:00
}
spnego . type = SPNEGO_NEG_TOKEN_INIT ;
2005-10-18 07:24:00 +04:00
spnego . negTokenInit . mechTypes = my_mechs ;
2009-08-13 10:12:01 +04:00
spnego . negTokenInit . reqFlags = data_blob_null ;
spnego . negTokenInit . reqFlagsPadding = 0 ;
2003-08-01 11:59:23 +04:00
spnego . negTokenInit . mechListMIC = null_blob ;
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
status = ntlmssp_update ( client_ntlmssp_state , null_blob ,
2003-08-01 11:59:23 +04:00
& spnego . negTokenInit . mechToken ) ;
2005-09-30 21:13:37 +04:00
if ( ! ( NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) | |
NT_STATUS_IS_OK ( status ) ) ) {
DEBUG ( 1 , ( " Expected OK or MORE_PROCESSING_REQUIRED, got: %s \n " ,
2003-08-01 11:59:23 +04:00
nt_errstr ( status ) ) ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( client_ntlmssp_state ) ;
2003-08-04 17:10:43 +04:00
return False ;
2003-08-01 11:59:23 +04:00
}
2009-09-17 02:21:01 +04:00
spnego_write_data ( ctx , & to_server , & spnego ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & spnego . negTokenInit . mechToken ) ;
2008-01-19 04:12:35 +03:00
to_server_base64 = base64_encode_data_blob ( talloc_tos ( ) , to_server ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & to_server ) ;
x_fprintf ( x_stdout , " KK %s \n " , to_server_base64 ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( to_server_base64 ) ;
2003-08-04 17:10:43 +04:00
return True ;
2003-08-01 11:59:23 +04:00
}
2009-09-17 02:21:01 +04:00
static void manage_client_ntlmssp_targ ( struct spnego_data spnego )
2003-08-01 11:59:23 +04:00
{
NTSTATUS status ;
2007-05-14 16:16:20 +04:00
DATA_BLOB null_blob = data_blob_null ;
2003-08-01 11:59:23 +04:00
DATA_BLOB request ;
DATA_BLOB to_server ;
char * to_server_base64 ;
2009-09-17 02:21:01 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-08-01 11:59:23 +04:00
DEBUG ( 10 , ( " Got spnego negTokenTarg with NTLMSSP \n " ) ) ;
if ( client_ntlmssp_state = = NULL ) {
DEBUG ( 1 , ( " Got NTLMSSP tArg without a client state \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Got NTLMSSP tArg without a client state \n " ) ;
2003-08-01 11:59:23 +04:00
return ;
}
if ( spnego . negTokenTarg . negResult = = SPNEGO_REJECT ) {
x_fprintf ( x_stdout , " NA \n " ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( client_ntlmssp_state ) ;
2003-08-01 11:59:23 +04:00
return ;
}
if ( spnego . negTokenTarg . negResult = = SPNEGO_ACCEPT_COMPLETED ) {
x_fprintf ( x_stdout , " AF \n " ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( client_ntlmssp_state ) ;
2003-08-01 11:59:23 +04:00
return ;
}
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
status = ntlmssp_update ( client_ntlmssp_state ,
2003-08-01 11:59:23 +04:00
spnego . negTokenTarg . responseToken ,
& request ) ;
2010-01-09 22:26:46 +03:00
2003-08-01 11:59:23 +04:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
DEBUG ( 1 , ( " Expected MORE_PROCESSING_REQUIRED from "
" ntlmssp_client_update, got: %s \n " ,
nt_errstr ( status ) ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Expected MORE_PROCESSING_REQUIRED from "
" ntlmssp_client_update \n " ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & request ) ;
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( client_ntlmssp_state ) ;
2003-08-01 11:59:23 +04:00
return ;
}
spnego . type = SPNEGO_NEG_TOKEN_TARG ;
spnego . negTokenTarg . negResult = SPNEGO_ACCEPT_INCOMPLETE ;
2005-09-30 21:13:37 +04:00
spnego . negTokenTarg . supportedMech = ( char * ) OID_NTLMSSP ;
2003-08-01 11:59:23 +04:00
spnego . negTokenTarg . responseToken = request ;
spnego . negTokenTarg . mechListMIC = null_blob ;
2010-01-09 22:26:46 +03:00
2009-09-17 02:21:01 +04:00
spnego_write_data ( ctx , & to_server , & spnego ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & request ) ;
2008-01-19 04:12:35 +03:00
to_server_base64 = base64_encode_data_blob ( talloc_tos ( ) , to_server ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & to_server ) ;
x_fprintf ( x_stdout , " KK %s \n " , to_server_base64 ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( to_server_base64 ) ;
2003-08-01 11:59:23 +04:00
return ;
}
2003-08-14 21:21:22 +04:00
# ifdef HAVE_KRB5
2009-09-17 02:21:01 +04:00
static bool manage_client_krb5_init ( struct spnego_data spnego )
2003-08-01 11:59:23 +04:00
{
2003-08-13 00:50:56 +04:00
char * principal ;
DATA_BLOB tkt , to_server ;
2007-05-14 16:16:20 +04:00
DATA_BLOB session_key_krb5 = data_blob_null ;
2009-09-17 02:21:01 +04:00
struct spnego_data reply ;
2003-08-13 00:50:56 +04:00
char * reply_base64 ;
2004-01-08 11:19:18 +03:00
int retval ;
2007-12-04 05:48:41 +03:00
2003-08-13 00:50:56 +04:00
const char * my_mechs [ ] = { OID_KERBEROS5_OLD , NULL } ;
ssize_t len ;
2009-09-17 02:21:01 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-08-13 00:50:56 +04:00
if ( ( spnego . negTokenInit . mechListMIC . data = = NULL ) | |
( spnego . negTokenInit . mechListMIC . length = = 0 ) ) {
DEBUG ( 1 , ( " Did not get a principal for krb5 \n " ) ) ;
return False ;
}
2006-08-08 00:15:31 +04:00
principal = ( char * ) SMB_MALLOC (
spnego . negTokenInit . mechListMIC . length + 1 ) ;
2003-08-13 00:50:56 +04:00
if ( principal = = NULL ) {
DEBUG ( 1 , ( " Could not malloc principal \n " ) ) ;
return False ;
}
memcpy ( principal , spnego . negTokenInit . mechListMIC . data ,
spnego . negTokenInit . mechListMIC . length ) ;
principal [ spnego . negTokenInit . mechListMIC . length ] = ' \0 ' ;
2010-07-21 04:00:12 +04:00
retval = cli_krb5_get_ticket ( ctx , principal , 0 ,
& tkt , & session_key_krb5 ,
0 , NULL , NULL , NULL ) ;
2004-01-08 11:19:18 +03:00
if ( retval ) {
2007-12-04 05:48:41 +03:00
char * user = NULL ;
2003-08-13 00:50:56 +04:00
/* Let's try to first get the TGT, for that we need a
password . */
if ( opt_password = = NULL ) {
DEBUG ( 10 , ( " Requesting password \n " ) ) ;
x_fprintf ( x_stdout , " PW \n " ) ;
return True ;
}
2007-12-04 05:48:41 +03:00
user = talloc_asprintf ( talloc_tos ( ) , " %s@%s " , opt_username , opt_domain ) ;
if ( ! user ) {
return false ;
}
2003-08-13 00:50:56 +04:00
2006-03-20 22:05:44 +03:00
if ( ( retval = kerberos_kinit_password ( user , opt_password , 0 , NULL ) ) ) {
2004-01-08 11:19:18 +03:00
DEBUG ( 10 , ( " Requesting TGT failed: %s \n " , error_message ( retval ) ) ) ;
2004-06-14 07:22:52 +04:00
return False ;
2003-08-13 00:50:56 +04:00
}
2010-07-21 04:00:12 +04:00
retval = cli_krb5_get_ticket ( ctx , principal , 0 ,
& tkt , & session_key_krb5 ,
0 , NULL , NULL , NULL ) ;
2004-01-08 11:19:18 +03:00
if ( retval ) {
DEBUG ( 10 , ( " Kinit suceeded, but getting a ticket failed: %s \n " , error_message ( retval ) ) ) ;
2004-06-14 07:22:52 +04:00
return False ;
2004-01-08 11:19:18 +03:00
}
2003-08-13 00:50:56 +04:00
}
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
data_blob_free ( & session_key_krb5 ) ;
2003-08-13 00:50:56 +04:00
ZERO_STRUCT ( reply ) ;
reply . type = SPNEGO_NEG_TOKEN_INIT ;
reply . negTokenInit . mechTypes = my_mechs ;
2009-08-13 10:12:01 +04:00
reply . negTokenInit . reqFlags = data_blob_null ;
reply . negTokenInit . reqFlagsPadding = 0 ;
2003-08-13 00:50:56 +04:00
reply . negTokenInit . mechToken = tkt ;
2007-05-14 16:16:20 +04:00
reply . negTokenInit . mechListMIC = data_blob_null ;
2003-08-13 00:50:56 +04:00
2009-09-17 02:21:01 +04:00
len = spnego_write_data ( ctx , & to_server , & reply ) ;
2003-08-13 00:50:56 +04:00
data_blob_free ( & tkt ) ;
if ( len = = - 1 ) {
DEBUG ( 1 , ( " Could not write SPNEGO data blob \n " ) ) ;
return False ;
}
2008-01-19 04:12:35 +03:00
reply_base64 = base64_encode_data_blob ( talloc_tos ( ) , to_server ) ;
2003-08-13 00:50:56 +04:00
x_fprintf ( x_stdout , " KK %s * \n " , reply_base64 ) ;
2007-10-28 21:15:08 +03:00
TALLOC_FREE ( reply_base64 ) ;
2003-08-13 00:50:56 +04:00
data_blob_free ( & to_server ) ;
DEBUG ( 10 , ( " sent GSS-SPNEGO KERBEROS5 negTokenInit \n " ) ) ;
return True ;
2003-08-01 11:59:23 +04:00
}
2009-09-17 02:21:01 +04:00
static void manage_client_krb5_targ ( struct spnego_data spnego )
2003-08-01 11:59:23 +04:00
{
2003-08-13 00:50:56 +04:00
switch ( spnego . negTokenTarg . negResult ) {
case SPNEGO_ACCEPT_INCOMPLETE :
DEBUG ( 1 , ( " Got a Kerberos negTokenTarg with ACCEPT_INCOMPLETE \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Got a Kerberos negTokenTarg with "
" ACCEPT_INCOMPLETE \n " ) ;
2003-08-13 00:50:56 +04:00
break ;
case SPNEGO_ACCEPT_COMPLETED :
DEBUG ( 10 , ( " Accept completed \n " ) ) ;
x_fprintf ( x_stdout , " AF \n " ) ;
break ;
case SPNEGO_REJECT :
DEBUG ( 10 , ( " Rejected \n " ) ) ;
x_fprintf ( x_stdout , " NA \n " ) ;
break ;
default :
DEBUG ( 1 , ( " Got an invalid negTokenTarg \n " ) ) ;
x_fprintf ( x_stdout , " AF \n " ) ;
}
2003-08-01 11:59:23 +04:00
}
2003-08-14 21:21:22 +04:00
# endif
2008-01-18 12:37:16 +03:00
static void manage_gss_spnego_client_request ( struct ntlm_auth_state * state ,
char * buf , int length )
2003-08-01 11:59:23 +04:00
{
DATA_BLOB request ;
2009-09-17 02:21:01 +04:00
struct spnego_data spnego ;
2003-08-01 11:59:23 +04:00
ssize_t len ;
2009-09-17 02:21:01 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2003-08-01 11:59:23 +04:00
2006-09-01 08:41:03 +04:00
if ( ! opt_username | | ! * opt_username ) {
x_fprintf ( x_stderr , " username must be specified! \n \n " ) ;
exit ( 1 ) ;
}
2003-08-01 11:59:23 +04:00
if ( strlen ( buf ) < = 3 ) {
DEBUG ( 1 , ( " SPNEGO query [%s] too short \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH SPNEGO query too short \n " ) ;
2003-08-01 11:59:23 +04:00
return ;
}
request = base64_decode_data_blob ( buf + 3 ) ;
if ( strncmp ( buf , " PW " , 3 ) = = 0 ) {
/* We asked for a password and obviously got it :-) */
2004-12-07 21:25:53 +03:00
opt_password = SMB_STRNDUP ( ( const char * ) request . data , request . length ) ;
2010-01-09 22:26:46 +03:00
2003-08-01 11:59:23 +04:00
if ( opt_password = = NULL ) {
DEBUG ( 1 , ( " Out of memory \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Out of memory \n " ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & request ) ;
return ;
}
x_fprintf ( x_stdout , " OK \n " ) ;
data_blob_free ( & request ) ;
return ;
}
if ( ( strncmp ( buf , " TT " , 3 ) ! = 0 ) & &
( strncmp ( buf , " AF " , 3 ) ! = 0 ) & &
( strncmp ( buf , " NA " , 3 ) ! = 0 ) ) {
DEBUG ( 1 , ( " SPNEGO request [%s] invalid \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH SPNEGO request invalid \n " ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & request ) ;
return ;
}
/* So we got a server challenge to generate a SPNEGO
client - to - server request . . . */
2009-09-17 02:21:01 +04:00
len = spnego_read_data ( ctx , request , & spnego ) ;
2003-08-01 11:59:23 +04:00
data_blob_free ( & request ) ;
if ( len = = - 1 ) {
DEBUG ( 1 , ( " Could not read SPNEGO data for [%s] \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Could not read SPNEGO data \n " ) ;
2003-08-01 11:59:23 +04:00
return ;
}
if ( spnego . type = = SPNEGO_NEG_TOKEN_INIT ) {
/* The server offers a list of mechanisms */
2005-09-30 21:13:37 +04:00
const char * * mechType = ( const char * * ) spnego . negTokenInit . mechTypes ;
2003-08-01 11:59:23 +04:00
while ( * mechType ! = NULL ) {
2003-08-14 21:21:22 +04:00
# ifdef HAVE_KRB5
2003-08-04 17:10:43 +04:00
if ( ( strcmp ( * mechType , OID_KERBEROS5_OLD ) = = 0 ) | |
( strcmp ( * mechType , OID_KERBEROS5 ) = = 0 ) ) {
if ( manage_client_krb5_init ( spnego ) )
goto out ;
2003-08-01 11:59:23 +04:00
}
2003-08-14 21:21:22 +04:00
# endif
2003-08-01 11:59:23 +04:00
2003-08-04 17:10:43 +04:00
if ( strcmp ( * mechType , OID_NTLMSSP ) = = 0 ) {
if ( manage_client_ntlmssp_init ( spnego ) )
goto out ;
2003-08-01 11:59:23 +04:00
}
mechType + + ;
}
DEBUG ( 1 , ( " Server offered no compatible mechanism \n " ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Server offered no compatible mechanism \n " ) ;
2003-08-01 11:59:23 +04:00
return ;
}
if ( spnego . type = = SPNEGO_NEG_TOKEN_TARG ) {
2003-08-04 17:10:43 +04:00
if ( spnego . negTokenTarg . supportedMech = = NULL ) {
/* On accept/reject Windows does not send the
mechanism anymore . Handle that here and
shut down the mechanisms . */
switch ( spnego . negTokenTarg . negResult ) {
case SPNEGO_ACCEPT_COMPLETED :
x_fprintf ( x_stdout , " AF \n " ) ;
break ;
case SPNEGO_REJECT :
x_fprintf ( x_stdout , " NA \n " ) ;
break ;
default :
DEBUG ( 1 , ( " Got a negTokenTarg with no mech and an "
" unknown negResult: %d \n " ,
spnego . negTokenTarg . negResult ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Got a negTokenTarg with "
" no mech and an unknown "
" negResult \n " ) ;
2003-08-04 17:10:43 +04:00
}
2010-07-17 01:30:14 +04:00
TALLOC_FREE ( client_ntlmssp_state ) ;
2003-08-04 17:10:43 +04:00
goto out ;
}
2003-08-01 11:59:23 +04:00
if ( strcmp ( spnego . negTokenTarg . supportedMech ,
OID_NTLMSSP ) = = 0 ) {
manage_client_ntlmssp_targ ( spnego ) ;
goto out ;
}
2003-08-14 21:21:22 +04:00
# if HAVE_KRB5
2003-08-01 11:59:23 +04:00
if ( strcmp ( spnego . negTokenTarg . supportedMech ,
OID_KERBEROS5_OLD ) = = 0 ) {
manage_client_krb5_targ ( spnego ) ;
goto out ;
}
2003-08-14 21:21:22 +04:00
# endif
2003-08-01 11:59:23 +04:00
}
DEBUG ( 1 , ( " Got an SPNEGO token I could not handle [%s]! \n " , buf ) ) ;
2008-03-20 01:32:38 +03:00
x_fprintf ( x_stdout , " BH Got an SPNEGO token I could not handle \n " ) ;
2003-08-01 11:59:23 +04:00
return ;
out :
2009-09-17 02:21:01 +04:00
spnego_free_data ( & spnego ) ;
2003-08-01 11:59:23 +04:00
return ;
}
2008-01-18 12:37:16 +03:00
static void manage_ntlm_server_1_request ( struct ntlm_auth_state * state ,
char * buf , int length )
2004-04-13 00:46:13 +04:00
{
char * request , * parameter ;
static DATA_BLOB challenge ;
static DATA_BLOB lm_response ;
static DATA_BLOB nt_response ;
static char * full_username ;
static char * username ;
static char * domain ;
static char * plaintext_password ;
2007-10-19 04:40:25 +04:00
static bool ntlm_server_1_user_session_key ;
static bool ntlm_server_1_lm_session_key ;
2010-01-09 22:26:46 +03:00
2004-04-13 00:46:13 +04:00
if ( strequal ( buf , " . " ) ) {
if ( ! full_username & & ! username ) {
x_fprintf ( x_stdout , " Error: No username supplied! \n " ) ;
} else if ( plaintext_password ) {
/* handle this request as plaintext */
if ( ! full_username ) {
if ( asprintf ( & full_username , " %s%c%s " , domain , winbind_separator ( ) , username ) = = - 1 ) {
x_fprintf ( x_stdout , " Error: Out of memory in asprintf! \n . \n " ) ;
return ;
}
}
if ( check_plaintext_auth ( full_username , plaintext_password , False ) ) {
x_fprintf ( x_stdout , " Authenticated: Yes \n " ) ;
} else {
x_fprintf ( x_stdout , " Authenticated: No \n " ) ;
}
2004-04-14 00:57:26 +04:00
} else if ( ! lm_response . data & & ! nt_response . data ) {
2004-04-13 00:46:13 +04:00
x_fprintf ( x_stdout , " Error: No password supplied! \n " ) ;
} else if ( ! challenge . data ) {
x_fprintf ( x_stdout , " Error: No lanman-challenge supplied! \n " ) ;
} else {
char * error_string = NULL ;
uchar lm_key [ 8 ] ;
uchar user_session_key [ 16 ] ;
uint32 flags = 0 ;
if ( full_username & & ! username ) {
fstring fstr_user ;
fstring fstr_domain ;
2010-01-09 22:26:46 +03:00
2004-04-13 00:46:13 +04:00
if ( ! parse_ntlm_auth_domain_user ( full_username , fstr_user , fstr_domain ) ) {
/* username might be 'tainted', don't print into our new-line deleimianted stream */
x_fprintf ( x_stdout , " Error: Could not parse into domain and username \n " ) ;
}
SAFE_FREE ( username ) ;
SAFE_FREE ( domain ) ;
username = smb_xstrdup ( fstr_user ) ;
domain = smb_xstrdup ( fstr_domain ) ;
}
if ( ! domain ) {
domain = smb_xstrdup ( get_winbind_domain ( ) ) ;
}
if ( ntlm_server_1_lm_session_key )
flags | = WBFLAG_PAM_LMKEY ;
2010-01-09 22:26:46 +03:00
2004-04-13 00:46:13 +04:00
if ( ntlm_server_1_user_session_key )
flags | = WBFLAG_PAM_USER_SESSION_KEY ;
if ( ! NT_STATUS_IS_OK (
contact_winbind_auth_crap ( username ,
domain ,
global_myname ( ) ,
& challenge ,
& lm_response ,
& nt_response ,
flags ,
lm_key ,
user_session_key ,
& error_string ,
NULL ) ) ) {
x_fprintf ( x_stdout , " Authenticated: No \n " ) ;
x_fprintf ( x_stdout , " Authentication-Error: %s \n . \n " , error_string ) ;
} else {
static char zeros [ 16 ] ;
char * hex_lm_key ;
char * hex_user_session_key ;
x_fprintf ( x_stdout , " Authenticated: Yes \n " ) ;
if ( ntlm_server_1_lm_session_key
& & ( memcmp ( zeros , lm_key ,
sizeof ( lm_key ) ) ! = 0 ) ) {
2008-10-18 18:16:57 +04:00
hex_lm_key = hex_encode_talloc ( NULL ,
2005-08-08 00:59:28 +04:00
( const unsigned char * ) lm_key ,
sizeof ( lm_key ) ) ;
2004-04-13 00:46:13 +04:00
x_fprintf ( x_stdout , " LANMAN-Session-Key: %s \n " , hex_lm_key ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( hex_lm_key ) ;
2004-04-13 00:46:13 +04:00
}
if ( ntlm_server_1_user_session_key
& & ( memcmp ( zeros , user_session_key ,
sizeof ( user_session_key ) ) ! = 0 ) ) {
2008-10-18 18:16:57 +04:00
hex_user_session_key = hex_encode_talloc ( NULL ,
2005-08-08 00:59:28 +04:00
( const unsigned char * ) user_session_key ,
sizeof ( user_session_key ) ) ;
2004-04-13 00:46:13 +04:00
x_fprintf ( x_stdout , " User-Session-Key: %s \n " , hex_user_session_key ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( hex_user_session_key ) ;
2004-04-13 00:46:13 +04:00
}
}
2009-02-13 12:08:37 +03:00
SAFE_FREE ( error_string ) ;
2004-04-13 00:46:13 +04:00
}
/* clear out the state */
2007-05-14 16:16:20 +04:00
challenge = data_blob_null ;
nt_response = data_blob_null ;
lm_response = data_blob_null ;
2004-04-13 00:46:13 +04:00
SAFE_FREE ( full_username ) ;
SAFE_FREE ( username ) ;
SAFE_FREE ( domain ) ;
SAFE_FREE ( plaintext_password ) ;
ntlm_server_1_user_session_key = False ;
ntlm_server_1_lm_session_key = False ;
x_fprintf ( x_stdout , " . \n " ) ;
return ;
}
request = buf ;
2004-04-14 00:57:26 +04:00
/* Indicates a base64 encoded structure */
parameter = strstr_m ( request , " :: " ) ;
2004-04-13 00:46:13 +04:00
if ( ! parameter ) {
2004-04-14 00:57:26 +04:00
parameter = strstr_m ( request , " : " ) ;
2010-01-09 22:26:46 +03:00
2004-04-13 00:46:13 +04:00
if ( ! parameter ) {
DEBUG ( 0 , ( " Parameter not found! \n " ) ) ;
x_fprintf ( x_stdout , " Error: Parameter not found! \n . \n " ) ;
return ;
}
2010-01-09 22:26:46 +03:00
2004-04-13 00:46:13 +04:00
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
} else {
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
2004-04-14 00:57:26 +04:00
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
base64_decode_inplace ( parameter ) ;
2004-04-13 00:46:13 +04:00
}
if ( strequal ( request , " LANMAN-Challenge " ) ) {
2005-08-08 00:59:28 +04:00
challenge = strhex_to_data_blob ( NULL , parameter ) ;
2004-04-13 00:46:13 +04:00
if ( challenge . length ! = 8 ) {
x_fprintf ( x_stdout , " Error: hex decode of %s failed! (got %d bytes, expected 8) \n . \n " ,
parameter ,
( int ) challenge . length ) ;
2007-05-14 16:16:20 +04:00
challenge = data_blob_null ;
2004-04-13 00:46:13 +04:00
}
} else if ( strequal ( request , " NT-Response " ) ) {
2005-08-08 00:59:28 +04:00
nt_response = strhex_to_data_blob ( NULL , parameter ) ;
2004-04-13 00:46:13 +04:00
if ( nt_response . length < 24 ) {
x_fprintf ( x_stdout , " Error: hex decode of %s failed! (only got %d bytes, needed at least 24) \n . \n " ,
parameter ,
2004-07-25 17:11:39 +04:00
( int ) nt_response . length ) ;
2007-05-14 16:16:20 +04:00
nt_response = data_blob_null ;
2004-04-13 00:46:13 +04:00
}
} else if ( strequal ( request , " LANMAN-Response " ) ) {
2005-08-08 00:59:28 +04:00
lm_response = strhex_to_data_blob ( NULL , parameter ) ;
2004-04-13 00:46:13 +04:00
if ( lm_response . length ! = 24 ) {
x_fprintf ( x_stdout , " Error: hex decode of %s failed! (got %d bytes, expected 24) \n . \n " ,
parameter ,
( int ) lm_response . length ) ;
2007-05-14 16:16:20 +04:00
lm_response = data_blob_null ;
2004-04-13 00:46:13 +04:00
}
} else if ( strequal ( request , " Password " ) ) {
plaintext_password = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " NT-Domain " ) ) {
domain = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " Username " ) ) {
username = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " Full-Username " ) ) {
full_username = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " Request-User-Session-Key " ) ) {
ntlm_server_1_user_session_key = strequal ( parameter , " Yes " ) ;
} else if ( strequal ( request , " Request-LanMan-Session-Key " ) ) {
ntlm_server_1_lm_session_key = strequal ( parameter , " Yes " ) ;
} else {
2004-04-13 12:58:02 +04:00
x_fprintf ( x_stdout , " Error: Unknown request %s \n . \n " , request ) ;
2004-04-13 00:46:13 +04:00
}
}
2008-01-18 12:37:16 +03:00
static void manage_ntlm_change_password_1_request ( struct ntlm_auth_state * state ,
char * buf , int length )
2006-07-13 13:29:25 +04:00
{
char * request , * parameter ;
static DATA_BLOB new_nt_pswd ;
static DATA_BLOB old_nt_hash_enc ;
static DATA_BLOB new_lm_pswd ;
static DATA_BLOB old_lm_hash_enc ;
static char * full_username = NULL ;
static char * username = NULL ;
static char * domain = NULL ;
static char * newpswd = NULL ;
static char * oldpswd = NULL ;
if ( strequal ( buf , " . " ) ) {
if ( newpswd & & oldpswd ) {
uchar old_nt_hash [ 16 ] ;
uchar old_lm_hash [ 16 ] ;
uchar new_nt_hash [ 16 ] ;
uchar new_lm_hash [ 16 ] ;
new_nt_pswd = data_blob ( NULL , 516 ) ;
old_nt_hash_enc = data_blob ( NULL , 16 ) ;
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
/* Calculate the MD4 hash (NT compatible) of the
* password */
E_md4hash ( oldpswd , old_nt_hash ) ;
E_md4hash ( newpswd , new_nt_hash ) ;
/* E_deshash returns false for 'long'
passwords ( > 14 DOS chars ) .
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
Therefore , don ' t send a buffer
encrypted with the truncated hash
( it could allow an even easier
attack on the password )
Likewise , obey the admin ' s restriction
*/
if ( lp_client_lanman_auth ( ) & &
E_deshash ( newpswd , new_lm_hash ) & &
E_deshash ( oldpswd , old_lm_hash ) ) {
new_lm_pswd = data_blob ( NULL , 516 ) ;
old_lm_hash_enc = data_blob ( NULL , 16 ) ;
encode_pw_buffer ( new_lm_pswd . data , newpswd ,
STR_UNICODE ) ;
2009-03-16 13:27:58 +03:00
arcfour_crypt ( new_lm_pswd . data , old_nt_hash , 516 ) ;
2006-07-13 13:29:25 +04:00
E_old_pw_hash ( new_nt_hash , old_lm_hash ,
old_lm_hash_enc . data ) ;
} else {
new_lm_pswd . data = NULL ;
new_lm_pswd . length = 0 ;
old_lm_hash_enc . data = NULL ;
old_lm_hash_enc . length = 0 ;
}
encode_pw_buffer ( new_nt_pswd . data , newpswd ,
STR_UNICODE ) ;
2010-01-09 22:26:46 +03:00
2009-03-16 13:27:58 +03:00
arcfour_crypt ( new_nt_pswd . data , old_nt_hash , 516 ) ;
2006-07-13 13:29:25 +04:00
E_old_pw_hash ( new_nt_hash , old_nt_hash ,
old_nt_hash_enc . data ) ;
}
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
if ( ! full_username & & ! username ) {
x_fprintf ( x_stdout , " Error: No username supplied! \n " ) ;
} else if ( ( ! new_nt_pswd . data | | ! old_nt_hash_enc . data ) & &
( ! new_lm_pswd . data | | old_lm_hash_enc . data ) ) {
x_fprintf ( x_stdout , " Error: No NT or LM password "
" blobs supplied! \n " ) ;
} else {
char * error_string = NULL ;
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
if ( full_username & & ! username ) {
fstring fstr_user ;
fstring fstr_domain ;
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
if ( ! parse_ntlm_auth_domain_user ( full_username ,
fstr_user ,
fstr_domain ) ) {
/* username might be 'tainted', don't
* print into our new - line
* deleimianted stream */
x_fprintf ( x_stdout , " Error: Could not "
" parse into domain and "
" username \n " ) ;
SAFE_FREE ( username ) ;
username = smb_xstrdup ( full_username ) ;
} else {
SAFE_FREE ( username ) ;
SAFE_FREE ( domain ) ;
username = smb_xstrdup ( fstr_user ) ;
domain = smb_xstrdup ( fstr_domain ) ;
}
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
}
if ( ! NT_STATUS_IS_OK ( contact_winbind_change_pswd_auth_crap (
username , domain ,
new_nt_pswd ,
old_nt_hash_enc ,
new_lm_pswd ,
old_lm_hash_enc ,
& error_string ) ) ) {
x_fprintf ( x_stdout , " Password-Change: No \n " ) ;
x_fprintf ( x_stdout , " Password-Change-Error: "
" %s \n . \n " , error_string ) ;
} else {
x_fprintf ( x_stdout , " Password-Change: Yes \n " ) ;
}
SAFE_FREE ( error_string ) ;
}
/* clear out the state */
2007-05-14 16:16:20 +04:00
new_nt_pswd = data_blob_null ;
old_nt_hash_enc = data_blob_null ;
new_lm_pswd = data_blob_null ;
old_nt_hash_enc = data_blob_null ;
2006-07-13 13:29:25 +04:00
SAFE_FREE ( full_username ) ;
SAFE_FREE ( username ) ;
SAFE_FREE ( domain ) ;
SAFE_FREE ( newpswd ) ;
SAFE_FREE ( oldpswd ) ;
x_fprintf ( x_stdout , " . \n " ) ;
return ;
}
request = buf ;
/* Indicates a base64 encoded structure */
parameter = strstr_m ( request , " :: " ) ;
if ( ! parameter ) {
parameter = strstr_m ( request , " : " ) ;
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
if ( ! parameter ) {
DEBUG ( 0 , ( " Parameter not found! \n " ) ) ;
x_fprintf ( x_stdout , " Error: Parameter not found! \n . \n " ) ;
return ;
}
2010-01-09 22:26:46 +03:00
2006-07-13 13:29:25 +04:00
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
} else {
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
parameter [ 0 ] = ' \0 ' ;
parameter + + ;
base64_decode_inplace ( parameter ) ;
}
if ( strequal ( request , " new-nt-password-blob " ) ) {
new_nt_pswd = strhex_to_data_blob ( NULL , parameter ) ;
if ( new_nt_pswd . length ! = 516 ) {
x_fprintf ( x_stdout , " Error: hex decode of %s failed! "
" (got %d bytes, expected 516) \n . \n " ,
parameter ,
( int ) new_nt_pswd . length ) ;
2007-05-14 16:16:20 +04:00
new_nt_pswd = data_blob_null ;
2006-07-13 13:29:25 +04:00
}
} else if ( strequal ( request , " old-nt-hash-blob " ) ) {
old_nt_hash_enc = strhex_to_data_blob ( NULL , parameter ) ;
if ( old_nt_hash_enc . length ! = 16 ) {
x_fprintf ( x_stdout , " Error: hex decode of %s failed! "
" (got %d bytes, expected 16) \n . \n " ,
parameter ,
( int ) old_nt_hash_enc . length ) ;
2007-05-14 16:16:20 +04:00
old_nt_hash_enc = data_blob_null ;
2006-07-13 13:29:25 +04:00
}
} else if ( strequal ( request , " new-lm-password-blob " ) ) {
new_lm_pswd = strhex_to_data_blob ( NULL , parameter ) ;
if ( new_lm_pswd . length ! = 516 ) {
x_fprintf ( x_stdout , " Error: hex decode of %s failed! "
" (got %d bytes, expected 516) \n . \n " ,
parameter ,
( int ) new_lm_pswd . length ) ;
2007-05-14 16:16:20 +04:00
new_lm_pswd = data_blob_null ;
2006-07-13 13:29:25 +04:00
}
}
else if ( strequal ( request , " old-lm-hash-blob " ) ) {
old_lm_hash_enc = strhex_to_data_blob ( NULL , parameter ) ;
if ( old_lm_hash_enc . length ! = 16 )
{
x_fprintf ( x_stdout , " Error: hex decode of %s failed! "
" (got %d bytes, expected 16) \n . \n " ,
parameter ,
( int ) old_lm_hash_enc . length ) ;
2007-05-14 16:16:20 +04:00
old_lm_hash_enc = data_blob_null ;
2006-07-13 13:29:25 +04:00
}
} else if ( strequal ( request , " nt-domain " ) ) {
domain = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " username " ) ) {
username = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " full-username " ) ) {
username = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " new-password " ) ) {
newpswd = smb_xstrdup ( parameter ) ;
} else if ( strequal ( request , " old-password " ) ) {
oldpswd = smb_xstrdup ( parameter ) ;
} else {
x_fprintf ( x_stdout , " Error: Unknown request %s \n . \n " , request ) ;
}
}
2008-01-16 16:45:22 +03:00
static void manage_squid_request ( struct ntlm_auth_state * state ,
stdio_helper_function fn )
2002-11-24 11:32:03 +03:00
{
2008-01-16 11:52:26 +03:00
char * buf ;
char tmp [ INITIAL_BUFFER_SIZE + 1 ] ;
int length , buf_size = 0 ;
2003-01-16 06:29:54 +03:00
char * c ;
2003-03-24 12:54:13 +03:00
2008-01-16 16:45:22 +03:00
buf = talloc_strdup ( state - > mem_ctx , " " ) ;
2008-01-16 11:52:26 +03:00
if ( ! buf ) {
DEBUG ( 0 , ( " Failed to allocate input buffer. \n " ) ) ;
2002-11-24 11:32:03 +03:00
x_fprintf ( x_stderr , " ERR \n " ) ;
2008-01-16 11:52:26 +03:00
exit ( 1 ) ;
2002-11-24 11:32:03 +03:00
}
2008-01-16 11:52:26 +03:00
do {
/* this is not a typo - x_fgets doesn't work too well under
* squid */
if ( fgets ( tmp , sizeof ( tmp ) - 1 , stdin ) = = NULL ) {
if ( ferror ( stdin ) ) {
DEBUG ( 1 , ( " fgets() failed! dying..... errno=%d "
" (%s) \n " , ferror ( stdin ) ,
strerror ( ferror ( stdin ) ) ) ) ;
exit ( 1 ) ;
}
exit ( 0 ) ;
}
buf = talloc_strdup_append_buffer ( buf , tmp ) ;
buf_size + = INITIAL_BUFFER_SIZE ;
if ( buf_size > MAX_BUFFER_SIZE ) {
DEBUG ( 2 , ( " Oversized message \n " ) ) ;
x_fprintf ( x_stderr , " ERR \n " ) ;
talloc_free ( buf ) ;
return ;
}
c = strchr ( buf , ' \n ' ) ;
} while ( c = = NULL ) ;
* c = ' \0 ' ;
length = c - buf ;
2002-11-24 11:32:03 +03:00
DEBUG ( 10 , ( " Got '%s' from squid (length: %d). \n " , buf , length ) ) ;
if ( buf [ 0 ] = = ' \0 ' ) {
DEBUG ( 2 , ( " Invalid Request \n " ) ) ;
x_fprintf ( x_stderr , " ERR \n " ) ;
2008-01-16 11:52:26 +03:00
talloc_free ( buf ) ;
2002-11-24 11:32:03 +03:00
return ;
}
2008-01-16 11:52:26 +03:00
2008-01-18 12:37:16 +03:00
fn ( state , buf , length ) ;
2008-01-16 11:52:26 +03:00
talloc_free ( buf ) ;
2002-11-24 11:32:03 +03:00
}
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
static void squid_stream ( enum stdio_helper_mode stdio_mode , stdio_helper_function fn ) {
2008-01-16 16:45:22 +03:00
TALLOC_CTX * mem_ctx ;
struct ntlm_auth_state * state ;
2002-11-24 11:32:03 +03:00
/* initialize FDescs */
x_setbuf ( x_stdout , NULL ) ;
x_setbuf ( x_stderr , NULL ) ;
2008-01-16 16:45:22 +03:00
mem_ctx = talloc_init ( " ntlm_auth " ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " squid_stream: Failed to create talloc context \n " ) ) ;
x_fprintf ( x_stderr , " ERR \n " ) ;
exit ( 1 ) ;
}
2008-01-18 16:40:47 +03:00
state = talloc_zero ( mem_ctx , struct ntlm_auth_state ) ;
2008-01-16 16:45:22 +03:00
if ( ! state ) {
DEBUG ( 0 , ( " squid_stream: Failed to talloc ntlm_auth_state \n " ) ) ;
x_fprintf ( x_stderr , " ERR \n " ) ;
exit ( 1 ) ;
}
state - > mem_ctx = mem_ctx ;
state - > helper_mode = stdio_mode ;
2002-11-24 11:32:03 +03:00
while ( 1 ) {
2010-09-16 12:36:21 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-01-16 16:45:22 +03:00
manage_squid_request ( state , fn ) ;
2010-09-16 12:36:21 +04:00
TALLOC_FREE ( frame ) ;
2002-11-24 11:32:03 +03:00
}
}
/* Authenticate a user with a challenge/response */
2007-10-19 04:40:25 +04:00
static bool check_auth_crap ( void )
2002-11-24 11:32:03 +03:00
{
2003-04-07 11:10:53 +04:00
NTSTATUS nt_status ;
uint32 flags = 0 ;
char lm_key [ 8 ] ;
2004-04-12 14:17:48 +04:00
char user_session_key [ 16 ] ;
2003-04-07 11:10:53 +04:00
char * hex_lm_key ;
2004-04-12 14:17:48 +04:00
char * hex_user_session_key ;
2003-04-07 11:10:53 +04:00
char * error_string ;
2003-03-24 12:54:13 +03:00
static uint8 zeros [ 16 ] ;
2003-05-12 05:49:03 +04:00
x_setbuf ( x_stdout , NULL ) ;
2003-03-24 12:54:13 +03:00
if ( request_lm_key )
2003-07-07 09:11:10 +04:00
flags | = WBFLAG_PAM_LMKEY ;
2003-03-24 12:54:13 +03:00
2004-04-12 14:17:48 +04:00
if ( request_user_session_key )
2004-04-06 12:11:16 +04:00
flags | = WBFLAG_PAM_USER_SESSION_KEY ;
2003-04-07 11:10:53 +04:00
2004-04-06 20:44:24 +04:00
flags | = WBFLAG_PAM_NT_STATUS_SQUASH ;
2003-04-07 11:10:53 +04:00
nt_status = contact_winbind_auth_crap ( opt_username , opt_domain ,
opt_workstation ,
& opt_challenge ,
& opt_lm_response ,
& opt_nt_response ,
flags ,
2003-08-15 08:42:05 +04:00
( unsigned char * ) lm_key ,
2004-04-12 14:17:48 +04:00
( unsigned char * ) user_session_key ,
2003-12-30 16:20:39 +03:00
& error_string , NULL ) ;
2003-04-07 11:10:53 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2003-05-12 04:18:45 +04:00
x_fprintf ( x_stdout , " %s (0x%x) \n " ,
error_string ,
NT_STATUS_V ( nt_status ) ) ;
2003-04-07 11:10:53 +04:00
SAFE_FREE ( error_string ) ;
return False ;
}
2003-03-24 12:54:13 +03:00
2003-04-07 11:10:53 +04:00
if ( request_lm_key
& & ( memcmp ( zeros , lm_key ,
sizeof ( lm_key ) ) ! = 0 ) ) {
2009-04-14 06:43:34 +04:00
hex_lm_key = hex_encode_talloc ( talloc_tos ( ) , ( const unsigned char * ) lm_key ,
2005-08-08 00:59:28 +04:00
sizeof ( lm_key ) ) ;
2003-05-12 04:18:45 +04:00
x_fprintf ( x_stdout , " LM_KEY: %s \n " , hex_lm_key ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( hex_lm_key ) ;
2003-04-07 11:10:53 +04:00
}
2004-04-12 14:17:48 +04:00
if ( request_user_session_key
& & ( memcmp ( zeros , user_session_key ,
sizeof ( user_session_key ) ) ! = 0 ) ) {
2009-04-14 06:43:34 +04:00
hex_user_session_key = hex_encode_talloc ( talloc_tos ( ) , ( const unsigned char * ) user_session_key ,
2005-08-08 00:59:28 +04:00
sizeof ( user_session_key ) ) ;
2004-04-12 14:17:48 +04:00
x_fprintf ( x_stdout , " NT_KEY: %s \n " , hex_user_session_key ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( hex_user_session_key ) ;
2003-04-07 11:10:53 +04:00
}
2002-11-24 11:32:03 +03:00
2003-04-07 11:10:53 +04:00
return True ;
}
2002-11-24 11:32:03 +03:00
/* Main program */
2003-01-17 07:12:12 +03:00
enum {
2002-11-24 11:32:03 +03:00
OPT_USERNAME = 1000 ,
OPT_DOMAIN ,
OPT_WORKSTATION ,
OPT_CHALLENGE ,
OPT_RESPONSE ,
OPT_LM ,
OPT_NT ,
2003-03-24 12:54:13 +03:00
OPT_PASSWORD ,
OPT_LM_KEY ,
2004-04-12 14:17:48 +04:00
OPT_USER_SESSION_KEY ,
2004-04-06 20:44:24 +04:00
OPT_DIAGNOSTICS ,
2006-08-19 05:04:54 +04:00
OPT_REQUIRE_MEMBERSHIP ,
2009-05-21 22:03:32 +04:00
OPT_USE_CACHED_CREDS ,
OPT_PAM_WINBIND_CONF
2002-11-24 11:32:03 +03:00
} ;
2003-04-07 11:10:53 +04:00
int main ( int argc , const char * * argv )
2002-11-24 11:32:03 +03:00
{
2007-11-21 06:17:47 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2002-11-24 11:32:03 +03:00
int opt ;
2003-05-05 09:01:59 +04:00
static const char * helper_protocol ;
static int diagnostics ;
2002-11-24 11:32:03 +03:00
2003-04-07 11:10:53 +04:00
static const char * hex_challenge ;
static const char * hex_lm_response ;
static const char * hex_nt_response ;
2002-11-24 11:32:03 +03:00
poptContext pc ;
2003-04-07 11:10:53 +04:00
/* NOTE: DO NOT change this interface without considering the implications!
This is an external interface , which other programs will use to interact
with this helper .
*/
/* We do not use single-letter command abbreviations, because they harm future
interface stability . */
2002-11-24 11:32:03 +03:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
{ " helper-protocol " , 0 , POPT_ARG_STRING , & helper_protocol , OPT_DOMAIN , " operate as a stdio-based helper " , " helper protocol to use " } ,
2003-04-07 11:10:53 +04:00
{ " username " , 0 , POPT_ARG_STRING , & opt_username , OPT_USERNAME , " username " } ,
{ " domain " , 0 , POPT_ARG_STRING , & opt_domain , OPT_DOMAIN , " domain name " } ,
{ " workstation " , 0 , POPT_ARG_STRING , & opt_workstation , OPT_WORKSTATION , " workstation " } ,
2002-11-24 11:32:03 +03:00
{ " challenge " , 0 , POPT_ARG_STRING , & hex_challenge , OPT_CHALLENGE , " challenge (HEX encoded) " } ,
{ " lm-response " , 0 , POPT_ARG_STRING , & hex_lm_response , OPT_LM , " LM Response to the challenge (HEX encoded) " } ,
{ " nt-response " , 0 , POPT_ARG_STRING , & hex_nt_response , OPT_NT , " NT or NTLMv2 Response to the challenge (HEX encoded) " } ,
2003-04-07 11:10:53 +04:00
{ " password " , 0 , POPT_ARG_STRING , & opt_password , OPT_PASSWORD , " User's plaintext password " } ,
2005-04-25 06:30:12 +04:00
{ " request-lm-key " , 0 , POPT_ARG_NONE , & request_lm_key , OPT_LM_KEY , " Retrieve LM session key " } ,
{ " request-nt-key " , 0 , POPT_ARG_NONE , & request_user_session_key , OPT_USER_SESSION_KEY , " Retrieve User (NT) session key " } ,
2006-08-19 05:04:54 +04:00
{ " use-cached-creds " , 0 , POPT_ARG_NONE , & use_cached_creds , OPT_USE_CACHED_CREDS , " Use cached credentials if no password is given " } ,
2010-09-13 13:44:19 +04:00
{ " diagnostics " , 0 , POPT_ARG_NONE , & diagnostics ,
OPT_DIAGNOSTICS ,
" Perform diagnostics on the authentication chain " } ,
2004-04-06 20:44:24 +04:00
{ " require-membership-of " , 0 , POPT_ARG_STRING , & require_membership_of , OPT_REQUIRE_MEMBERSHIP , " Require that a user be a member of this group (either name or SID) for authentication to succeed " } ,
2009-05-21 22:03:32 +04:00
{ " pam-winbind-conf " , 0 , POPT_ARG_STRING , & opt_pam_winbind_conf , OPT_PAM_WINBIND_CONF , " Require that request must set WBFLAG_PAM_CONTACT_TRUSTDOM when krb5 auth is required " } ,
2008-01-31 11:42:03 +03:00
POPT_COMMON_CONFIGFILE
POPT_COMMON_VERSION
2003-04-14 07:59:04 +04:00
POPT_TABLEEND
2002-11-24 11:32:03 +03:00
} ;
/* Samba client initialisation */
2005-12-29 01:48:54 +03:00
load_case_tables ( ) ;
2002-11-24 11:32:03 +03:00
2010-10-29 07:19:32 +04:00
setup_logging ( " ntlm_auth " , DEBUG_STDERR ) ;
2003-05-12 04:18:45 +04:00
2002-11-24 11:32:03 +03:00
/* Parse options */
pc = poptGetContext ( " ntlm_auth " , argc , argv , long_options , 0 ) ;
/* Parse command line options */
if ( argc = = 1 ) {
poptPrintHelp ( pc , stderr , 0 ) ;
return 1 ;
}
2008-01-31 11:42:03 +03:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
/* Get generic config options like --configfile */
}
poptFreeContext ( pc ) ;
if ( ! lp_load ( get_dyn_CONFIGFILE ( ) , True , False , False , True ) ) {
d_fprintf ( stderr , " ntlm_auth: error opening config file %s. Error was %s \n " ,
get_dyn_CONFIGFILE ( ) , strerror ( errno ) ) ;
exit ( 1 ) ;
}
2002-11-24 11:32:03 +03:00
pc = poptGetContext ( NULL , argc , ( const char * * ) argv , long_options ,
POPT_CONTEXT_KEEP_FIRST ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case OPT_CHALLENGE :
2005-08-08 00:59:28 +04:00
opt_challenge = strhex_to_data_blob ( NULL , hex_challenge ) ;
2004-04-06 20:44:24 +04:00
if ( opt_challenge . length ! = 8 ) {
2004-04-12 14:17:48 +04:00
x_fprintf ( x_stderr , " hex decode of %s failed! (only got %d bytes) \n " ,
hex_challenge ,
( int ) opt_challenge . length ) ;
2002-11-24 11:32:03 +03:00
exit ( 1 ) ;
}
break ;
case OPT_LM :
2005-08-08 00:59:28 +04:00
opt_lm_response = strhex_to_data_blob ( NULL , hex_lm_response ) ;
2004-04-06 20:44:24 +04:00
if ( opt_lm_response . length ! = 24 ) {
2004-04-12 14:17:48 +04:00
x_fprintf ( x_stderr , " hex decode of %s failed! (only got %d bytes) \n " ,
hex_lm_response ,
( int ) opt_lm_response . length ) ;
2002-11-24 11:32:03 +03:00
exit ( 1 ) ;
}
break ;
2004-04-06 20:44:24 +04:00
2003-03-24 12:54:13 +03:00
case OPT_NT :
2005-08-08 00:59:28 +04:00
opt_nt_response = strhex_to_data_blob ( NULL , hex_nt_response ) ;
2004-04-06 20:44:24 +04:00
if ( opt_nt_response . length < 24 ) {
2004-04-12 14:17:48 +04:00
x_fprintf ( x_stderr , " hex decode of %s failed! (only got %d bytes) \n " ,
hex_nt_response ,
( int ) opt_nt_response . length ) ;
2002-11-24 11:32:03 +03:00
exit ( 1 ) ;
}
2004-04-06 20:44:24 +04:00
break ;
case OPT_REQUIRE_MEMBERSHIP :
if ( StrnCaseCmp ( " S- " , require_membership_of , 2 ) = = 0 ) {
2004-10-01 07:28:39 +04:00
require_membership_of_sid = require_membership_of ;
2004-04-06 20:44:24 +04:00
}
2002-11-24 11:32:03 +03:00
break ;
}
}
2006-09-01 08:33:33 +04:00
if ( opt_username ) {
2006-09-01 08:15:04 +04:00
char * domain = SMB_STRDUP ( opt_username ) ;
char * p = strchr_m ( domain , * lp_winbind_separator ( ) ) ;
if ( p ) {
opt_username = p + 1 ;
* p = ' \0 ' ;
if ( opt_domain & & ! strequal ( opt_domain , domain ) ) {
x_fprintf ( x_stderr , " Domain specified in username (%s) "
" doesn't match specified domain (%s)! \n \n " ,
domain , opt_domain ) ;
poptPrintHelp ( pc , stderr , 0 ) ;
exit ( 1 ) ;
}
opt_domain = domain ;
} else {
SAFE_FREE ( domain ) ;
}
}
2007-03-02 23:15:11 +03:00
/* Note: if opt_domain is "" then send no domain */
if ( opt_domain = = NULL ) {
2006-09-01 08:15:04 +04:00
opt_domain = get_winbind_domain ( ) ;
}
if ( opt_workstation = = NULL ) {
opt_workstation = " " ;
}
2002-11-24 11:32:03 +03:00
if ( helper_protocol ) {
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
int i ;
for ( i = 0 ; i < NUM_HELPER_MODES ; i + + ) {
if ( strcmp ( helper_protocol , stdio_helper_protocols [ i ] . name ) = = 0 ) {
squid_stream ( stdio_helper_protocols [ i ] . mode , stdio_helper_protocols [ i ] . fn ) ;
exit ( 0 ) ;
}
2002-11-24 11:32:03 +03:00
}
2003-12-30 10:33:58 +03:00
x_fprintf ( x_stderr , " unknown helper protocol [%s] \n \n Valid helper protools: \n \n " , helper_protocol ) ;
for ( i = 0 ; i < NUM_HELPER_MODES ; i + + ) {
x_fprintf ( x_stderr , " %s \n " , stdio_helper_protocols [ i ] . name ) ;
}
Changes all over the shop, but all towards:
- NTLM2 support in the server
- KEY_EXCH support in the server
- variable length session keys.
In detail:
- NTLM2 is an extension of NTLMv1, that is compatible with existing
domain controllers (unlike NTLMv2, which requires a DC upgrade).
* This is known as 'NTLMv2 session security' *
(This is not yet implemented on the RPC pipes however, so there may
well still be issues for PDC setups, particuarly around password
changes. We do not fully understand the sign/seal implications of
NTLM2 on RPC pipes.)
This requires modifications to our authentication subsystem, as we
must handle the 'challege' input into the challenge-response algorithm
being changed. This also needs to be turned off for
'security=server', which does not support this.
- KEY_EXCH is another 'security' mechanism, whereby the session key
actually used by the server is sent by the client, rather than being
the shared-secret directly or indirectly.
- As both these methods change the session key, the auth subsystem
needed to be changed, to 'override' session keys provided by the
backend.
- There has also been a major overhaul of the NTLMSSP subsystem, to merge the 'client' and 'server' functions, so they both operate on a single structure. This should help the SPNEGO implementation.
- The 'names blob' in NTLMSSP is always in unicode - never in ascii.
Don't make an ascii version ever.
- The other big change is to allow variable length session keys. We
have always assumed that session keys are 16 bytes long - and padded
to this length if shorter. However, Kerberos session keys are 8 bytes
long, when the krb5 login uses DES.
* This fix allows SMB signging on machines not yet running MIT KRB5 1.3.1. *
- Add better DEBUG() messages to ntlm_auth, warning administrators of
misconfigurations that prevent access to the privileged pipe. This
should help reduce some of the 'it just doesn't work' issues.
- Fix data_blob_talloc() to behave the same way data_blob() does when
passed a NULL data pointer. (just allocate)
REMEMBER to make clean after this commit - I have changed plenty of data structures...
(This used to be commit f3bbc87b0dac63426cda6fac7a295d3aad810ecc)
2003-11-22 16:19:38 +03:00
exit ( 1 ) ;
2002-11-24 11:32:03 +03:00
}
2006-09-01 08:33:33 +04:00
if ( ! opt_username | | ! * opt_username ) {
x_fprintf ( x_stderr , " username must be specified! \n \n " ) ;
poptPrintHelp ( pc , stderr , 0 ) ;
exit ( 1 ) ;
}
2003-04-07 11:10:53 +04:00
if ( opt_challenge . length ) {
2002-11-24 11:32:03 +03:00
if ( ! check_auth_crap ( ) ) {
exit ( 1 ) ;
}
2003-04-07 11:10:53 +04:00
exit ( 0 ) ;
}
if ( ! opt_password ) {
opt_password = getpass ( " password: " ) ;
}
if ( diagnostics ) {
if ( ! diagnose_ntlm_auth ( ) ) {
2004-04-12 14:17:48 +04:00
return 1 ;
2003-04-07 11:10:53 +04:00
}
} else {
2002-11-24 11:32:03 +03:00
fstring user ;
2003-04-07 11:10:53 +04:00
2003-07-23 16:33:59 +04:00
fstr_sprintf ( user , " %s%c%s " , opt_domain , winbind_separator ( ) , opt_username ) ;
2003-04-07 11:10:53 +04:00
if ( ! check_plaintext_auth ( user , opt_password , True ) ) {
2004-04-12 14:17:48 +04:00
return 1 ;
2002-11-24 11:32:03 +03:00
}
}
/* Exit code */
poptFreeContext ( pc ) ;
2007-11-21 06:17:47 +03:00
TALLOC_FREE ( frame ) ;
2002-11-24 11:32:03 +03:00
return 0 ;
}