Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Wrapper for krb5_init_context
4 :
5 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
6 : Copyright (C) Andrew Tridgell 2005
7 : Copyright (C) Stefan Metzmacher 2004
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "system/kerberos.h"
25 : #include "system/gssapi.h"
26 : #include <tevent.h>
27 : #include "auth/kerberos/kerberos.h"
28 : #include "lib/socket/socket.h"
29 : #include "lib/stream/packet.h"
30 : #include "system/network.h"
31 : #include "param/param.h"
32 : #include "libcli/resolve/resolve.h"
33 : #include "../lib/tsocket/tsocket.h"
34 : #include "krb5_init_context.h"
35 : /*
36 : context structure for operations on cldap packets
37 : */
38 : struct smb_krb5_socket {
39 : struct socket_context *sock;
40 :
41 : /* the fd event */
42 : struct tevent_fd *fde;
43 :
44 : NTSTATUS status;
45 : DATA_BLOB request, reply;
46 :
47 : struct packet_context *packet;
48 :
49 : size_t partial_read;
50 : #ifdef SAMBA4_USES_HEIMDAL
51 : krb5_krbhst_info *hi;
52 : #endif
53 : };
54 :
55 576089 : static krb5_error_code smb_krb5_context_destroy(struct smb_krb5_context *ctx)
56 : {
57 : #ifdef SAMBA4_USES_HEIMDAL
58 506740 : if (ctx->pvt_log_data) {
59 : /* Otherwise krb5_free_context will try and close what we
60 : * have already free()ed */
61 506740 : krb5_set_warn_dest(ctx->krb5_context, NULL);
62 506740 : krb5_closelog(ctx->krb5_context,
63 506740 : (krb5_log_facility *)ctx->pvt_log_data);
64 : }
65 : #endif
66 576089 : krb5_free_context(ctx->krb5_context);
67 576089 : return 0;
68 : }
69 :
70 : #ifdef SAMBA4_USES_HEIMDAL
71 : /* We never close down the DEBUG system, and no need to unreference the use */
72 506740 : static void smb_krb5_debug_close(void *private_data) {
73 506740 : return;
74 : }
75 : #endif
76 :
77 : #ifdef SAMBA4_USES_HEIMDAL
78 332111 : static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private_data)
79 : {
80 332111 : DEBUGC(DBGC_KERBEROS, 3, ("Kerberos: %s\n", msg));
81 332111 : }
82 : #endif
83 :
84 : #ifdef SAMBA4_USES_HEIMDAL
85 : /*
86 : handle recv events on a smb_krb5 socket
87 : */
88 25090 : static void smb_krb5_socket_recv(struct smb_krb5_socket *smb_krb5)
89 : {
90 25090 : TALLOC_CTX *tmp_ctx = talloc_new(smb_krb5);
91 : DATA_BLOB blob;
92 : size_t nread, dsize;
93 :
94 25090 : smb_krb5->status = socket_pending(smb_krb5->sock, &dsize);
95 25090 : if (!NT_STATUS_IS_OK(smb_krb5->status)) {
96 0 : talloc_free(tmp_ctx);
97 0 : return;
98 : }
99 :
100 25090 : blob = data_blob_talloc(tmp_ctx, NULL, dsize);
101 25090 : if (blob.data == NULL && dsize != 0) {
102 0 : smb_krb5->status = NT_STATUS_NO_MEMORY;
103 0 : talloc_free(tmp_ctx);
104 0 : return;
105 : }
106 :
107 25090 : smb_krb5->status = socket_recv(smb_krb5->sock, blob.data, blob.length, &nread);
108 25090 : if (!NT_STATUS_IS_OK(smb_krb5->status)) {
109 0 : talloc_free(tmp_ctx);
110 0 : return;
111 : }
112 25090 : blob.length = nread;
113 :
114 25090 : if (nread == 0) {
115 0 : smb_krb5->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
116 0 : talloc_free(tmp_ctx);
117 0 : return;
118 : }
119 :
120 25090 : DEBUG(4,("Received smb_krb5 packet of length %d\n",
121 : (int)blob.length));
122 :
123 25090 : talloc_steal(smb_krb5, blob.data);
124 25090 : smb_krb5->reply = blob;
125 25090 : talloc_free(tmp_ctx);
126 : }
127 :
128 50848 : static NTSTATUS smb_krb5_full_packet(void *private_data, DATA_BLOB data)
129 : {
130 50848 : struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket);
131 50848 : talloc_steal(smb_krb5, data.data);
132 50848 : smb_krb5->reply = data;
133 50848 : smb_krb5->reply.length -= 4;
134 50848 : smb_krb5->reply.data += 4;
135 50848 : return NT_STATUS_OK;
136 : }
137 :
138 : /*
139 : handle request timeouts
140 : */
141 12 : static void smb_krb5_request_timeout(struct tevent_context *event_ctx,
142 : struct tevent_timer *te, struct timeval t,
143 : void *private_data)
144 : {
145 12 : struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket);
146 12 : DEBUG(5,("Timed out smb_krb5 packet\n"));
147 12 : smb_krb5->status = NT_STATUS_IO_TIMEOUT;
148 12 : }
149 :
150 0 : static void smb_krb5_error_handler(void *private_data, NTSTATUS status)
151 : {
152 0 : struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket);
153 0 : smb_krb5->status = status;
154 0 : }
155 :
156 : /*
157 : handle send events on a smb_krb5 socket
158 : */
159 1942502 : static void smb_krb5_socket_send(struct smb_krb5_socket *smb_krb5)
160 : {
161 : NTSTATUS status;
162 :
163 : size_t len;
164 :
165 1942502 : len = smb_krb5->request.length;
166 1942502 : status = socket_send(smb_krb5->sock, &smb_krb5->request, &len);
167 :
168 1942502 : if (!NT_STATUS_IS_OK(status)) return;
169 :
170 25090 : TEVENT_FD_READABLE(smb_krb5->fde);
171 :
172 25090 : TEVENT_FD_NOT_WRITEABLE(smb_krb5->fde);
173 25090 : return;
174 : }
175 :
176 :
177 : /*
178 : handle fd events on a smb_krb5_socket
179 : */
180 2142006 : static void smb_krb5_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
181 : uint16_t flags, void *private_data)
182 : {
183 2142006 : struct smb_krb5_socket *smb_krb5 = talloc_get_type(private_data, struct smb_krb5_socket);
184 2142006 : switch (smb_krb5->hi->proto) {
185 1967592 : case KRB5_KRBHST_UDP:
186 1967592 : if (flags & TEVENT_FD_READ) {
187 25090 : smb_krb5_socket_recv(smb_krb5);
188 25090 : return;
189 : }
190 1942502 : if (flags & TEVENT_FD_WRITE) {
191 1942502 : smb_krb5_socket_send(smb_krb5);
192 1942502 : return;
193 : }
194 : /* not reached */
195 0 : return;
196 174414 : case KRB5_KRBHST_TCP:
197 174414 : if (flags & TEVENT_FD_READ) {
198 123331 : packet_recv(smb_krb5->packet);
199 123331 : return;
200 : }
201 51083 : if (flags & TEVENT_FD_WRITE) {
202 51083 : packet_queue_run(smb_krb5->packet);
203 51083 : return;
204 : }
205 : /* not reached */
206 0 : return;
207 0 : case KRB5_KRBHST_HTTP:
208 : /* can't happen */
209 0 : break;
210 : }
211 : }
212 :
213 75950 : static krb5_error_code smb_krb5_send_and_recv_func_int(krb5_context context,
214 : struct tevent_context *ev,
215 : krb5_krbhst_info *hi,
216 : struct addrinfo *ai,
217 : krb5_send_to_kdc_func func,
218 : void *data,
219 : time_t timeout,
220 : const krb5_data *send_buf,
221 : krb5_data *recv_buf)
222 : {
223 : krb5_error_code ret;
224 : NTSTATUS status;
225 : const char *name;
226 : struct addrinfo *a;
227 : struct smb_krb5_socket *smb_krb5;
228 :
229 : DATA_BLOB send_blob;
230 :
231 75950 : TALLOC_CTX *frame = talloc_stackframe();
232 75950 : if (frame == NULL) {
233 0 : return ENOMEM;
234 : }
235 :
236 75950 : send_blob = data_blob_const(send_buf->data, send_buf->length);
237 :
238 75962 : for (a = ai; a; a = a->ai_next) {
239 : struct socket_address *remote_addr;
240 75950 : smb_krb5 = talloc(frame, struct smb_krb5_socket);
241 75950 : if (!smb_krb5) {
242 0 : TALLOC_FREE(frame);
243 0 : return ENOMEM;
244 : }
245 75950 : smb_krb5->hi = hi;
246 :
247 75950 : switch (a->ai_family) {
248 73976 : case PF_INET:
249 73976 : name = "ipv4";
250 73976 : break;
251 : #ifdef HAVE_IPV6
252 0 : case PF_INET6:
253 0 : name = "ipv6";
254 0 : break;
255 : #endif
256 0 : default:
257 0 : TALLOC_FREE(frame);
258 0 : return EINVAL;
259 : }
260 :
261 75950 : status = NT_STATUS_INVALID_PARAMETER;
262 75950 : switch (hi->proto) {
263 25102 : case KRB5_KRBHST_UDP:
264 25102 : status = socket_create(smb_krb5, name,
265 : SOCKET_TYPE_DGRAM,
266 : &smb_krb5->sock, 0);
267 25102 : break;
268 50848 : case KRB5_KRBHST_TCP:
269 50848 : status = socket_create(smb_krb5, name,
270 : SOCKET_TYPE_STREAM,
271 : &smb_krb5->sock, 0);
272 50848 : break;
273 0 : case KRB5_KRBHST_HTTP:
274 0 : TALLOC_FREE(frame);
275 0 : return EINVAL;
276 : }
277 75950 : if (!NT_STATUS_IS_OK(status)) {
278 0 : talloc_free(smb_krb5);
279 0 : continue;
280 : }
281 :
282 75950 : remote_addr = socket_address_from_sockaddr(smb_krb5, a->ai_addr, a->ai_addrlen);
283 75950 : if (!remote_addr) {
284 0 : talloc_free(smb_krb5);
285 0 : continue;
286 : }
287 :
288 75950 : status = socket_connect_ev(smb_krb5->sock, NULL, remote_addr, 0, ev);
289 75950 : if (!NT_STATUS_IS_OK(status)) {
290 0 : talloc_free(smb_krb5);
291 0 : continue;
292 : }
293 :
294 : /* Setup the FDE, start listening for read events
295 : * from the start (otherwise we may miss a socket
296 : * drop) and mark as AUTOCLOSE along with the fde */
297 :
298 : /* Ths is equivilant to EVENT_FD_READABLE(smb_krb5->fde) */
299 75950 : smb_krb5->fde = tevent_add_fd(ev, smb_krb5->sock,
300 : socket_get_fd(smb_krb5->sock),
301 : TEVENT_FD_READ,
302 : smb_krb5_socket_handler, smb_krb5);
303 : /* its now the job of the event layer to close the socket */
304 75950 : tevent_fd_set_close_fn(smb_krb5->fde, socket_tevent_fd_close_fn);
305 75950 : socket_set_flags(smb_krb5->sock, SOCKET_FLAG_NOCLOSE);
306 :
307 75950 : tevent_add_timer(ev, smb_krb5,
308 : timeval_current_ofs(timeout, 0),
309 : smb_krb5_request_timeout, smb_krb5);
310 :
311 75950 : smb_krb5->status = NT_STATUS_OK;
312 75950 : smb_krb5->reply = data_blob(NULL, 0);
313 :
314 75950 : switch (hi->proto) {
315 25102 : case KRB5_KRBHST_UDP:
316 25102 : TEVENT_FD_WRITEABLE(smb_krb5->fde);
317 25102 : smb_krb5->request = send_blob;
318 25102 : break;
319 50848 : case KRB5_KRBHST_TCP:
320 :
321 50848 : smb_krb5->packet = packet_init(smb_krb5);
322 50848 : if (smb_krb5->packet == NULL) {
323 0 : talloc_free(smb_krb5);
324 0 : return ENOMEM;
325 : }
326 50848 : packet_set_private(smb_krb5->packet, smb_krb5);
327 50848 : packet_set_socket(smb_krb5->packet, smb_krb5->sock);
328 50848 : packet_set_callback(smb_krb5->packet, smb_krb5_full_packet);
329 50848 : packet_set_full_request(smb_krb5->packet, packet_full_request_u32);
330 50848 : packet_set_error_handler(smb_krb5->packet, smb_krb5_error_handler);
331 50848 : packet_set_event_context(smb_krb5->packet, ev);
332 50848 : packet_set_fde(smb_krb5->packet, smb_krb5->fde);
333 :
334 50848 : smb_krb5->request = data_blob_talloc(smb_krb5, NULL, send_blob.length + 4);
335 50848 : RSIVAL(smb_krb5->request.data, 0, send_blob.length);
336 52232 : memcpy(smb_krb5->request.data+4, send_blob.data, send_blob.length);
337 50848 : packet_send(smb_krb5->packet, smb_krb5->request);
338 50848 : break;
339 0 : case KRB5_KRBHST_HTTP:
340 0 : TALLOC_FREE(frame);
341 0 : return EINVAL;
342 : }
343 2463236 : while ((NT_STATUS_IS_OK(smb_krb5->status)) && !smb_krb5->reply.length) {
344 2313310 : if (tevent_loop_once(ev) != 0) {
345 0 : TALLOC_FREE(frame);
346 0 : return EINVAL;
347 : }
348 :
349 2313310 : if (func) {
350 : /* After each and every event loop, reset the
351 : * send_to_kdc pointers to what they were when
352 : * we entered this loop. That way, if a
353 : * nested event has invalidated them, we put
354 : * it back before we return to the heimdal
355 : * code */
356 2265229 : ret = krb5_set_send_to_kdc_func(context,
357 : func,
358 : data);
359 2265229 : if (ret != 0) {
360 0 : TALLOC_FREE(frame);
361 0 : return ret;
362 : }
363 : }
364 : }
365 75950 : if (NT_STATUS_EQUAL(smb_krb5->status, NT_STATUS_IO_TIMEOUT)) {
366 12 : talloc_free(smb_krb5);
367 12 : continue;
368 : }
369 :
370 75938 : if (!NT_STATUS_IS_OK(smb_krb5->status)) {
371 0 : struct tsocket_address *addr = socket_address_to_tsocket_address(smb_krb5, remote_addr);
372 0 : const char *addr_string = NULL;
373 0 : if (addr) {
374 0 : addr_string = tsocket_address_inet_addr_string(addr, smb_krb5);
375 : } else {
376 0 : addr_string = NULL;
377 : }
378 0 : DEBUG(2,("Error reading smb_krb5 reply packet: %s from %s\n", nt_errstr(smb_krb5->status),
379 : addr_string));
380 0 : talloc_free(smb_krb5);
381 0 : continue;
382 : }
383 :
384 75938 : ret = krb5_data_copy(recv_buf, smb_krb5->reply.data, smb_krb5->reply.length);
385 75938 : if (ret) {
386 0 : TALLOC_FREE(frame);
387 0 : return ret;
388 : }
389 75938 : talloc_free(smb_krb5);
390 :
391 75938 : break;
392 : }
393 75950 : TALLOC_FREE(frame);
394 75950 : if (a) {
395 73964 : return 0;
396 : }
397 12 : return KRB5_KDC_UNREACH;
398 : }
399 :
400 55958 : krb5_error_code smb_krb5_send_and_recv_func(krb5_context context,
401 : void *data,
402 : krb5_krbhst_info *hi,
403 : time_t timeout,
404 : const krb5_data *send_buf,
405 : krb5_data *recv_buf)
406 : {
407 : krb5_error_code ret;
408 : struct addrinfo *ai;
409 :
410 : struct tevent_context *ev;
411 55958 : TALLOC_CTX *frame = talloc_stackframe();
412 55958 : if (frame == NULL) {
413 0 : return ENOMEM;
414 : }
415 :
416 55958 : if (data == NULL) {
417 : /* If no event context was available, then create one for this loop */
418 1547 : ev = samba_tevent_context_init(frame);
419 1547 : if (ev == NULL) {
420 0 : TALLOC_FREE(frame);
421 0 : return ENOMEM;
422 : }
423 : } else {
424 54411 : ev = talloc_get_type_abort(data, struct tevent_context);
425 : }
426 :
427 55958 : ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
428 55958 : if (ret) {
429 0 : TALLOC_FREE(frame);
430 0 : return ret;
431 : }
432 :
433 55958 : ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, smb_krb5_send_and_recv_func, data, timeout, send_buf, recv_buf);
434 55958 : TALLOC_FREE(frame);
435 55958 : return ret;
436 : }
437 :
438 19992 : krb5_error_code smb_krb5_send_and_recv_func_forced(krb5_context context,
439 : void *data, /* struct addrinfo */
440 : krb5_krbhst_info *hi,
441 : time_t timeout,
442 : const krb5_data *send_buf,
443 : krb5_data *recv_buf)
444 : {
445 : krb5_error_code k5ret;
446 19992 : struct addrinfo *ai = data;
447 :
448 : struct tevent_context *ev;
449 19992 : TALLOC_CTX *frame = talloc_stackframe();
450 19992 : if (frame == NULL) {
451 0 : return ENOMEM;
452 : }
453 :
454 : /* no event context is passed in, create one for this loop */
455 19992 : ev = samba_tevent_context_init(frame);
456 19992 : if (ev == NULL) {
457 0 : TALLOC_FREE(frame);
458 0 : return ENOMEM;
459 : }
460 :
461 : /* No need to pass in send_and_recv functions, we won't nest on this private event loop */
462 19992 : k5ret = smb_krb5_send_and_recv_func_int(context, ev, hi, ai, NULL, NULL,
463 : timeout, send_buf, recv_buf);
464 19992 : TALLOC_FREE(frame);
465 19992 : return k5ret;
466 : }
467 : #endif
468 :
469 : krb5_error_code
470 363086 : smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx,
471 : struct loadparm_context *lp_ctx,
472 : krb5_context *_krb5_context)
473 : {
474 : krb5_error_code ret;
475 : #ifdef SAMBA4_USES_HEIMDAL
476 : char **config_files;
477 : const char *config_file, *realm;
478 : #endif
479 : krb5_context krb5_ctx;
480 :
481 363086 : ret = smb_krb5_init_context_common(&krb5_ctx);
482 363086 : if (ret) {
483 0 : return ret;
484 : }
485 :
486 : /* The MIT Kerberos build relies on using the system krb5.conf file.
487 : * If you really want to use another file please set KRB5_CONFIG
488 : * accordingly. */
489 : #ifdef SAMBA4_USES_HEIMDAL
490 305820 : config_file = lpcfg_config_path(tmp_ctx, lp_ctx, "krb5.conf");
491 305820 : if (!config_file) {
492 0 : krb5_free_context(krb5_ctx);
493 0 : return ENOMEM;
494 : }
495 :
496 : /* Use our local krb5.conf file by default */
497 305820 : ret = krb5_prepend_config_files_default(config_file, &config_files);
498 305820 : if (ret) {
499 0 : DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n",
500 : smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
501 0 : krb5_free_context(krb5_ctx);
502 0 : return ret;
503 : }
504 :
505 305820 : ret = krb5_set_config_files(krb5_ctx, config_files);
506 305820 : krb5_free_config_files(config_files);
507 305820 : if (ret) {
508 0 : DEBUG(1,("krb5_set_config_files failed (%s)\n",
509 : smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
510 0 : krb5_free_context(krb5_ctx);
511 0 : return ret;
512 : }
513 :
514 : /*
515 : * This is already called in smb_krb5_init_context_common(),
516 : * but krb5_set_config_files() may resets it.
517 : */
518 305820 : krb5_set_dns_canonicalize_hostname(krb5_ctx, false);
519 :
520 305820 : realm = lpcfg_realm(lp_ctx);
521 305820 : if (realm != NULL) {
522 305820 : ret = krb5_set_default_realm(krb5_ctx, realm);
523 305820 : if (ret) {
524 0 : DEBUG(1,("krb5_set_default_realm failed (%s)\n",
525 : smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
526 0 : krb5_free_context(krb5_ctx);
527 0 : return ret;
528 : }
529 : }
530 : #endif
531 363086 : *_krb5_context = krb5_ctx;
532 363086 : return 0;
533 : }
534 :
535 362563 : krb5_error_code smb_krb5_init_context(void *parent_ctx,
536 : struct loadparm_context *lp_ctx,
537 : struct smb_krb5_context **smb_krb5_context)
538 : {
539 : krb5_error_code ret;
540 : TALLOC_CTX *tmp_ctx;
541 : krb5_context kctx;
542 : #ifdef SAMBA4_USES_HEIMDAL
543 : krb5_log_facility *logf;
544 : #endif
545 :
546 362563 : tmp_ctx = talloc_new(parent_ctx);
547 362563 : *smb_krb5_context = talloc_zero(tmp_ctx, struct smb_krb5_context);
548 :
549 362563 : if (!*smb_krb5_context || !tmp_ctx) {
550 0 : talloc_free(tmp_ctx);
551 0 : return ENOMEM;
552 : }
553 :
554 362563 : ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, &kctx);
555 362563 : if (ret) {
556 0 : DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n",
557 : error_message(ret)));
558 0 : talloc_free(tmp_ctx);
559 0 : return ret;
560 : }
561 362563 : (*smb_krb5_context)->krb5_context = kctx;
562 :
563 362563 : talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy);
564 :
565 : #ifdef SAMBA4_USES_HEIMDAL
566 : /* TODO: Should we have a different name here? */
567 305541 : ret = krb5_initlog(kctx, "Samba", &logf);
568 :
569 305541 : if (ret) {
570 0 : DEBUG(1,("krb5_initlog failed (%s)\n",
571 : smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
572 0 : talloc_free(tmp_ctx);
573 0 : return ret;
574 : }
575 305541 : (*smb_krb5_context)->pvt_log_data = logf;
576 :
577 305541 : ret = krb5_addlog_func(kctx, logf, 0 /* min */, -1 /* max */,
578 : smb_krb5_debug_wrapper,
579 : smb_krb5_debug_close, NULL);
580 305541 : if (ret) {
581 0 : DEBUG(1,("krb5_addlog_func failed (%s)\n",
582 : smb_get_krb5_error_message(kctx, ret, tmp_ctx)));
583 0 : talloc_free(tmp_ctx);
584 0 : return ret;
585 : }
586 305541 : krb5_set_warn_dest(kctx, logf);
587 : #endif
588 362563 : talloc_steal(parent_ctx, *smb_krb5_context);
589 362563 : talloc_free(tmp_ctx);
590 :
591 362563 : return 0;
592 : }
593 :
594 : #ifdef SAMBA4_USES_HEIMDAL
595 9776 : krb5_error_code smb_krb5_context_set_event_ctx(struct smb_krb5_context *smb_krb5_context,
596 : struct tevent_context *ev,
597 : struct tevent_context **previous_ev)
598 : {
599 : int ret;
600 9776 : if (!ev) {
601 0 : return EINVAL;
602 : }
603 :
604 9776 : *previous_ev = smb_krb5_context->current_ev;
605 :
606 9776 : smb_krb5_context->current_ev = talloc_reference(smb_krb5_context, ev);
607 9776 : if (!smb_krb5_context->current_ev) {
608 0 : return ENOMEM;
609 : }
610 :
611 : /* Set use of our socket lib */
612 9776 : ret = krb5_set_send_to_kdc_func(smb_krb5_context->krb5_context,
613 : smb_krb5_send_and_recv_func,
614 : ev);
615 9776 : if (ret) {
616 0 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
617 0 : DEBUG(1,("krb5_set_send_recv_func failed (%s)\n",
618 : smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, tmp_ctx)));
619 0 : talloc_free(tmp_ctx);
620 0 : talloc_unlink(smb_krb5_context, smb_krb5_context->current_ev);
621 0 : smb_krb5_context->current_ev = NULL;
622 0 : return ret;
623 : }
624 9481 : return 0;
625 : }
626 :
627 9776 : krb5_error_code smb_krb5_context_remove_event_ctx(struct smb_krb5_context *smb_krb5_context,
628 : struct tevent_context *previous_ev,
629 : struct tevent_context *ev)
630 : {
631 : int ret;
632 9776 : talloc_unlink(smb_krb5_context, ev);
633 : /* If there was a mismatch with things happening on a stack, then don't wipe things */
634 9776 : smb_krb5_context->current_ev = previous_ev;
635 : /* Set use of our socket lib */
636 9776 : ret = krb5_set_send_to_kdc_func(smb_krb5_context->krb5_context,
637 : smb_krb5_send_and_recv_func,
638 : previous_ev);
639 9776 : if (ret) {
640 0 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
641 0 : DEBUG(1,("krb5_set_send_recv_func failed (%s)\n",
642 : smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, tmp_ctx)));
643 0 : talloc_free(tmp_ctx);
644 0 : return ret;
645 : }
646 9481 : return 0;
647 : }
648 : #endif
|