2010-01-28 10:05:05 +03:00
/*
2005-09-17 05:11:50 +04:00
Unix SMB / CIFS implementation .
Wrapper for krb5_init_context
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005
2005-09-28 05:09:10 +04:00
Copyright ( C ) Andrew Tridgell 2005
Copyright ( C ) Stefan Metzmacher 2004
2005-09-17 05:11:50 +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
2005-09-17 05:11:50 +04:00
( at your option ) any later version .
2010-01-28 10:05:05 +03:00
2005-09-17 05:11:50 +04: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 .
2010-01-28 10:05:05 +03:00
2005-09-17 05:11:50 +04:00
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/>.
2005-09-17 05:11:50 +04:00
*/
# include "includes.h"
# include "system/kerberos.h"
2012-04-24 20:37:13 +04:00
# include "system/gssapi.h"
2009-01-03 14:48:20 +03:00
# include <tevent.h>
2005-09-17 05:11:50 +04:00
# include "auth/kerberos/kerberos.h"
2005-09-28 05:09:10 +04:00
# include "lib/socket/socket.h"
2007-05-17 09:46:45 +04:00
# include "lib/stream/packet.h"
2006-03-11 11:11:33 +03:00
# include "system/network.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2007-12-10 20:41:19 +03:00
# include "libcli/resolve/resolve.h"
2010-11-05 09:08:52 +03:00
# include "../lib/tsocket/tsocket.h"
2012-04-20 21:14:30 +04:00
# include "krb5_init_context.h"
2005-09-28 05:09:10 +04:00
/*
context structure for operations on cldap packets
*/
struct smb_krb5_socket {
struct socket_context * sock ;
/* the fd event */
2008-12-29 22:24:57 +03:00
struct tevent_fd * fde ;
2005-09-28 05:09:10 +04:00
NTSTATUS status ;
2007-05-17 09:46:45 +04:00
DATA_BLOB request , reply ;
2010-01-28 10:05:05 +03:00
2007-05-17 09:46:45 +04:00
struct packet_context * packet ;
2005-09-28 05:09:10 +04:00
size_t partial_read ;
2012-04-25 18:31:12 +04:00
# ifdef SAMBA4_USES_HEIMDAL
2005-09-28 05:09:10 +04:00
krb5_krbhst_info * hi ;
2012-04-25 18:31:12 +04:00
# endif
2005-09-28 05:09:10 +04:00
} ;
2005-09-17 05:11:50 +04:00
2010-01-31 21:28:04 +03:00
static krb5_error_code smb_krb5_context_destroy ( struct smb_krb5_context * ctx )
2005-09-17 05:11:50 +04:00
{
2012-04-20 21:14:30 +04:00
# ifdef SAMBA4_USES_HEIMDAL
if ( ctx - > pvt_log_data ) {
/* Otherwise krb5_free_context will try and close what we
* have already free ( ) ed */
krb5_set_warn_dest ( ctx - > krb5_context , NULL ) ;
krb5_closelog ( ctx - > krb5_context ,
( krb5_log_facility * ) ctx - > pvt_log_data ) ;
}
# endif
2010-01-31 21:28:04 +03:00
krb5_free_context ( ctx - > krb5_context ) ;
2005-09-17 05:11:50 +04:00
return 0 ;
}
2012-04-25 18:31:12 +04:00
# ifdef SAMBA4_USES_HEIMDAL
2005-09-17 05:11:50 +04:00
/* We never close down the DEBUG system, and no need to unreference the use */
2009-02-02 10:17:20 +03:00
static void smb_krb5_debug_close ( void * private_data ) {
2005-09-17 05:11:50 +04:00
return ;
}
2012-04-25 18:31:12 +04:00
# endif
2005-09-17 05:11:50 +04:00
2012-04-20 21:14:30 +04:00
# ifdef SAMBA4_USES_HEIMDAL
2009-02-02 10:17:20 +03:00
static void smb_krb5_debug_wrapper ( const char * timestr , const char * msg , void * private_data )
2005-09-17 05:11:50 +04:00
{
2010-01-16 09:57:17 +03:00
DEBUG ( 3 , ( " Kerberos: %s \n " , msg ) ) ;
2005-09-17 05:11:50 +04:00
}
2012-04-20 21:14:30 +04:00
# endif
2005-09-17 05:11:50 +04:00
2012-04-22 00:35:48 +04:00
# ifdef SAMBA4_USES_HEIMDAL
2005-09-28 05:09:10 +04:00
/*
handle recv events on a smb_krb5 socket
*/
static void smb_krb5_socket_recv ( struct smb_krb5_socket * smb_krb5 )
{
TALLOC_CTX * tmp_ctx = talloc_new ( smb_krb5 ) ;
DATA_BLOB blob ;
size_t nread , dsize ;
2007-05-17 09:46:45 +04:00
smb_krb5 - > status = socket_pending ( smb_krb5 - > sock , & dsize ) ;
if ( ! NT_STATUS_IS_OK ( smb_krb5 - > status ) ) {
2005-09-28 05:09:10 +04:00
talloc_free ( tmp_ctx ) ;
return ;
}
2010-01-28 10:05:05 +03:00
2007-05-17 09:46:45 +04:00
blob = data_blob_talloc ( tmp_ctx , NULL , dsize ) ;
if ( blob . data = = NULL & & dsize ! = 0 ) {
smb_krb5 - > status = NT_STATUS_NO_MEMORY ;
talloc_free ( tmp_ctx ) ;
return ;
}
2010-01-28 10:05:05 +03:00
2007-05-17 09:46:45 +04:00
smb_krb5 - > status = socket_recv ( smb_krb5 - > sock , blob . data , blob . length , & nread ) ;
if ( ! NT_STATUS_IS_OK ( smb_krb5 - > status ) ) {
talloc_free ( tmp_ctx ) ;
return ;
}
blob . length = nread ;
2010-01-28 10:05:05 +03:00
2007-05-17 09:46:45 +04:00
if ( nread = = 0 ) {
smb_krb5 - > status = NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
talloc_free ( tmp_ctx ) ;
return ;
}
2010-01-28 10:05:05 +03:00
2011-04-01 08:57:39 +04:00
DEBUG ( 4 , ( " Received smb_krb5 packet of length %d \n " ,
2007-05-17 09:46:45 +04:00
( int ) blob . length ) ) ;
2010-01-28 10:05:05 +03:00
2007-05-17 09:46:45 +04:00
talloc_steal ( smb_krb5 , blob . data ) ;
smb_krb5 - > reply = blob ;
talloc_free ( tmp_ctx ) ;
}
2009-02-02 10:17:20 +03:00
static NTSTATUS smb_krb5_full_packet ( void * private_data , DATA_BLOB data )
2007-05-17 09:46:45 +04:00
{
2009-02-02 10:17:20 +03:00
struct smb_krb5_socket * smb_krb5 = talloc_get_type ( private_data , struct smb_krb5_socket ) ;
2007-05-17 09:46:45 +04:00
talloc_steal ( smb_krb5 , data . data ) ;
smb_krb5 - > reply = data ;
smb_krb5 - > reply . length - = 4 ;
smb_krb5 - > reply . data + = 4 ;
return NT_STATUS_OK ;
2005-09-28 05:09:10 +04:00
}
/*
handle request timeouts
*/
2010-01-28 10:05:05 +03:00
static void smb_krb5_request_timeout ( struct tevent_context * event_ctx ,
2008-12-29 22:24:57 +03:00
struct tevent_timer * te , struct timeval t ,
2009-02-02 10:17:20 +03:00
void * private_data )
2005-09-28 05:09:10 +04:00
{
2009-02-02 10:17:20 +03:00
struct smb_krb5_socket * smb_krb5 = talloc_get_type ( private_data , struct smb_krb5_socket ) ;
2005-10-14 10:06:18 +04:00
DEBUG ( 5 , ( " Timed out smb_krb5 packet \n " ) ) ;
2007-05-17 09:46:45 +04:00
smb_krb5 - > status = NT_STATUS_IO_TIMEOUT ;
}
2009-02-02 10:17:20 +03:00
static void smb_krb5_error_handler ( void * private_data , NTSTATUS status )
2007-05-17 09:46:45 +04:00
{
2009-02-02 10:17:20 +03:00
struct smb_krb5_socket * smb_krb5 = talloc_get_type ( private_data , struct smb_krb5_socket ) ;
2007-05-17 09:46:45 +04:00
smb_krb5 - > status = status ;
2005-09-28 05:09:10 +04:00
}
/*
handle send events on a smb_krb5 socket
*/
static void smb_krb5_socket_send ( struct smb_krb5_socket * smb_krb5 )
{
NTSTATUS status ;
size_t len ;
2010-01-28 10:05:05 +03:00
2005-09-28 05:09:10 +04:00
len = smb_krb5 - > request . length ;
2006-04-30 09:58:31 +04:00
status = socket_send ( smb_krb5 - > sock , & smb_krb5 - > request , & len ) ;
2005-09-28 05:09:10 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) return ;
2010-01-28 10:05:05 +03:00
2009-01-03 14:48:20 +03:00
TEVENT_FD_READABLE ( smb_krb5 - > fde ) ;
2005-09-28 05:09:10 +04:00
2009-01-03 14:48:20 +03:00
TEVENT_FD_NOT_WRITEABLE ( smb_krb5 - > fde ) ;
2005-09-28 05:09:10 +04:00
return ;
}
/*
handle fd events on a smb_krb5_socket
*/
2008-12-29 22:24:57 +03:00
static void smb_krb5_socket_handler ( struct tevent_context * ev , struct tevent_fd * fde ,
2009-02-02 10:17:20 +03:00
uint16_t flags , void * private_data )
2005-09-28 05:09:10 +04:00
{
2009-02-02 10:17:20 +03:00
struct smb_krb5_socket * smb_krb5 = talloc_get_type ( private_data , struct smb_krb5_socket ) ;
2007-05-17 09:46:45 +04:00
switch ( smb_krb5 - > hi - > proto ) {
case KRB5_KRBHST_UDP :
2009-01-03 14:48:20 +03:00
if ( flags & TEVENT_FD_READ ) {
2007-05-17 09:46:45 +04:00
smb_krb5_socket_recv ( smb_krb5 ) ;
2007-05-18 09:47:33 +04:00
return ;
2007-05-17 09:46:45 +04:00
}
2009-01-03 14:48:20 +03:00
if ( flags & TEVENT_FD_WRITE ) {
2007-05-18 09:47:33 +04:00
smb_krb5_socket_send ( smb_krb5 ) ;
return ;
}
/* not reached */
return ;
2007-05-17 09:46:45 +04:00
case KRB5_KRBHST_TCP :
2009-01-03 14:48:20 +03:00
if ( flags & TEVENT_FD_READ ) {
2007-05-17 09:46:45 +04:00
packet_recv ( smb_krb5 - > packet ) ;
2007-05-18 09:47:33 +04:00
return ;
2007-05-17 09:46:45 +04:00
}
2009-01-03 14:48:20 +03:00
if ( flags & TEVENT_FD_WRITE ) {
2007-05-17 09:46:45 +04:00
packet_queue_run ( smb_krb5 - > packet ) ;
2007-05-18 09:47:33 +04:00
return ;
2007-05-17 09:46:45 +04:00
}
2007-05-18 09:47:33 +04:00
/* not reached */
return ;
2007-05-17 09:46:45 +04:00
case KRB5_KRBHST_HTTP :
/* can't happen */
break ;
2005-09-28 05:09:10 +04:00
}
}
2015-01-05 04:54:45 +03:00
static krb5_error_code smb_krb5_send_and_recv_func_int ( krb5_context context ,
struct tevent_context * ev ,
krb5_krbhst_info * hi ,
struct addrinfo * ai ,
krb5_send_to_kdc_func func ,
void * data ,
time_t timeout ,
const krb5_data * send_buf ,
krb5_data * recv_buf )
2005-09-28 05:09:10 +04:00
{
krb5_error_code ret ;
NTSTATUS status ;
const char * name ;
2015-01-05 04:54:45 +03:00
struct addrinfo * a ;
2005-09-28 05:09:10 +04:00
struct smb_krb5_socket * smb_krb5 ;
2010-10-11 09:53:08 +04:00
DATA_BLOB send_blob ;
2005-09-28 05:09:10 +04:00
2015-02-05 22:53:21 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
if ( frame = = NULL ) {
2010-10-11 09:53:08 +04:00
return ENOMEM ;
}
send_blob = data_blob_const ( send_buf - > data , send_buf - > length ) ;
2005-09-28 05:09:10 +04:00
2010-11-14 06:26:06 +03:00
for ( a = ai ; a ; a = a - > ai_next ) {
2010-11-14 05:40:02 +03:00
struct socket_address * remote_addr ;
2015-02-05 22:53:21 +03:00
smb_krb5 = talloc ( frame , struct smb_krb5_socket ) ;
2005-09-28 05:09:10 +04:00
if ( ! smb_krb5 ) {
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2005-09-28 05:09:10 +04:00
return ENOMEM ;
}
smb_krb5 - > hi = hi ;
2010-01-28 10:05:05 +03:00
2005-09-28 05:09:10 +04:00
switch ( a - > ai_family ) {
case PF_INET :
name = " ipv4 " ;
break ;
2007-04-30 15:27:41 +04:00
# ifdef HAVE_IPV6
2005-09-28 05:09:10 +04:00
case PF_INET6 :
name = " ipv6 " ;
break ;
2006-05-25 02:17:01 +04:00
# endif
2005-09-28 05:09:10 +04:00
default :
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2005-09-28 05:09:10 +04:00
return EINVAL ;
}
2010-01-28 10:05:05 +03:00
2005-09-28 05:09:10 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
switch ( hi - > proto ) {
case KRB5_KRBHST_UDP :
2008-11-02 03:03:46 +03:00
status = socket_create ( name , SOCKET_TYPE_DGRAM , & smb_krb5 - > sock , 0 ) ;
2006-03-13 09:56:31 +03:00
break ;
2005-09-28 05:09:10 +04:00
case KRB5_KRBHST_TCP :
2008-11-02 03:03:46 +03:00
status = socket_create ( name , SOCKET_TYPE_STREAM , & smb_krb5 - > sock , 0 ) ;
2006-03-13 09:56:31 +03:00
break ;
2005-09-28 05:09:10 +04:00
case KRB5_KRBHST_HTTP :
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2005-09-28 05:09:10 +04:00
return EINVAL ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( smb_krb5 ) ;
continue ;
}
talloc_steal ( smb_krb5 , smb_krb5 - > sock ) ;
2010-01-28 10:05:05 +03:00
remote_addr = socket_address_from_sockaddr ( smb_krb5 , a - > ai_addr , a - > ai_addrlen ) ;
2006-01-10 01:12:53 +03:00
if ( ! remote_addr ) {
2005-09-28 05:09:10 +04:00
talloc_free ( smb_krb5 ) ;
2006-01-10 01:12:53 +03:00
continue ;
2005-09-28 05:09:10 +04:00
}
2006-01-10 01:12:53 +03:00
2008-12-18 01:13:44 +03:00
status = socket_connect_ev ( smb_krb5 - > sock , NULL , remote_addr , 0 , ev ) ;
2005-09-28 05:09:10 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( smb_krb5 ) ;
continue ;
}
2007-05-18 09:47:33 +04:00
/* Setup the FDE, start listening for read events
* from the start ( otherwise we may miss a socket
* drop ) and mark as AUTOCLOSE along with the fde */
/* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */
2009-01-03 14:47:24 +03:00
smb_krb5 - > fde = tevent_add_fd ( ev , smb_krb5 - > sock ,
socket_get_fd ( smb_krb5 - > sock ) ,
TEVENT_FD_READ ,
smb_krb5_socket_handler , smb_krb5 ) ;
2007-05-17 06:21:07 +04:00
/* its now the job of the event layer to close the socket */
2009-01-03 14:47:24 +03:00
tevent_fd_set_close_fn ( smb_krb5 - > fde , socket_tevent_fd_close_fn ) ;
2007-05-17 06:21:07 +04:00
socket_set_flags ( smb_krb5 - > sock , SOCKET_FLAG_NOCLOSE ) ;
2005-09-28 05:09:10 +04:00
2009-01-03 14:48:20 +03:00
tevent_add_timer ( ev , smb_krb5 ,
timeval_current_ofs ( timeout , 0 ) ,
smb_krb5_request_timeout , smb_krb5 ) ;
2005-09-28 05:09:10 +04:00
2007-05-17 09:46:45 +04:00
smb_krb5 - > status = NT_STATUS_OK ;
smb_krb5 - > reply = data_blob ( NULL , 0 ) ;
2005-09-28 05:09:10 +04:00
switch ( hi - > proto ) {
case KRB5_KRBHST_UDP :
2009-01-03 14:48:20 +03:00
TEVENT_FD_WRITEABLE ( smb_krb5 - > fde ) ;
2005-09-28 05:09:10 +04:00
smb_krb5 - > request = send_blob ;
break ;
case KRB5_KRBHST_TCP :
2007-05-17 09:46:45 +04:00
smb_krb5 - > packet = packet_init ( smb_krb5 ) ;
if ( smb_krb5 - > packet = = NULL ) {
talloc_free ( smb_krb5 ) ;
return ENOMEM ;
}
packet_set_private ( smb_krb5 - > packet , smb_krb5 ) ;
packet_set_socket ( smb_krb5 - > packet , smb_krb5 - > sock ) ;
packet_set_callback ( smb_krb5 - > packet , smb_krb5_full_packet ) ;
packet_set_full_request ( smb_krb5 - > packet , packet_full_request_u32 ) ;
packet_set_error_handler ( smb_krb5 - > packet , smb_krb5_error_handler ) ;
packet_set_event_context ( smb_krb5 - > packet , ev ) ;
packet_set_fde ( smb_krb5 - > packet , smb_krb5 - > fde ) ;
2005-09-28 05:09:10 +04:00
smb_krb5 - > request = data_blob_talloc ( smb_krb5 , NULL , send_blob . length + 4 ) ;
RSIVAL ( smb_krb5 - > request . data , 0 , send_blob . length ) ;
memcpy ( smb_krb5 - > request . data + 4 , send_blob . data , send_blob . length ) ;
2007-05-17 09:46:45 +04:00
packet_send ( smb_krb5 - > packet , smb_krb5 - > request ) ;
2005-09-28 05:09:10 +04:00
break ;
case KRB5_KRBHST_HTTP :
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2005-09-28 05:09:10 +04:00
return EINVAL ;
}
2007-05-17 09:46:45 +04:00
while ( ( NT_STATUS_IS_OK ( smb_krb5 - > status ) ) & & ! smb_krb5 - > reply . length ) {
2009-01-03 14:48:20 +03:00
if ( tevent_loop_once ( ev ) ! = 0 ) {
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2005-09-28 05:09:10 +04:00
return EINVAL ;
}
2010-10-11 09:53:08 +04:00
2015-01-05 04:54:45 +03:00
if ( func ) {
/* After each and every event loop, reset the
* send_to_kdc pointers to what they were when
* we entered this loop . That way , if a
* nested event has invalidated them , we put
* it back before we return to the heimdal
* code */
ret = krb5_set_send_to_kdc_func ( context ,
func ,
data ) ;
if ( ret ! = 0 ) {
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2015-01-05 04:54:45 +03:00
return ret ;
}
2010-10-11 09:53:08 +04:00
}
2005-09-28 05:09:10 +04:00
}
2007-05-17 09:46:45 +04:00
if ( NT_STATUS_EQUAL ( smb_krb5 - > status , NT_STATUS_IO_TIMEOUT ) ) {
2005-09-28 05:09:10 +04:00
talloc_free ( smb_krb5 ) ;
continue ;
}
2007-05-17 09:46:45 +04:00
if ( ! NT_STATUS_IS_OK ( smb_krb5 - > status ) ) {
2010-11-05 09:08:52 +03:00
struct tsocket_address * addr = socket_address_to_tsocket_address ( smb_krb5 , remote_addr ) ;
const char * addr_string = NULL ;
if ( addr ) {
addr_string = tsocket_address_inet_addr_string ( addr , smb_krb5 ) ;
} else {
addr_string = NULL ;
}
DEBUG ( 2 , ( " Error reading smb_krb5 reply packet: %s from %s \n " , nt_errstr ( smb_krb5 - > status ) ,
addr_string ) ) ;
2005-09-28 05:09:10 +04:00
talloc_free ( smb_krb5 ) ;
continue ;
}
ret = krb5_data_copy ( recv_buf , smb_krb5 - > reply . data , smb_krb5 - > reply . length ) ;
if ( ret ) {
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2005-09-28 05:09:10 +04:00
return ret ;
}
talloc_free ( smb_krb5 ) ;
2010-01-28 10:05:05 +03:00
2005-09-28 05:09:10 +04:00
break ;
}
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2005-09-28 05:09:10 +04:00
if ( a ) {
return 0 ;
}
return KRB5_KDC_UNREACH ;
}
2015-01-05 04:54:45 +03:00
krb5_error_code smb_krb5_send_and_recv_func ( krb5_context context ,
void * data ,
krb5_krbhst_info * hi ,
time_t timeout ,
const krb5_data * send_buf ,
krb5_data * recv_buf )
{
krb5_error_code ret ;
struct addrinfo * ai ;
struct tevent_context * ev ;
2015-02-05 22:53:21 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
if ( frame = = NULL ) {
2015-01-05 04:54:45 +03:00
return ENOMEM ;
}
2015-02-05 22:53:21 +03:00
if ( data = = NULL ) {
2015-01-05 04:54:45 +03:00
/* If no event context was available, then create one for this loop */
2015-02-05 22:53:21 +03:00
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
TALLOC_FREE ( frame ) ;
2015-01-05 04:54:45 +03:00
return ENOMEM ;
}
} else {
ev = talloc_get_type_abort ( data , struct tevent_context ) ;
}
ret = krb5_krbhst_get_addrinfo ( context , hi , & ai ) ;
if ( ret ) {
2015-02-05 22:53:21 +03:00
TALLOC_FREE ( frame ) ;
2015-01-05 04:54:45 +03:00
return ret ;
}
2015-02-05 22:53:21 +03:00
ret = smb_krb5_send_and_recv_func_int ( context , ev , hi , ai , smb_krb5_send_and_recv_func , data , timeout , send_buf , recv_buf ) ;
TALLOC_FREE ( frame ) ;
return ret ;
2015-01-05 04:54:45 +03:00
}
krb5_error_code smb_krb5_send_and_recv_func_forced ( krb5_context context ,
void * data , /* struct addrinfo */
krb5_krbhst_info * hi ,
time_t timeout ,
const krb5_data * send_buf ,
krb5_data * recv_buf )
{
2015-02-05 22:53:21 +03:00
krb5_error_code k5ret ;
2015-01-05 04:54:45 +03:00
struct addrinfo * ai = data ;
struct tevent_context * ev ;
2015-02-05 22:53:21 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
if ( frame = = NULL ) {
2015-01-05 04:54:45 +03:00
return ENOMEM ;
}
2015-02-05 22:53:21 +03:00
/* no event context is passed in, create one for this loop */
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
TALLOC_FREE ( frame ) ;
2015-01-05 04:54:45 +03:00
return ENOMEM ;
}
/* No need to pass in send_and_recv functions, we won't nest on this private event loop */
2015-02-05 22:53:21 +03:00
k5ret = smb_krb5_send_and_recv_func_int ( context , ev , hi , ai , NULL , NULL ,
timeout , send_buf , recv_buf ) ;
TALLOC_FREE ( frame ) ;
return k5ret ;
2015-01-05 04:54:45 +03:00
}
2012-04-22 00:35:48 +04:00
# endif
2005-09-28 05:09:10 +04:00
2010-01-31 21:28:04 +03:00
krb5_error_code
smb_krb5_init_context_basic ( TALLOC_CTX * tmp_ctx ,
struct loadparm_context * lp_ctx ,
krb5_context * _krb5_context )
2005-09-17 05:11:50 +04:00
{
krb5_error_code ret ;
2012-04-25 18:31:12 +04:00
# ifdef SAMBA4_USES_HEIMDAL
2007-01-24 05:48:40 +03:00
char * * config_files ;
2009-10-12 21:09:18 +04:00
const char * config_file , * realm ;
2012-04-25 18:31:12 +04:00
# endif
2010-01-31 21:28:04 +03:00
krb5_context krb5_ctx ;
2010-01-28 10:05:05 +03:00
2005-09-17 05:11:50 +04:00
initialize_krb5_error_table ( ) ;
2010-01-28 10:05:05 +03:00
2010-01-31 21:28:04 +03:00
ret = krb5_init_context ( & krb5_ctx ) ;
2005-09-17 05:11:50 +04:00
if ( ret ) {
2010-01-28 10:05:05 +03:00
DEBUG ( 1 , ( " krb5_init_context failed (%s) \n " ,
2005-09-17 05:11:50 +04:00
error_message ( ret ) ) ) ;
return ret ;
}
2012-04-25 18:31:12 +04:00
/* The MIT Kerberos build relies on using the system krb5.conf file.
* If you really want to use another file please set KRB5_CONFIG
* accordingly . */
# ifdef SAMBA4_USES_HEIMDAL
2011-04-29 06:46:10 +04:00
config_file = lpcfg_config_path ( tmp_ctx , lp_ctx , " krb5.conf " ) ;
2007-01-24 05:48:40 +03:00
if ( ! config_file ) {
2010-01-31 21:28:04 +03:00
krb5_free_context ( krb5_ctx ) ;
2007-01-24 05:48:40 +03:00
return ENOMEM ;
}
2010-01-28 10:05:05 +03:00
2007-01-24 05:48:40 +03:00
/* Use our local krb5.conf file by default */
2012-04-25 18:19:07 +04:00
ret = krb5_prepend_config_files_default ( config_file , & config_files ) ;
2007-01-24 05:48:40 +03:00
if ( ret ) {
2010-01-28 10:05:05 +03:00
DEBUG ( 1 , ( " krb5_prepend_config_files_default failed (%s) \n " ,
2010-01-31 21:28:04 +03:00
smb_get_krb5_error_message ( krb5_ctx , ret , tmp_ctx ) ) ) ;
krb5_free_context ( krb5_ctx ) ;
2007-01-24 05:48:40 +03:00
return ret ;
}
2010-01-31 21:28:04 +03:00
ret = krb5_set_config_files ( krb5_ctx , config_files ) ;
2007-01-24 05:48:40 +03:00
krb5_free_config_files ( config_files ) ;
if ( ret ) {
2010-01-28 10:05:05 +03:00
DEBUG ( 1 , ( " krb5_set_config_files failed (%s) \n " ,
2010-01-31 21:28:04 +03:00
smb_get_krb5_error_message ( krb5_ctx , ret , tmp_ctx ) ) ) ;
krb5_free_context ( krb5_ctx ) ;
2007-01-24 05:48:40 +03:00
return ret ;
}
2010-01-28 10:05:05 +03:00
2010-07-16 08:32:42 +04:00
realm = lpcfg_realm ( lp_ctx ) ;
2009-10-12 21:09:18 +04:00
if ( realm ! = NULL ) {
2010-01-31 21:28:04 +03:00
ret = krb5_set_default_realm ( krb5_ctx , realm ) ;
2005-09-17 05:11:50 +04:00
if ( ret ) {
2010-01-28 10:05:05 +03:00
DEBUG ( 1 , ( " krb5_set_default_realm failed (%s) \n " ,
2010-01-31 21:28:04 +03:00
smb_get_krb5_error_message ( krb5_ctx , ret , tmp_ctx ) ) ) ;
krb5_free_context ( krb5_ctx ) ;
2005-09-17 05:11:50 +04:00
return ret ;
}
}
2012-04-25 18:31:12 +04:00
# endif
2010-01-31 21:28:04 +03:00
* _krb5_context = krb5_ctx ;
return 0 ;
}
krb5_error_code smb_krb5_init_context ( void * parent_ctx ,
struct loadparm_context * lp_ctx ,
2010-10-11 09:53:08 +04:00
struct smb_krb5_context * * smb_krb5_context )
2010-01-31 21:28:04 +03:00
{
krb5_error_code ret ;
TALLOC_CTX * tmp_ctx ;
2012-04-20 21:14:30 +04:00
krb5_context kctx ;
# ifdef SAMBA4_USES_HEIMDAL
krb5_log_facility * logf ;
# endif
2010-01-31 21:28:04 +03:00
initialize_krb5_error_table ( ) ;
tmp_ctx = talloc_new ( parent_ctx ) ;
2010-10-11 09:53:08 +04:00
* smb_krb5_context = talloc_zero ( tmp_ctx , struct smb_krb5_context ) ;
2010-01-31 21:28:04 +03:00
if ( ! * smb_krb5_context | | ! tmp_ctx ) {
talloc_free ( tmp_ctx ) ;
return ENOMEM ;
}
2012-04-20 21:14:30 +04:00
ret = smb_krb5_init_context_basic ( tmp_ctx , lp_ctx , & kctx ) ;
2010-01-31 21:28:04 +03:00
if ( ret ) {
DEBUG ( 1 , ( " smb_krb5_context_init_basic failed (%s) \n " ,
error_message ( ret ) ) ) ;
talloc_free ( tmp_ctx ) ;
return ret ;
}
2012-04-20 21:14:30 +04:00
( * smb_krb5_context ) - > krb5_context = kctx ;
2010-01-31 21:28:04 +03:00
2012-04-20 21:14:30 +04:00
talloc_set_destructor ( * smb_krb5_context , smb_krb5_context_destroy ) ;
# ifdef SAMBA4_USES_HEIMDAL
2005-09-17 05:11:50 +04:00
/* TODO: Should we have a different name here? */
2012-04-20 21:14:30 +04:00
ret = krb5_initlog ( kctx , " Samba " , & logf ) ;
2010-01-28 10:05:05 +03:00
2005-09-17 05:11:50 +04:00
if ( ret ) {
2010-01-28 10:05:05 +03:00
DEBUG ( 1 , ( " krb5_initlog failed (%s) \n " ,
2012-04-20 21:14:30 +04:00
smb_get_krb5_error_message ( kctx , ret , tmp_ctx ) ) ) ;
2005-09-17 05:11:50 +04:00
talloc_free ( tmp_ctx ) ;
return ret ;
}
2012-04-20 21:14:30 +04:00
( * smb_krb5_context ) - > pvt_log_data = logf ;
2005-09-17 05:11:50 +04:00
2012-04-20 21:14:30 +04:00
ret = krb5_addlog_func ( kctx , logf , 0 /* min */ , - 1 /* max */ ,
smb_krb5_debug_wrapper ,
smb_krb5_debug_close , NULL ) ;
2005-09-17 05:11:50 +04:00
if ( ret ) {
2010-01-28 10:05:05 +03:00
DEBUG ( 1 , ( " krb5_addlog_func failed (%s) \n " ,
2012-04-20 21:14:30 +04:00
smb_get_krb5_error_message ( kctx , ret , tmp_ctx ) ) ) ;
2005-09-17 05:11:50 +04:00
talloc_free ( tmp_ctx ) ;
return ret ;
}
2012-04-20 21:14:30 +04:00
krb5_set_warn_dest ( kctx , logf ) ;
2005-09-17 05:11:50 +04:00
2005-09-20 11:03:47 +04:00
/* Set options in kerberos */
2012-04-20 21:14:30 +04:00
krb5_set_dns_canonicalize_hostname ( kctx ,
lpcfg_parm_bool ( lp_ctx , NULL , " krb5 " ,
" set_dns_canonicalize " , false ) ) ;
# endif
talloc_steal ( parent_ctx , * smb_krb5_context ) ;
talloc_free ( tmp_ctx ) ;
2005-09-28 05:09:10 +04:00
2005-09-17 05:11:50 +04:00
return 0 ;
}
2012-04-22 00:35:48 +04:00
# ifdef SAMBA4_USES_HEIMDAL
2010-10-11 09:53:08 +04:00
krb5_error_code smb_krb5_context_set_event_ctx ( struct smb_krb5_context * smb_krb5_context ,
struct tevent_context * ev ,
struct tevent_context * * previous_ev )
{
int ret ;
if ( ! ev ) {
return EINVAL ;
}
2010-11-04 04:52:08 +03:00
* previous_ev = smb_krb5_context - > current_ev ;
2010-10-11 09:53:08 +04:00
smb_krb5_context - > current_ev = talloc_reference ( smb_krb5_context , ev ) ;
if ( ! smb_krb5_context - > current_ev ) {
return ENOMEM ;
}
/* Set use of our socket lib */
ret = krb5_set_send_to_kdc_func ( smb_krb5_context - > krb5_context ,
smb_krb5_send_and_recv_func ,
ev ) ;
if ( ret ) {
TALLOC_CTX * tmp_ctx = talloc_new ( NULL ) ;
DEBUG ( 1 , ( " krb5_set_send_recv_func failed (%s) \n " ,
smb_get_krb5_error_message ( smb_krb5_context - > krb5_context , ret , tmp_ctx ) ) ) ;
talloc_free ( tmp_ctx ) ;
talloc_unlink ( smb_krb5_context , smb_krb5_context - > current_ev ) ;
smb_krb5_context - > current_ev = NULL ;
return ret ;
}
return 0 ;
}
krb5_error_code smb_krb5_context_remove_event_ctx ( struct smb_krb5_context * smb_krb5_context ,
struct tevent_context * previous_ev ,
struct tevent_context * ev )
{
int ret ;
talloc_unlink ( smb_krb5_context , ev ) ;
/* If there was a mismatch with things happening on a stack, then don't wipe things */
smb_krb5_context - > current_ev = previous_ev ;
/* Set use of our socket lib */
ret = krb5_set_send_to_kdc_func ( smb_krb5_context - > krb5_context ,
smb_krb5_send_and_recv_func ,
previous_ev ) ;
if ( ret ) {
TALLOC_CTX * tmp_ctx = talloc_new ( NULL ) ;
DEBUG ( 1 , ( " krb5_set_send_recv_func failed (%s) \n " ,
smb_get_krb5_error_message ( smb_krb5_context - > krb5_context , ret , tmp_ctx ) ) ) ;
talloc_free ( tmp_ctx ) ;
return ret ;
}
return 0 ;
}
2012-04-22 00:35:48 +04:00
# endif