X-Git-Url: http://git.samba.org/samba.git/?p=kai%2Fsamba-autobuild%2F.git;a=blobdiff_plain;f=source4%2Fauth%2Fkerberos%2Fkrb5_init_context.c;h=7fcc8a6048d70efd3175d6638edfa1cc92953e91;hp=acf26cdbe2701f68dabe9f083da098741469c4da;hb=bdde51b26f4f5bcd6b0dcb5557fee40d7bc40207;hpb=1ea47faa979ad2e4aa4cf1f4252aa33aef98dbd8 diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c index acf26cdbe27..7fcc8a6048d 100644 --- a/source4/auth/kerberos/krb5_init_context.c +++ b/source4/auth/kerberos/krb5_init_context.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. Wrapper for krb5_init_context @@ -10,28 +10,28 @@ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (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 along with this program. If not, see . */ #include "includes.h" #include "system/kerberos.h" -#include "heimdal/lib/krb5/krb5_locl.h" +#include "system/gssapi.h" +#include #include "auth/kerberos/kerberos.h" #include "lib/socket/socket.h" #include "lib/stream/packet.h" #include "system/network.h" -#include "lib/events/events.h" -#include "roken.h" #include "param/param.h" #include "libcli/resolve/resolve.h" - +#include "../lib/tsocket/tsocket.h" +#include "krb5_init_context.h" /* context structure for operations on cldap packets */ @@ -39,43 +39,49 @@ struct smb_krb5_socket { struct socket_context *sock; /* the fd event */ - struct fd_event *fde; + struct tevent_fd *fde; NTSTATUS status; DATA_BLOB request, reply; - + struct packet_context *packet; size_t partial_read; - +#ifdef SAMBA4_USES_HEIMDAL krb5_krbhst_info *hi; +#endif }; -static int smb_krb5_context_destroy_1(struct smb_krb5_context *ctx) +static krb5_error_code smb_krb5_context_destroy(struct smb_krb5_context *ctx) { - krb5_free_context(ctx->krb5_context); - return 0; -} - -static int smb_krb5_context_destroy_2(struct smb_krb5_context *ctx) -{ - /* 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, ctx->logf); - smb_krb5_context_destroy_1(ctx); +#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 + krb5_free_context(ctx->krb5_context); return 0; } +#ifdef SAMBA4_USES_HEIMDAL /* We never close down the DEBUG system, and no need to unreference the use */ -static void smb_krb5_debug_close(void *private) { +static void smb_krb5_debug_close(void *private_data) { return; } +#endif -static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private) +#ifdef SAMBA4_USES_HEIMDAL +static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private_data) { - DEBUG(2, ("Kerberos: %s\n", msg)); + DEBUG(3, ("Kerberos: %s\n", msg)); } +#endif +#ifdef SAMBA4_USES_HEIMDAL /* handle recv events on a smb_krb5 socket */ @@ -90,38 +96,38 @@ static void smb_krb5_socket_recv(struct smb_krb5_socket *smb_krb5) talloc_free(tmp_ctx); return; } - + 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; } - + 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; - + if (nread == 0) { smb_krb5->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; talloc_free(tmp_ctx); return; } - - DEBUG(2,("Received smb_krb5 packet of length %d\n", + + DEBUG(4,("Received smb_krb5 packet of length %d\n", (int)blob.length)); - + talloc_steal(smb_krb5, blob.data); smb_krb5->reply = blob; talloc_free(tmp_ctx); } -static NTSTATUS smb_krb5_full_packet(void *private, DATA_BLOB data) +static NTSTATUS smb_krb5_full_packet(void *private_data, DATA_BLOB data) { - struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); + struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket); talloc_steal(smb_krb5, data.data); smb_krb5->reply = data; smb_krb5->reply.length -= 4; @@ -132,18 +138,18 @@ static NTSTATUS smb_krb5_full_packet(void *private, DATA_BLOB data) /* handle request timeouts */ -static void smb_krb5_request_timeout(struct event_context *event_ctx, - struct timed_event *te, struct timeval t, - void *private) +static void smb_krb5_request_timeout(struct tevent_context *event_ctx, + struct tevent_timer *te, struct timeval t, + void *private_data) { - struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); + struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket); DEBUG(5,("Timed out smb_krb5 packet\n")); smb_krb5->status = NT_STATUS_IO_TIMEOUT; } -static void smb_krb5_error_handler(void *private, NTSTATUS status) +static void smb_krb5_error_handler(void *private_data, NTSTATUS status) { - struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); + struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket); smb_krb5->status = status; } @@ -155,15 +161,15 @@ static void smb_krb5_socket_send(struct smb_krb5_socket *smb_krb5) NTSTATUS status; size_t len; - + len = smb_krb5->request.length; status = socket_send(smb_krb5->sock, &smb_krb5->request, &len); if (!NT_STATUS_IS_OK(status)) return; - - EVENT_FD_READABLE(smb_krb5->fde); - EVENT_FD_NOT_WRITEABLE(smb_krb5->fde); + TEVENT_FD_READABLE(smb_krb5->fde); + + TEVENT_FD_NOT_WRITEABLE(smb_krb5->fde); return; } @@ -171,28 +177,28 @@ static void smb_krb5_socket_send(struct smb_krb5_socket *smb_krb5) /* handle fd events on a smb_krb5_socket */ -static void smb_krb5_socket_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private) +static void smb_krb5_socket_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) { - struct smb_krb5_socket *smb_krb5 = talloc_get_type(private, struct smb_krb5_socket); + struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket); switch (smb_krb5->hi->proto) { case KRB5_KRBHST_UDP: - if (flags & EVENT_FD_READ) { + if (flags & TEVENT_FD_READ) { smb_krb5_socket_recv(smb_krb5); return; } - if (flags & EVENT_FD_WRITE) { + if (flags & TEVENT_FD_WRITE) { smb_krb5_socket_send(smb_krb5); return; } /* not reached */ return; case KRB5_KRBHST_TCP: - if (flags & EVENT_FD_READ) { + if (flags & TEVENT_FD_READ) { packet_recv(smb_krb5->packet); return; } - if (flags & EVENT_FD_WRITE) { + if (flags & TEVENT_FD_WRITE) { packet_queue_run(smb_krb5->packet); return; } @@ -204,36 +210,40 @@ static void smb_krb5_socket_handler(struct event_context *ev, struct fd_event *f } } - -krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, - void *data, - krb5_krbhst_info *hi, - const krb5_data *send_buf, - krb5_data *recv_buf) +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) { krb5_error_code ret; NTSTATUS status; - struct socket_address *remote_addr; const char *name; - struct addrinfo *ai, *a; + struct addrinfo *a; struct smb_krb5_socket *smb_krb5; - struct event_context *ev = talloc_get_type(data, struct event_context); - - DATA_BLOB send_blob = data_blob_const(send_buf->data, send_buf->length); + DATA_BLOB send_blob; - ret = krb5_krbhst_get_addrinfo(context, hi, &ai); - if (ret) { - return ret; + TALLOC_CTX *frame = talloc_stackframe(); + if (frame == NULL) { + return ENOMEM; } - for (a = ai; a; a = ai->ai_next) { - smb_krb5 = talloc(NULL, struct smb_krb5_socket); + send_blob = data_blob_const(send_buf->data, send_buf->length); + + for (a = ai; a; a = a->ai_next) { + struct socket_address *remote_addr; + smb_krb5 = talloc(frame, struct smb_krb5_socket); if (!smb_krb5) { + TALLOC_FREE(frame); return ENOMEM; } smb_krb5->hi = hi; - + switch (a->ai_family) { case PF_INET: name = "ipv4"; @@ -244,24 +254,20 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, break; #endif default: - talloc_free(smb_krb5); + TALLOC_FREE(frame); return EINVAL; } - + status = NT_STATUS_INVALID_PARAMETER; switch (hi->proto) { case KRB5_KRBHST_UDP: - if (lp_parm_bool(global_loadparm, NULL, "krb5", "udp", true)) { - status = socket_create(name, SOCKET_TYPE_DGRAM, &smb_krb5->sock, 0); - } + status = socket_create(name, SOCKET_TYPE_DGRAM, &smb_krb5->sock, 0); break; case KRB5_KRBHST_TCP: - if (lp_parm_bool(global_loadparm, NULL, "krb5", "tcp", true)) { - status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0); - } + status = socket_create(name, SOCKET_TYPE_STREAM, &smb_krb5->sock, 0); break; case KRB5_KRBHST_HTTP: - talloc_free(smb_krb5); + TALLOC_FREE(frame); return EINVAL; } if (!NT_STATUS_IS_OK(status)) { @@ -270,44 +276,42 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, } talloc_steal(smb_krb5, smb_krb5->sock); - - remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen); + + remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen); if (!remote_addr) { talloc_free(smb_krb5); continue; } - status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, - NULL, ev); + status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, ev); if (!NT_STATUS_IS_OK(status)) { talloc_free(smb_krb5); continue; } - talloc_free(remote_addr); /* 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) */ - smb_krb5->fde = event_add_fd(ev, smb_krb5->sock, - socket_get_fd(smb_krb5->sock), - EVENT_FD_READ|EVENT_FD_AUTOCLOSE, - smb_krb5_socket_handler, smb_krb5); + 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); /* its now the job of the event layer to close the socket */ + tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn); socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE); - event_add_timed(ev, smb_krb5, - timeval_current_ofs(context->kdc_timeout, 0), - smb_krb5_request_timeout, smb_krb5); + tevent_add_timer(ev, smb_krb5, + timeval_current_ofs(timeout, 0), + smb_krb5_request_timeout, smb_krb5); - smb_krb5->status = NT_STATUS_OK; smb_krb5->reply = data_blob(NULL, 0); switch (hi->proto) { case KRB5_KRBHST_UDP: - EVENT_FD_WRITEABLE(smb_krb5->fde); + TEVENT_FD_WRITEABLE(smb_krb5->fde); smb_krb5->request = send_blob; break; case KRB5_KRBHST_TCP: @@ -331,14 +335,30 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, packet_send(smb_krb5->packet, smb_krb5->request); break; case KRB5_KRBHST_HTTP: - talloc_free(smb_krb5); + TALLOC_FREE(frame); return EINVAL; } while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) { - if (event_loop_once(ev) != 0) { - talloc_free(smb_krb5); + if (tevent_loop_once(ev) != 0) { + TALLOC_FREE(frame); return EINVAL; } + + 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) { + TALLOC_FREE(frame); + return ret; + } + } } if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) { talloc_free(smb_krb5); @@ -346,138 +366,287 @@ krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, } if (!NT_STATUS_IS_OK(smb_krb5->status)) { - DEBUG(2,("Error reading smb_krb5 reply packet: %s\n", nt_errstr(smb_krb5->status))); + 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)); talloc_free(smb_krb5); continue; } ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length); if (ret) { - talloc_free(smb_krb5); + TALLOC_FREE(frame); return ret; } talloc_free(smb_krb5); - + break; } + TALLOC_FREE(frame); if (a) { return 0; } return KRB5_KDC_UNREACH; } -krb5_error_code smb_krb5_init_context(void *parent_ctx, - struct event_context *ev, - struct loadparm_context *lp_ctx, - struct smb_krb5_context **smb_krb5_context) +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; - TALLOC_CTX *tmp_ctx; - char **config_files; - const char *config_file; - - initialize_krb5_error_table(); - - tmp_ctx = talloc_new(parent_ctx); - *smb_krb5_context = talloc(tmp_ctx, struct smb_krb5_context); + struct addrinfo *ai; - if (!*smb_krb5_context || !tmp_ctx) { - talloc_free(tmp_ctx); + struct tevent_context *ev; + TALLOC_CTX *frame = talloc_stackframe(); + if (frame == NULL) { return ENOMEM; } - ret = krb5_init_context(&(*smb_krb5_context)->krb5_context); + if (data == NULL) { + /* If no event context was available, then create one for this loop */ + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + TALLOC_FREE(frame); + return ENOMEM; + } + } else { + ev = talloc_get_type_abort(data, struct tevent_context); + } + + ret = krb5_krbhst_get_addrinfo(context, hi, &ai); if (ret) { - DEBUG(1,("krb5_init_context failed (%s)\n", - error_message(ret))); - talloc_free(tmp_ctx); + TALLOC_FREE(frame); return ret; } - talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy_1); + 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; +} - config_file = config_path(tmp_ctx, lp_ctx, "krb5.conf"); +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) +{ + krb5_error_code k5ret; + struct addrinfo *ai = data; + + struct tevent_context *ev; + TALLOC_CTX *frame = talloc_stackframe(); + if (frame == NULL) { + return ENOMEM; + } + + /* no event context is passed in, create one for this loop */ + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + TALLOC_FREE(frame); + return ENOMEM; + } + + /* No need to pass in send_and_recv functions, we won't nest on this private event loop */ + k5ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, NULL, NULL, + timeout, send_buf, recv_buf); + TALLOC_FREE(frame); + return k5ret; +} +#endif + +krb5_error_code +smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx, + struct loadparm_context *lp_ctx, + krb5_context *_krb5_context) +{ + krb5_error_code ret; +#ifdef SAMBA4_USES_HEIMDAL + char **config_files; + const char *config_file, *realm; +#endif + krb5_context krb5_ctx; + + initialize_krb5_error_table(); + + ret = krb5_init_context(&krb5_ctx); + if (ret) { + DEBUG(1,("krb5_init_context failed (%s)\n", + error_message(ret))); + return ret; + } + + /* 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 + config_file = lpcfg_config_path(tmp_ctx, lp_ctx, "krb5.conf"); if (!config_file) { - talloc_free(tmp_ctx); + krb5_free_context(krb5_ctx); return ENOMEM; } - + /* Use our local krb5.conf file by default */ ret = krb5_prepend_config_files_default(config_file, &config_files); if (ret) { - DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n", - smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); - talloc_free(tmp_ctx); + DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n", + smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); + krb5_free_context(krb5_ctx); return ret; } - ret = krb5_set_config_files((*smb_krb5_context)->krb5_context, - config_files); + ret = krb5_set_config_files(krb5_ctx, config_files); krb5_free_config_files(config_files); if (ret) { - DEBUG(1,("krb5_set_config_files failed (%s)\n", - smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); - talloc_free(tmp_ctx); + DEBUG(1,("krb5_set_config_files failed (%s)\n", + smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); + krb5_free_context(krb5_ctx); return ret; } - - if (lp_realm(lp_ctx) && *lp_realm(lp_ctx)) { - char *upper_realm = strupper_talloc(tmp_ctx, lp_realm(lp_ctx)); - if (!upper_realm) { - DEBUG(1,("gensec_krb5_start: could not uppercase realm: %s\n", lp_realm(lp_ctx))); - talloc_free(tmp_ctx); - return ENOMEM; - } - ret = krb5_set_default_realm((*smb_krb5_context)->krb5_context, upper_realm); + + realm = lpcfg_realm(lp_ctx); + if (realm != NULL) { + ret = krb5_set_default_realm(krb5_ctx, realm); if (ret) { - DEBUG(1,("krb5_set_default_realm failed (%s)\n", - smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); - talloc_free(tmp_ctx); + DEBUG(1,("krb5_set_default_realm failed (%s)\n", + smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); + krb5_free_context(krb5_ctx); return ret; } } +#endif + *_krb5_context = krb5_ctx; + return 0; +} - /* TODO: Should we have a different name here? */ - ret = krb5_initlog((*smb_krb5_context)->krb5_context, "Samba", &(*smb_krb5_context)->logf); - +krb5_error_code smb_krb5_init_context(void *parent_ctx, + struct loadparm_context *lp_ctx, + struct smb_krb5_context **smb_krb5_context) +{ + krb5_error_code ret; + TALLOC_CTX *tmp_ctx; + krb5_context kctx; +#ifdef SAMBA4_USES_HEIMDAL + krb5_log_facility *logf; +#endif + + initialize_krb5_error_table(); + + tmp_ctx = talloc_new(parent_ctx); + *smb_krb5_context = talloc_zero(tmp_ctx, struct smb_krb5_context); + + if (!*smb_krb5_context || !tmp_ctx) { + talloc_free(tmp_ctx); + return ENOMEM; + } + + ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, &kctx); if (ret) { - DEBUG(1,("krb5_initlog failed (%s)\n", - smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); + DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n", + error_message(ret))); talloc_free(tmp_ctx); return ret; } + (*smb_krb5_context)->krb5_context = kctx; + + talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy); - talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy_2); +#ifdef SAMBA4_USES_HEIMDAL + /* TODO: Should we have a different name here? */ + ret = krb5_initlog(kctx, "Samba", &logf); - ret = krb5_addlog_func((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf, 0 /* min */, -1 /* max */, - smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL); if (ret) { - DEBUG(1,("krb5_addlog_func failed (%s)\n", - smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); + DEBUG(1,("krb5_initlog failed (%s)\n", + smb_get_krb5_error_message(kctx, ret, tmp_ctx))); talloc_free(tmp_ctx); return ret; } - krb5_set_warn_dest((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf); + (*smb_krb5_context)->pvt_log_data = logf; - /* 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); + ret = krb5_addlog_func(kctx, logf, 0 /* min */, -1 /* max */, + smb_krb5_debug_wrapper, + smb_krb5_debug_close, NULL); if (ret) { - DEBUG(1,("krb5_set_send_recv_func failed (%s)\n", - smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); + DEBUG(1,("krb5_addlog_func failed (%s)\n", + smb_get_krb5_error_message(kctx, ret, tmp_ctx))); talloc_free(tmp_ctx); return ret; } + krb5_set_warn_dest(kctx, logf); + /* Set options in kerberos */ + + 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); - /* Set options in kerberos */ + return 0; +} + +#ifdef SAMBA4_USES_HEIMDAL +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; + } - krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context, - lp_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false)); + *previous_ev = smb_krb5_context->current_ev; + 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; +} +#endif