2004-07-11 14:16:36 +04:00
/*
Unix SMB / CIFS implementation .
Kerberos backend for GENSEC
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004
Copyright ( C ) Andrew Tridgell 2001
Copyright ( C ) Luke Howard 2002 - 2003
2005-01-09 15:55:25 +03:00
Copyright ( C ) Stefan Metzmacher 2004 - 2005
2004-07-11 14:16:36 +04: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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-07-11 14:16:36 +04:00
( at your option ) any later version .
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 .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-07-11 14:16:36 +04:00
*/
# include "includes.h"
2004-11-02 01:48:25 +03:00
# include "system/kerberos.h"
2005-03-29 12:24:03 +04:00
# include "auth/kerberos/kerberos.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/krb5pac.h"
2004-11-02 05:57:18 +03:00
# include "auth/auth.h"
2006-03-14 18:44:40 +03:00
# include "lib/ldb/include/ldb.h"
2006-03-07 14:07:23 +03:00
# include "auth/auth_sam.h"
2006-01-03 01:00:40 +03:00
# include "system/network.h"
# include "lib/socket/socket.h"
2006-03-18 18:42:57 +03:00
# include "librpc/rpc/dcerpc.h"
2006-11-07 03:48:36 +03:00
# include "auth/credentials/credentials.h"
# include "auth/credentials/credentials_krb5.h"
# include "auth/gensec/gensec.h"
2008-04-02 06:53:27 +04:00
# include "auth/gensec/gensec_proto.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2008-04-02 06:53:27 +04:00
# include "auth/session_proto.h"
2004-07-11 14:16:36 +04:00
enum GENSEC_KRB5_STATE {
GENSEC_KRB5_SERVER_START ,
GENSEC_KRB5_CLIENT_START ,
GENSEC_KRB5_CLIENT_MUTUAL_AUTH ,
GENSEC_KRB5_DONE
} ;
struct gensec_krb5_state {
DATA_BLOB session_key ;
2004-11-06 02:26:02 +03:00
DATA_BLOB pac ;
2004-07-11 14:16:36 +04:00
enum GENSEC_KRB5_STATE state_position ;
2005-06-04 15:17:05 +04:00
struct smb_krb5_context * smb_krb5_context ;
2005-02-18 02:11:26 +03:00
krb5_auth_context auth_context ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
krb5_data enc_ticket ;
2005-06-29 17:55:09 +04:00
krb5_keyblock * keyblock ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
krb5_ticket * ticket ;
2007-10-07 02:16:19 +04:00
bool gssapi ;
2004-07-11 14:16:36 +04:00
} ;
2006-05-24 11:32:17 +04:00
static int gensec_krb5_destroy ( struct gensec_krb5_state * gensec_krb5_state )
2004-10-21 12:52:01 +04:00
{
2005-09-17 13:46:20 +04:00
if ( ! gensec_krb5_state - > smb_krb5_context ) {
/* We can't clean anything else up unless we started up this far */
return 0 ;
}
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
if ( gensec_krb5_state - > enc_ticket . length ) {
2005-06-04 15:17:05 +04:00
kerberos_free_data_contents ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
& gensec_krb5_state - > enc_ticket ) ;
2004-10-21 12:52:01 +04:00
}
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
if ( gensec_krb5_state - > ticket ) {
krb5_free_ticket ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
gensec_krb5_state - > ticket ) ;
}
2005-05-16 03:42:11 +04:00
/* ccache freed in a child destructor */
2004-10-21 12:52:01 +04:00
2005-06-29 17:55:09 +04:00
krb5_free_keyblock ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
2005-06-30 15:23:33 +04:00
gensec_krb5_state - > keyblock ) ;
2004-10-21 19:24:50 +04:00
2005-02-18 02:11:26 +03:00
if ( gensec_krb5_state - > auth_context ) {
2005-06-04 15:17:05 +04:00
krb5_auth_con_free ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
2005-02-18 02:11:26 +03:00
gensec_krb5_state - > auth_context ) ;
2004-10-21 12:52:01 +04:00
}
2004-12-24 12:54:23 +03:00
return 0 ;
2004-10-21 12:52:01 +04:00
}
2004-07-11 14:16:36 +04:00
static NTSTATUS gensec_krb5_start ( struct gensec_security * gensec_security )
{
2005-10-20 11:36:08 +04:00
krb5_error_code ret ;
2004-07-11 14:16:36 +04:00
struct gensec_krb5_state * gensec_krb5_state ;
2005-10-20 11:36:08 +04:00
struct cli_credentials * creds ;
2006-01-10 01:12:53 +03:00
const struct socket_address * my_addr , * peer_addr ;
2006-01-03 01:00:40 +03:00
krb5_address my_krb5_addr , peer_krb5_addr ;
2005-10-20 11:36:08 +04:00
creds = gensec_get_credentials ( gensec_security ) ;
if ( ! creds ) {
2005-10-20 07:47:55 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2005-01-27 10:08:20 +03:00
gensec_krb5_state = talloc ( gensec_security , struct gensec_krb5_state ) ;
2004-07-11 14:16:36 +04:00
if ( ! gensec_krb5_state ) {
return NT_STATUS_NO_MEMORY ;
}
gensec_security - > private_data = gensec_krb5_state ;
2005-09-17 13:46:20 +04:00
gensec_krb5_state - > smb_krb5_context = NULL ;
2005-02-18 02:11:26 +03:00
gensec_krb5_state - > auth_context = NULL ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
gensec_krb5_state - > ticket = NULL ;
ZERO_STRUCT ( gensec_krb5_state - > enc_ticket ) ;
gensec_krb5_state - > keyblock = NULL ;
2004-07-11 14:16:36 +04:00
gensec_krb5_state - > session_key = data_blob ( NULL , 0 ) ;
2004-11-06 02:26:02 +03:00
gensec_krb5_state - > pac = data_blob ( NULL , 0 ) ;
2007-10-07 02:16:19 +04:00
gensec_krb5_state - > gssapi = false ;
2004-07-11 14:16:36 +04:00
2005-09-17 13:46:20 +04:00
talloc_set_destructor ( gensec_krb5_state , gensec_krb5_destroy ) ;
2004-12-24 12:54:23 +03:00
2007-12-03 19:41:50 +03:00
if ( cli_credentials_get_krb5_context ( creds , gensec_security - > lp_ctx , & gensec_krb5_state - > smb_krb5_context ) ) {
2005-10-20 11:36:08 +04:00
talloc_free ( gensec_krb5_state ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
ret = krb5_auth_con_init ( gensec_krb5_state - > smb_krb5_context - > krb5_context , & gensec_krb5_state - > auth_context ) ;
if ( ret ) {
DEBUG ( 1 , ( " gensec_krb5_start: krb5_auth_con_init failed (%s) \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
ret , gensec_krb5_state ) ) ) ;
talloc_free ( gensec_krb5_state ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
ret = krb5_auth_con_setflags ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
gensec_krb5_state - > auth_context ,
KRB5_AUTH_CONTEXT_DO_SEQUENCE ) ;
if ( ret ) {
DEBUG ( 1 , ( " gensec_krb5_start: krb5_auth_con_setflags failed (%s) \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
ret , gensec_krb5_state ) ) ) ;
talloc_free ( gensec_krb5_state ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
2006-01-10 01:12:53 +03:00
my_addr = gensec_get_my_addr ( gensec_security ) ;
if ( my_addr & & my_addr - > sockaddr ) {
2006-01-03 01:00:40 +03:00
ret = krb5_sockaddr2address ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
2006-01-10 01:12:53 +03:00
my_addr - > sockaddr , & my_krb5_addr ) ;
2006-01-03 01:00:40 +03:00
if ( ret ) {
DEBUG ( 1 , ( " gensec_krb5_start: krb5_sockaddr2address (local) failed (%s) \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
ret , gensec_krb5_state ) ) ) ;
talloc_free ( gensec_krb5_state ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
}
2006-06-06 08:50:14 +04:00
peer_addr = gensec_get_peer_addr ( gensec_security ) ;
2006-01-10 01:12:53 +03:00
if ( peer_addr & & peer_addr - > sockaddr ) {
2006-01-03 01:00:40 +03:00
ret = krb5_sockaddr2address ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
2006-01-10 01:12:53 +03:00
peer_addr - > sockaddr , & peer_krb5_addr ) ;
2006-01-03 01:00:40 +03:00
if ( ret ) {
DEBUG ( 1 , ( " gensec_krb5_start: krb5_sockaddr2address (local) failed (%s) \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
ret , gensec_krb5_state ) ) ) ;
talloc_free ( gensec_krb5_state ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
}
ret = krb5_auth_con_setaddrs ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
gensec_krb5_state - > auth_context ,
my_addr ? & my_krb5_addr : NULL ,
peer_addr ? & peer_krb5_addr : NULL ) ;
if ( ret ) {
DEBUG ( 1 , ( " gensec_krb5_start: krb5_auth_con_setaddrs failed (%s) \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
ret , gensec_krb5_state ) ) ) ;
talloc_free ( gensec_krb5_state ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
2004-07-11 14:16:36 +04:00
return NT_STATUS_OK ;
}
static NTSTATUS gensec_krb5_server_start ( struct gensec_security * gensec_security )
{
NTSTATUS nt_status ;
struct gensec_krb5_state * gensec_krb5_state ;
nt_status = gensec_krb5_start ( gensec_security ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
}
2005-08-29 08:30:22 +04:00
2007-09-07 17:31:15 +04:00
gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2004-07-11 14:16:36 +04:00
gensec_krb5_state - > state_position = GENSEC_KRB5_SERVER_START ;
return NT_STATUS_OK ;
}
2005-09-21 14:18:40 +04:00
static NTSTATUS gensec_fake_gssapi_krb5_server_start ( struct gensec_security * gensec_security )
{
NTSTATUS nt_status = gensec_krb5_server_start ( gensec_security ) ;
if ( NT_STATUS_IS_OK ( nt_status ) ) {
struct gensec_krb5_state * gensec_krb5_state ;
2007-09-07 17:31:15 +04:00
gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2007-10-07 02:16:19 +04:00
gensec_krb5_state - > gssapi = true ;
2005-09-21 14:18:40 +04:00
}
return nt_status ;
}
2007-12-03 19:41:50 +03:00
static NTSTATUS gensec_krb5_client_start ( struct gensec_security * gensec_security )
2004-07-11 14:16:36 +04:00
{
struct gensec_krb5_state * gensec_krb5_state ;
2004-07-12 13:11:13 +04:00
krb5_error_code ret ;
2004-07-11 14:16:36 +04:00
NTSTATUS nt_status ;
2005-08-29 08:30:22 +04:00
struct ccache_container * ccache_container ;
2005-09-17 13:46:20 +04:00
const char * hostname ;
krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED ;
2005-05-16 03:42:11 +04:00
2005-10-30 13:39:52 +03:00
const char * principal ;
2005-10-20 11:36:08 +04:00
krb5_data in_data ;
2005-09-17 13:46:20 +04:00
hostname = gensec_get_target_hostname ( gensec_security ) ;
r6028: A MAJOR update to intergrate the new credentails system fully with
GENSEC, and to pull SCHANNEL into GENSEC, by making it less 'special'.
GENSEC now no longer has it's own handling of 'set username' etc,
instead it uses cli_credentials calls.
In order to link the credentails code right though Samba, a lot of
interfaces have changed to remove 'username, domain, password'
arguments, and these have been replaced with a single 'struct
cli_credentials'.
In the session setup code, a new parameter 'workgroup' contains the
client/server current workgroup, which seems unrelated to the
authentication exchange (it was being filled in from the auth info).
This allows in particular kerberos to only call back for passwords
when it actually needs to perform the kinit.
The kerberos code has been modified not to use the SPNEGO provided
'principal name' (in the mechListMIC), but to instead use the name the
host was connected to as. This better matches Microsoft behaviour,
is more secure and allows better use of standard kerberos functions.
To achieve this, I made changes to our socket code so that the
hostname (before name resolution) is now recorded on the socket.
In schannel, most of the code from librpc/rpc/dcerpc_schannel.c is now
in libcli/auth/schannel.c, and it looks much more like a standard
GENSEC module. The actual sign/seal code moved to
libcli/auth/schannel_sign.c in a previous commit.
The schannel credentails structure is now merged with the rest of the
credentails, as many of the values (username, workstation, domain)
where already present there. This makes handling this in a generic
manner much easier, as there is no longer a custom entry-point.
The auth_domain module continues to be developed, but is now just as
functional as auth_winbind. The changes here are consequential to the
schannel changes.
The only removed function at this point is the RPC-LOGIN test
(simulating the load of a WinXP login), which needs much more work to
clean it up (it contains copies of too much code from all over the
torture suite, and I havn't been able to penetrate its 'structure').
Andrew Bartlett
(This used to be commit 2301a4b38a21aa60917973451687063d83d18d66)
2005-03-24 07:14:06 +03:00
if ( ! hostname ) {
DEBUG ( 1 , ( " Could not determine hostname for target computer, cannot use kerberos \n " ) ) ;
2005-07-09 05:58:38 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
if ( is_ipaddress ( hostname ) ) {
2005-09-21 14:18:40 +04:00
DEBUG ( 2 , ( " Cannot do krb5 to an IP address " ) ) ;
2005-07-09 05:58:38 +04:00
return NT_STATUS_INVALID_PARAMETER ;
r6028: A MAJOR update to intergrate the new credentails system fully with
GENSEC, and to pull SCHANNEL into GENSEC, by making it less 'special'.
GENSEC now no longer has it's own handling of 'set username' etc,
instead it uses cli_credentials calls.
In order to link the credentails code right though Samba, a lot of
interfaces have changed to remove 'username, domain, password'
arguments, and these have been replaced with a single 'struct
cli_credentials'.
In the session setup code, a new parameter 'workgroup' contains the
client/server current workgroup, which seems unrelated to the
authentication exchange (it was being filled in from the auth info).
This allows in particular kerberos to only call back for passwords
when it actually needs to perform the kinit.
The kerberos code has been modified not to use the SPNEGO provided
'principal name' (in the mechListMIC), but to instead use the name the
host was connected to as. This better matches Microsoft behaviour,
is more secure and allows better use of standard kerberos functions.
To achieve this, I made changes to our socket code so that the
hostname (before name resolution) is now recorded on the socket.
In schannel, most of the code from librpc/rpc/dcerpc_schannel.c is now
in libcli/auth/schannel.c, and it looks much more like a standard
GENSEC module. The actual sign/seal code moved to
libcli/auth/schannel_sign.c in a previous commit.
The schannel credentails structure is now merged with the rest of the
credentails, as many of the values (username, workstation, domain)
where already present there. This makes handling this in a generic
manner much easier, as there is no longer a custom entry-point.
The auth_domain module continues to be developed, but is now just as
functional as auth_winbind. The changes here are consequential to the
schannel changes.
The only removed function at this point is the RPC-LOGIN test
(simulating the load of a WinXP login), which needs much more work to
clean it up (it contains copies of too much code from all over the
torture suite, and I havn't been able to penetrate its 'structure').
Andrew Bartlett
(This used to be commit 2301a4b38a21aa60917973451687063d83d18d66)
2005-03-24 07:14:06 +03:00
}
2006-04-27 20:09:17 +04:00
if ( strcmp ( hostname , " localhost " ) = = 0 ) {
2005-09-28 08:50:02 +04:00
DEBUG ( 2 , ( " krb5 to 'localhost' does not make sense " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
r6028: A MAJOR update to intergrate the new credentails system fully with
GENSEC, and to pull SCHANNEL into GENSEC, by making it less 'special'.
GENSEC now no longer has it's own handling of 'set username' etc,
instead it uses cli_credentials calls.
In order to link the credentails code right though Samba, a lot of
interfaces have changed to remove 'username, domain, password'
arguments, and these have been replaced with a single 'struct
cli_credentials'.
In the session setup code, a new parameter 'workgroup' contains the
client/server current workgroup, which seems unrelated to the
authentication exchange (it was being filled in from the auth info).
This allows in particular kerberos to only call back for passwords
when it actually needs to perform the kinit.
The kerberos code has been modified not to use the SPNEGO provided
'principal name' (in the mechListMIC), but to instead use the name the
host was connected to as. This better matches Microsoft behaviour,
is more secure and allows better use of standard kerberos functions.
To achieve this, I made changes to our socket code so that the
hostname (before name resolution) is now recorded on the socket.
In schannel, most of the code from librpc/rpc/dcerpc_schannel.c is now
in libcli/auth/schannel.c, and it looks much more like a standard
GENSEC module. The actual sign/seal code moved to
libcli/auth/schannel_sign.c in a previous commit.
The schannel credentails structure is now merged with the rest of the
credentails, as many of the values (username, workstation, domain)
where already present there. This makes handling this in a generic
manner much easier, as there is no longer a custom entry-point.
The auth_domain module continues to be developed, but is now just as
functional as auth_winbind. The changes here are consequential to the
schannel changes.
The only removed function at this point is the RPC-LOGIN test
(simulating the load of a WinXP login), which needs much more work to
clean it up (it contains copies of too much code from all over the
torture suite, and I havn't been able to penetrate its 'structure').
Andrew Bartlett
(This used to be commit 2301a4b38a21aa60917973451687063d83d18d66)
2005-03-24 07:14:06 +03:00
2004-07-11 14:16:36 +04:00
nt_status = gensec_krb5_start ( gensec_security ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
}
2007-09-07 17:31:15 +04:00
gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2004-07-11 14:16:36 +04:00
gensec_krb5_state - > state_position = GENSEC_KRB5_CLIENT_START ;
2007-05-17 09:44:51 +04:00
principal = gensec_get_target_principal ( gensec_security ) ;
2007-12-14 00:46:17 +03:00
ret = cli_credentials_get_ccache ( gensec_get_credentials ( gensec_security ) , gensec_security - > lp_ctx , & ccache_container ) ;
2007-05-17 09:44:51 +04:00
switch ( ret ) {
case 0 :
break ;
case KRB5KDC_ERR_PREAUTH_FAILED :
return NT_STATUS_LOGON_FAILURE ;
case KRB5_KDC_UNREACH :
DEBUG ( 3 , ( " Cannot reach a KDC we require to contact %s \n " , principal ) ) ;
return NT_STATUS_INVALID_PARAMETER ; /* Make SPNEGO ignore us, we can't go any further here */
default :
2007-12-02 21:31:14 +03:00
DEBUG ( 1 , ( " gensec_krb5_start: Aquiring initiator credentials failed: %s \n " , error_message ( ret ) ) ) ;
2005-08-29 08:30:22 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2005-10-20 11:36:08 +04:00
in_data . length = 0 ;
2007-12-03 19:41:50 +03:00
if ( principal & & lp_client_use_spnego_principal ( gensec_security - > lp_ctx ) ) {
2005-10-20 11:36:08 +04:00
krb5_principal target_principal ;
ret = krb5_parse_name ( gensec_krb5_state - > smb_krb5_context - > krb5_context , principal ,
& target_principal ) ;
if ( ret = = 0 ) {
ret = krb5_mk_req_exact ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
& gensec_krb5_state - > auth_context ,
ap_req_options ,
target_principal ,
& in_data , ccache_container - > ccache ,
& gensec_krb5_state - > enc_ticket ) ;
krb5_free_principal ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
target_principal ) ;
2005-09-17 13:46:20 +04:00
}
2005-10-20 11:36:08 +04:00
} else {
ret = krb5_mk_req ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
& gensec_krb5_state - > auth_context ,
ap_req_options ,
gensec_get_target_service ( gensec_security ) ,
hostname ,
& in_data , ccache_container - > ccache ,
& gensec_krb5_state - > enc_ticket ) ;
2005-08-29 08:30:22 +04:00
}
switch ( ret ) {
case 0 :
return NT_STATUS_OK ;
case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN :
DEBUG ( 3 , ( " Server [%s] is not registered with our KDC: %s \n " ,
hostname , smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context , ret , gensec_krb5_state ) ) ) ;
2005-09-28 08:50:02 +04:00
return NT_STATUS_INVALID_PARAMETER ; /* Make SPNEGO ignore us, we can't go any further here */
2005-10-30 03:56:39 +03:00
case KRB5_KDC_UNREACH :
DEBUG ( 3 , ( " Cannot reach a KDC we require to contact host [%s]: %s \n " ,
hostname , smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context , ret , gensec_krb5_state ) ) ) ;
return NT_STATUS_INVALID_PARAMETER ; /* Make SPNEGO ignore us, we can't go any further here */
2005-08-29 08:30:22 +04:00
case KRB5KDC_ERR_PREAUTH_FAILED :
case KRB5KRB_AP_ERR_TKT_EXPIRED :
case KRB5_CC_END :
/* Too much clock skew - we will need to kinit to re-skew the clock */
case KRB5KRB_AP_ERR_SKEW :
case KRB5_KDCREP_SKEW :
{
DEBUG ( 3 , ( " kerberos (mk_req) failed: %s \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context , ret , gensec_krb5_state ) ) ) ;
2006-04-30 00:59:46 +04:00
/*fall through*/
2005-08-29 08:30:22 +04:00
}
2004-07-12 08:26:50 +04:00
2005-08-29 08:30:22 +04:00
/* just don't print a message for these really ordinary messages */
case KRB5_FCC_NOFILE :
case KRB5_CC_NOTFOUND :
case ENOENT :
2005-05-16 03:42:11 +04:00
2005-08-29 08:30:22 +04:00
return NT_STATUS_UNSUCCESSFUL ;
2005-05-16 03:42:11 +04:00
break ;
2005-08-29 08:30:22 +04:00
default :
DEBUG ( 0 , ( " kerberos: %s \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context , ret , gensec_krb5_state ) ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
2004-07-13 09:14:59 +04:00
}
2004-07-11 14:16:36 +04:00
}
2007-12-03 19:41:50 +03:00
static NTSTATUS gensec_fake_gssapi_krb5_client_start ( struct gensec_security * gensec_security )
2005-09-21 14:18:40 +04:00
{
2007-12-03 19:41:50 +03:00
NTSTATUS nt_status = gensec_krb5_client_start ( gensec_security ) ;
2005-09-21 14:18:40 +04:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
struct gensec_krb5_state * gensec_krb5_state ;
2007-09-08 17:27:14 +04:00
gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2007-10-07 02:16:19 +04:00
gensec_krb5_state - > gssapi = true ;
2005-09-21 14:18:40 +04:00
}
return nt_status ;
}
2004-07-11 14:16:36 +04:00
2005-06-22 06:12:26 +04:00
/**
* Check if the packet is one for this mechansim
*
* @ param gensec_security GENSEC state
* @ param in The request , as a DATA_BLOB
* @ return Error , INVALID_PARAMETER if it ' s not a packet for us
* or NT_STATUS_OK if the packet is ok .
*/
2005-09-21 14:18:40 +04:00
static NTSTATUS gensec_fake_gssapi_krb5_magic ( struct gensec_security * gensec_security ,
2005-06-22 06:12:26 +04:00
const DATA_BLOB * in )
{
if ( gensec_gssapi_check_oid ( in , GENSEC_OID_KERBEROS5 ) ) {
return NT_STATUS_OK ;
} else {
return NT_STATUS_INVALID_PARAMETER ;
}
}
2004-07-11 14:16:36 +04:00
/**
* Next state function for the Krb5 GENSEC mechanism
*
* @ param gensec_krb5_state KRB5 State
* @ param out_mem_ctx The TALLOC_CTX for * out to be allocated on
* @ param in The request , as a DATA_BLOB
* @ param out The reply , as an talloc ( ) ed DATA_BLOB , on * out_mem_ctx
* @ return Error , MORE_PROCESSING_REQUIRED if a reply is sent ,
* or NT_STATUS_OK if the user is authenticated .
*/
2004-12-24 12:54:23 +03:00
static NTSTATUS gensec_krb5_update ( struct gensec_security * gensec_security ,
TALLOC_CTX * out_mem_ctx ,
const DATA_BLOB in , DATA_BLOB * out )
2004-07-11 14:16:36 +04:00
{
2007-09-08 17:27:14 +04:00
struct gensec_krb5_state * gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2004-07-11 14:16:36 +04:00
krb5_error_code ret = 0 ;
NTSTATUS nt_status ;
switch ( gensec_krb5_state - > state_position ) {
case GENSEC_KRB5_CLIENT_START :
{
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
DATA_BLOB unwrapped_out ;
2005-09-21 14:18:40 +04:00
if ( gensec_krb5_state - > gssapi ) {
unwrapped_out = data_blob_talloc ( out_mem_ctx , gensec_krb5_state - > enc_ticket . data , gensec_krb5_state - > enc_ticket . length ) ;
/* wrap that up in a nice GSS-API wrapping */
* out = gensec_gssapi_gen_krb5_wrap ( out_mem_ctx , & unwrapped_out , TOK_ID_KRB_AP_REQ ) ;
} else {
* out = data_blob_talloc ( out_mem_ctx , gensec_krb5_state - > enc_ticket . data , gensec_krb5_state - > enc_ticket . length ) ;
}
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
gensec_krb5_state - > state_position = GENSEC_KRB5_CLIENT_MUTUAL_AUTH ;
nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED ;
2004-07-11 14:16:36 +04:00
return nt_status ;
}
case GENSEC_KRB5_CLIENT_MUTUAL_AUTH :
{
2005-09-21 14:18:40 +04:00
DATA_BLOB unwrapped_in ;
2004-07-11 14:16:36 +04:00
krb5_data inbuf ;
krb5_ap_rep_enc_part * repl = NULL ;
2005-02-10 08:22:53 +03:00
uint8_t tok_id [ 2 ] ;
2004-07-12 08:26:50 +04:00
2005-09-21 14:18:40 +04:00
if ( gensec_krb5_state - > gssapi ) {
if ( ! gensec_gssapi_parse_krb5_wrap ( out_mem_ctx , & in , & unwrapped_in , tok_id ) ) {
DEBUG ( 1 , ( " gensec_gssapi_parse_krb5_wrap(mutual authentication) failed to parse \n " ) ) ;
dump_data_pw ( " Mutual authentication message: \n " , in . data , in . length ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
} else {
unwrapped_in = in ;
2004-07-12 08:26:50 +04:00
}
/* TODO: check the tok_id */
inbuf . data = unwrapped_in . data ;
inbuf . length = unwrapped_in . length ;
2005-06-04 15:17:05 +04:00
ret = krb5_rd_rep ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
2005-02-18 02:11:26 +03:00
gensec_krb5_state - > auth_context ,
2004-07-11 14:16:36 +04:00
& inbuf , & repl ) ;
if ( ret ) {
DEBUG ( 1 , ( " krb5_rd_rep (mutual authentication) failed (%s) \n " ,
2005-06-04 15:17:05 +04:00
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context , ret , out_mem_ctx ) ) ) ;
2007-09-08 17:27:14 +04:00
dump_data_pw ( " Mutual authentication message: \n " , ( uint8_t * ) inbuf . data , inbuf . length ) ;
2004-07-11 14:16:36 +04:00
nt_status = NT_STATUS_ACCESS_DENIED ;
} else {
* out = data_blob ( NULL , 0 ) ;
nt_status = NT_STATUS_OK ;
gensec_krb5_state - > state_position = GENSEC_KRB5_DONE ;
}
if ( repl ) {
2005-06-04 15:17:05 +04:00
krb5_free_ap_rep_enc_part ( gensec_krb5_state - > smb_krb5_context - > krb5_context , repl ) ;
2004-07-11 14:16:36 +04:00
}
return nt_status ;
}
2004-08-12 11:37:49 +04:00
2004-07-11 14:16:36 +04:00
case GENSEC_KRB5_SERVER_START :
{
2004-07-12 08:26:50 +04:00
DATA_BLOB unwrapped_in ;
2004-12-02 21:27:08 +03:00
DATA_BLOB unwrapped_out = data_blob ( NULL , 0 ) ;
2006-11-08 04:48:35 +03:00
krb5_data inbuf , outbuf ;
2005-02-10 08:22:53 +03:00
uint8_t tok_id [ 2 ] ;
2006-11-08 04:48:35 +03:00
struct keytab_container * keytab ;
krb5_principal server_in_keytab ;
2004-07-12 08:26:50 +04:00
2004-12-02 21:27:08 +03:00
if ( ! in . data ) {
2005-09-21 14:18:40 +04:00
return NT_STATUS_INVALID_PARAMETER ;
2004-12-02 21:27:08 +03:00
}
2006-11-08 04:48:35 +03:00
/* Grab the keytab, however generated */
2007-12-14 00:46:17 +03:00
ret = cli_credentials_get_keytab ( gensec_get_credentials ( gensec_security ) , gensec_security - > lp_ctx , & keytab ) ;
2006-11-08 04:48:35 +03:00
if ( ret ) {
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
/* This ensures we lookup the correct entry in that keytab */
ret = principal_from_credentials ( out_mem_ctx , gensec_get_credentials ( gensec_security ) ,
gensec_krb5_state - > smb_krb5_context ,
& server_in_keytab ) ;
if ( ret ) {
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
2004-07-12 08:26:50 +04:00
/* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
2005-09-21 14:18:40 +04:00
if ( gensec_krb5_state - > gssapi
& & gensec_gssapi_parse_krb5_wrap ( out_mem_ctx , & in , & unwrapped_in , tok_id ) ) {
2006-11-08 04:48:35 +03:00
inbuf . data = unwrapped_in . data ;
inbuf . length = unwrapped_in . length ;
2004-07-12 08:26:50 +04:00
} else {
2006-11-08 04:48:35 +03:00
inbuf . data = in . data ;
inbuf . length = in . length ;
2004-07-12 08:26:50 +04:00
}
2004-07-11 14:16:36 +04:00
2006-11-08 04:48:35 +03:00
ret = smb_rd_req_return_stuff ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
& gensec_krb5_state - > auth_context ,
& inbuf , keytab - > keytab , server_in_keytab ,
& outbuf ,
& gensec_krb5_state - > ticket ,
& gensec_krb5_state - > keyblock ) ;
2004-08-12 11:37:49 +04:00
2006-11-08 04:48:35 +03:00
if ( ret ) {
return NT_STATUS_LOGON_FAILURE ;
2004-07-11 14:16:36 +04:00
}
2007-09-08 17:27:14 +04:00
unwrapped_out . data = ( uint8_t * ) outbuf . data ;
2006-11-08 04:48:35 +03:00
unwrapped_out . length = outbuf . length ;
gensec_krb5_state - > state_position = GENSEC_KRB5_DONE ;
/* wrap that up in a nice GSS-API wrapping */
if ( gensec_krb5_state - > gssapi ) {
* out = gensec_gssapi_gen_krb5_wrap ( out_mem_ctx , & unwrapped_out , TOK_ID_KRB_AP_REP ) ;
} else {
* out = data_blob_talloc ( out_mem_ctx , outbuf . data , outbuf . length ) ;
}
krb5_data_free ( & outbuf ) ;
return NT_STATUS_OK ;
2004-07-11 14:16:36 +04:00
}
2006-01-03 01:00:40 +03:00
2004-07-11 14:16:36 +04:00
case GENSEC_KRB5_DONE :
2006-01-03 01:00:40 +03:00
default :
/* Asking too many times... */
return NT_STATUS_INVALID_PARAMETER ;
2004-07-11 14:16:36 +04:00
}
}
static NTSTATUS gensec_krb5_session_key ( struct gensec_security * gensec_security ,
2005-06-04 15:17:05 +04:00
DATA_BLOB * session_key )
2004-07-11 14:16:36 +04:00
{
2007-09-07 19:08:14 +04:00
struct gensec_krb5_state * gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2005-06-04 15:17:05 +04:00
krb5_context context = gensec_krb5_state - > smb_krb5_context - > krb5_context ;
2005-02-18 02:11:26 +03:00
krb5_auth_context auth_context = gensec_krb5_state - > auth_context ;
2004-07-11 14:16:36 +04:00
krb5_keyblock * skey ;
2005-07-11 19:42:27 +04:00
krb5_error_code err = - 1 ;
2004-07-11 14:16:36 +04:00
if ( gensec_krb5_state - > session_key . data ) {
* session_key = gensec_krb5_state - > session_key ;
return NT_STATUS_OK ;
}
switch ( gensec_security - > gensec_role ) {
case GENSEC_CLIENT :
err = krb5_auth_con_getlocalsubkey ( context , auth_context , & skey ) ;
break ;
case GENSEC_SERVER :
err = krb5_auth_con_getremotesubkey ( context , auth_context , & skey ) ;
break ;
}
if ( err = = 0 & & skey ! = NULL ) {
2005-07-17 13:20:52 +04:00
DEBUG ( 10 , ( " Got KRB5 session key of length %d \n " ,
( int ) KRB5_KEY_LENGTH ( skey ) ) ) ;
2004-09-26 06:16:25 +04:00
gensec_krb5_state - > session_key = data_blob_talloc ( gensec_krb5_state ,
2004-07-11 14:16:36 +04:00
KRB5_KEY_DATA ( skey ) , KRB5_KEY_LENGTH ( skey ) ) ;
* session_key = gensec_krb5_state - > session_key ;
dump_data_pw ( " KRB5 Session Key: \n " , session_key - > data , session_key - > length ) ;
krb5_free_keyblock ( context , skey ) ;
return NT_STATUS_OK ;
} else {
DEBUG ( 10 , ( " KRB5 error getting session key %d \n " , err ) ) ;
return NT_STATUS_NO_USER_SESSION_KEY ;
}
}
2004-08-12 11:37:49 +04:00
static NTSTATUS gensec_krb5_session_info ( struct gensec_security * gensec_security ,
2005-01-09 15:55:25 +03:00
struct auth_session_info * * _session_info )
2004-08-12 11:37:49 +04:00
{
2005-10-20 14:15:31 +04:00
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
2007-09-07 19:08:14 +04:00
struct gensec_krb5_state * gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2005-10-27 03:41:01 +04:00
krb5_context context = gensec_krb5_state - > smb_krb5_context - > krb5_context ;
2004-09-12 03:09:26 +04:00
struct auth_serversupplied_info * server_info = NULL ;
2004-08-12 11:37:49 +04:00
struct auth_session_info * session_info = NULL ;
2004-11-06 02:26:02 +03:00
struct PAC_LOGON_INFO * logon_info ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
2005-10-27 03:41:01 +04:00
krb5_principal client_principal ;
2006-11-07 09:59:56 +03:00
char * principal_string ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
DATA_BLOB pac ;
2005-10-27 03:41:01 +04:00
krb5_data pac_data ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
2005-10-27 03:41:01 +04:00
krb5_error_code ret ;
2005-10-20 14:15:31 +04:00
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
TALLOC_CTX * mem_ctx = talloc_new ( gensec_security ) ;
if ( ! mem_ctx ) {
return NT_STATUS_NO_MEMORY ;
2004-09-12 03:09:26 +04:00
}
2005-10-20 14:15:31 +04:00
2006-11-07 09:59:56 +03:00
ret = krb5_ticket_get_client ( context , gensec_krb5_state - > ticket , & client_principal ) ;
if ( ret ) {
DEBUG ( 5 , ( " krb5_ticket_get_client failed to get cleint principal: %s \n " ,
smb_get_krb5_error_message ( context ,
ret , mem_ctx ) ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
ret = krb5_unparse_name ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
client_principal , & principal_string ) ;
if ( ret ) {
DEBUG ( 1 , ( " Unable to parse client principal: %s \n " ,
smb_get_krb5_error_message ( context ,
ret , mem_ctx ) ) ) ;
talloc_free ( mem_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-10-27 03:41:01 +04:00
ret = krb5_ticket_get_authorization_data_type ( context , gensec_krb5_state - > ticket ,
KRB5_AUTHDATA_WIN2K_PAC ,
& pac_data ) ;
2007-12-03 19:41:50 +03:00
if ( ret & & lp_parm_bool ( gensec_security - > lp_ctx , NULL , " gensec " , " require_pac " , false ) ) {
2006-11-07 09:59:56 +03:00
DEBUG ( 1 , ( " Unable to find PAC in ticket from %s, failing to allow access: %s \n " ,
principal_string ,
smb_get_krb5_error_message ( context ,
ret , mem_ctx ) ) ) ;
krb5_free_principal ( context , client_principal ) ;
free ( principal_string ) ;
return NT_STATUS_ACCESS_DENIED ;
} else if ( ret ) {
/* NO pac */
2005-10-27 03:41:01 +04:00
DEBUG ( 5 , ( " krb5_ticket_get_authorization_data_type failed to find PAC: %s \n " ,
smb_get_krb5_error_message ( context ,
ret , mem_ctx ) ) ) ;
2007-12-03 19:41:50 +03:00
nt_status = sam_get_server_info_principal ( mem_ctx , gensec_security - > lp_ctx , principal_string ,
2006-11-07 09:59:56 +03:00
& server_info ) ;
krb5_free_principal ( context , client_principal ) ;
free ( principal_string ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( mem_ctx ) ;
return nt_status ;
}
2005-10-27 03:41:01 +04:00
} else {
2006-11-07 09:59:56 +03:00
/* Found pac */
union netr_Validation validation ;
free ( principal_string ) ;
2005-10-27 03:41:01 +04:00
pac = data_blob_talloc ( mem_ctx , pac_data . data , pac_data . length ) ;
if ( ! pac . data ) {
2006-11-07 09:59:56 +03:00
krb5_free_principal ( context , client_principal ) ;
2006-01-31 04:50:54 +03:00
talloc_free ( mem_ctx ) ;
2005-10-27 03:41:01 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-11-06 02:26:02 +03:00
2005-10-20 14:15:31 +04:00
/* decode and verify the pac */
2008-02-21 16:16:02 +03:00
nt_status = kerberos_pac_logon_info ( gensec_krb5_state ,
lp_iconv_convenience ( gensec_security - > lp_ctx ) ,
& logon_info , pac ,
2005-10-20 14:15:31 +04:00
gensec_krb5_state - > smb_krb5_context - > krb5_context ,
NULL , gensec_krb5_state - > keyblock ,
client_principal ,
2005-11-07 05:29:37 +03:00
gensec_krb5_state - > ticket - > ticket . authtime , NULL ) ;
2005-10-27 03:41:01 +04:00
krb5_free_principal ( context , client_principal ) ;
2006-11-07 09:59:56 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2006-01-31 04:50:54 +03:00
talloc_free ( mem_ctx ) ;
2006-11-07 09:59:56 +03:00
return nt_status ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
}
2006-11-07 09:59:56 +03:00
validation . sam3 = & logon_info - > info3 ;
nt_status = make_server_info_netlogon_validation ( mem_ctx ,
NULL ,
3 , & validation ,
& server_info ) ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( mem_ctx ) ;
return nt_status ;
}
2004-12-23 05:23:42 +03:00
}
2004-10-25 08:25:29 +04:00
2004-12-23 05:23:42 +03:00
/* references the server_info into the session_info */
2007-12-03 20:47:35 +03:00
nt_status = auth_generate_session_info ( mem_ctx , gensec_security - > lp_ctx , server_info , & session_info ) ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-08 01:52:50 +04:00
2006-01-31 04:50:54 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( mem_ctx ) ;
return nt_status ;
}
2004-10-25 08:25:29 +04:00
2004-09-12 07:18:24 +04:00
nt_status = gensec_krb5_session_key ( gensec_security , & session_info - > session_key ) ;
2006-01-31 04:50:54 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( mem_ctx ) ;
return nt_status ;
}
2004-08-12 11:37:49 +04:00
2005-01-09 15:55:25 +03:00
* _session_info = session_info ;
2004-08-12 11:37:49 +04:00
2006-01-31 04:50:54 +03:00
talloc_steal ( gensec_krb5_state , session_info ) ;
talloc_free ( mem_ctx ) ;
2005-01-09 15:55:25 +03:00
return NT_STATUS_OK ;
2004-08-12 11:37:49 +04:00
}
2004-07-11 14:16:36 +04:00
2005-09-21 14:18:40 +04:00
static NTSTATUS gensec_krb5_wrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
2007-09-07 19:08:14 +04:00
struct gensec_krb5_state * gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2005-09-21 14:18:40 +04:00
krb5_context context = gensec_krb5_state - > smb_krb5_context - > krb5_context ;
krb5_auth_context auth_context = gensec_krb5_state - > auth_context ;
krb5_error_code ret ;
krb5_data input , output ;
input . length = in - > length ;
input . data = in - > data ;
if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
2005-10-21 05:25:55 +04:00
ret = krb5_mk_priv ( context , auth_context , & input , & output , NULL ) ;
2005-09-21 14:18:40 +04:00
if ( ret ) {
DEBUG ( 1 , ( " krb5_mk_priv failed: %s \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
ret , mem_ctx ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
* out = data_blob_talloc ( mem_ctx , output . data , output . length ) ;
krb5_data_free ( & output ) ;
} else {
return NT_STATUS_ACCESS_DENIED ;
}
return NT_STATUS_OK ;
}
static NTSTATUS gensec_krb5_unwrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
2007-09-07 19:08:14 +04:00
struct gensec_krb5_state * gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2005-09-21 14:18:40 +04:00
krb5_context context = gensec_krb5_state - > smb_krb5_context - > krb5_context ;
krb5_auth_context auth_context = gensec_krb5_state - > auth_context ;
krb5_error_code ret ;
krb5_data input , output ;
krb5_replay_data replay ;
input . length = in - > length ;
input . data = in - > data ;
if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
ret = krb5_rd_priv ( context , auth_context , & input , & output , & replay ) ;
if ( ret ) {
DEBUG ( 1 , ( " krb5_rd_priv failed: %s \n " ,
smb_get_krb5_error_message ( gensec_krb5_state - > smb_krb5_context - > krb5_context ,
ret , mem_ctx ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
* out = data_blob_talloc ( mem_ctx , output . data , output . length ) ;
krb5_data_free ( & output ) ;
} else {
return NT_STATUS_ACCESS_DENIED ;
}
return NT_STATUS_OK ;
}
2007-10-07 02:16:19 +04:00
static bool gensec_krb5_have_feature ( struct gensec_security * gensec_security ,
2005-02-10 08:22:53 +03:00
uint32_t feature )
2005-01-01 01:45:11 +03:00
{
2007-09-07 19:08:14 +04:00
struct gensec_krb5_state * gensec_krb5_state = ( struct gensec_krb5_state * ) gensec_security - > private_data ;
2005-01-01 01:45:11 +03:00
if ( feature & GENSEC_FEATURE_SESSION_KEY ) {
2007-10-07 02:16:19 +04:00
return true ;
2005-01-01 01:45:11 +03:00
}
2005-10-20 11:36:08 +04:00
if ( ! gensec_krb5_state - > gssapi & &
( feature & GENSEC_FEATURE_SEAL ) ) {
2007-10-07 02:16:19 +04:00
return true ;
2005-10-20 11:36:08 +04:00
}
2005-01-01 01:45:11 +03:00
2007-10-07 02:16:19 +04:00
return false ;
2005-01-01 01:45:11 +03:00
}
2005-05-16 03:42:11 +04:00
static const char * gensec_krb5_oids [ ] = {
GENSEC_OID_KERBEROS5 ,
GENSEC_OID_KERBEROS5_OLD ,
NULL
} ;
2004-07-11 14:16:36 +04:00
2005-09-21 14:18:40 +04:00
static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
. name = " fake_gssapi_krb5 " ,
2004-07-11 14:16:36 +04:00
. auth_type = DCERPC_AUTH_TYPE_KRB5 ,
2005-05-16 03:42:11 +04:00
. oid = gensec_krb5_oids ,
2005-09-21 14:18:40 +04:00
. client_start = gensec_fake_gssapi_krb5_client_start ,
. server_start = gensec_fake_gssapi_krb5_server_start ,
. update = gensec_krb5_update ,
. magic = gensec_fake_gssapi_krb5_magic ,
. session_key = gensec_krb5_session_key ,
. session_info = gensec_krb5_session_info ,
. have_feature = gensec_krb5_have_feature ,
2007-10-07 02:16:19 +04:00
. enabled = false ,
. kerberos = true ,
2006-09-08 10:21:02 +04:00
. priority = GENSEC_KRB5
2005-09-21 14:18:40 +04:00
} ;
static const struct gensec_security_ops gensec_krb5_security_ops = {
. name = " krb5 " ,
2004-07-11 14:16:36 +04:00
. client_start = gensec_krb5_client_start ,
. server_start = gensec_krb5_server_start ,
. update = gensec_krb5_update ,
. session_key = gensec_krb5_session_key ,
2004-08-12 11:37:49 +04:00
. session_info = gensec_krb5_session_info ,
2005-01-01 01:45:11 +03:00
. have_feature = gensec_krb5_have_feature ,
2005-10-20 11:36:08 +04:00
. wrap = gensec_krb5_wrap ,
. unwrap = gensec_krb5_unwrap ,
2007-10-07 02:16:19 +04:00
. enabled = true ,
. kerberos = true ,
2006-09-08 10:21:02 +04:00
. priority = GENSEC_KRB5
2004-07-11 14:16:36 +04:00
} ;
2008-02-20 21:40:20 +03:00
_PUBLIC_ NTSTATUS gensec_krb5_init ( void )
2004-07-11 14:16:36 +04:00
{
NTSTATUS ret ;
2004-09-17 10:33:19 +04:00
2007-12-10 20:41:38 +03:00
auth_init ( ) ;
2006-04-06 20:08:46 +04:00
2004-11-15 01:47:39 +03:00
ret = gensec_register ( & gensec_krb5_security_ops ) ;
2004-07-11 14:16:36 +04:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 0 , ( " Failed to register '%s' gensec backend! \n " ,
gensec_krb5_security_ops . name ) ) ;
return ret ;
}
2005-09-21 14:18:40 +04:00
ret = gensec_register ( & gensec_fake_gssapi_krb5_security_ops ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 0 , ( " Failed to register '%s' gensec backend! \n " ,
gensec_krb5_security_ops . name ) ) ;
return ret ;
}
2004-07-11 14:16:36 +04:00
return ret ;
}