LCOV - code coverage report
Current view: top level - source4/kdc - kdc-server.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 166 247 67.2 %
Date: 2024-02-14 10:14:15 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    KDC related functions
       5             : 
       6             :    Copyright (c) 2005-2008 Andrew Bartlett <abartlet@samba.org>
       7             :    Copyright (c) 2005      Andrew Tridgell <tridge@samba.org>
       8             :    Copyright (c) 2005      Stefan Metzmacher <metze@samba.org>
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "param/param.h"
      26             : #include "samba/process_model.h"
      27             : #include "lib/tsocket/tsocket.h"
      28             : #include "libcli/util/tstream.h"
      29             : #include "kdc/kdc-server.h"
      30             : #include "kdc/kdc-proxy.h"
      31             : #include "lib/stream/packet.h"
      32             : 
      33             : #undef DBGC_CLASS
      34             : #define DBGC_CLASS DBGC_KERBEROS
      35             : 
      36             : /*
      37             :  * State of an open tcp connection
      38             :  */
      39             : struct kdc_tcp_connection {
      40             :         /* stream connection we belong to */
      41             :         struct stream_connection *conn;
      42             : 
      43             :         /* the kdc_server the connection belongs to */
      44             :         struct kdc_socket *kdc_socket;
      45             : 
      46             :         struct tstream_context *tstream;
      47             : 
      48             :         struct tevent_queue *send_queue;
      49             : };
      50             : 
      51             : struct kdc_tcp_call {
      52             :         struct kdc_tcp_connection *kdc_conn;
      53             :         DATA_BLOB in;
      54             :         DATA_BLOB out;
      55             :         uint8_t out_hdr[4];
      56             :         struct iovec out_iov[2];
      57             : };
      58             : 
      59             : struct kdc_udp_call {
      60             :         struct kdc_udp_socket *sock;
      61             :         struct tsocket_address *src;
      62             :         DATA_BLOB in;
      63             :         DATA_BLOB out;
      64             : };
      65             : 
      66             : static void kdc_udp_call_proxy_done(struct tevent_req *subreq);
      67             : static void kdc_udp_call_sendto_done(struct tevent_req *subreq);
      68             : 
      69             : static void kdc_tcp_call_writev_done(struct tevent_req *subreq);
      70             : static void kdc_tcp_call_proxy_done(struct tevent_req *subreq);
      71             : 
      72       54312 : static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdc_conn,
      73             :                                          const char *reason)
      74             : {
      75       54312 :         stream_terminate_connection(kdc_conn->conn, reason);
      76       54312 : }
      77             : 
      78           0 : static NTSTATUS kdc_proxy_unavailable_error(struct kdc_server *kdc,
      79             :                                             TALLOC_CTX *mem_ctx,
      80             :                                             DATA_BLOB *out)
      81             : {
      82             :         krb5_error_code code;
      83             :         krb5_data enc_error;
      84             : 
      85           0 :         code = smb_krb5_mk_error(kdc->smb_krb5_context->krb5_context,
      86             :                                  KRB5KDC_ERR_SVC_UNAVAILABLE,
      87             :                                  NULL,
      88             :                                  NULL,
      89             :                                  NULL,
      90             :                                  NULL,
      91             :                                  &enc_error);
      92           0 :         if (code != 0) {
      93           0 :                 DBG_WARNING("Unable to form krb5 error reply\n");
      94           0 :                 return NT_STATUS_INTERNAL_ERROR;
      95             :         }
      96             : 
      97           0 :         *out = data_blob_talloc(mem_ctx, enc_error.data, enc_error.length);
      98           0 :         smb_krb5_free_data_contents(kdc->smb_krb5_context->krb5_context,
      99             :                                     &enc_error);
     100           0 :         if (!out->data) {
     101           0 :                 return NT_STATUS_NO_MEMORY;
     102             :         }
     103             : 
     104           0 :         return NT_STATUS_OK;
     105             : }
     106             : 
     107       16937 : static void kdc_udp_call_loop(struct tevent_req *subreq)
     108             : {
     109       16937 :         struct kdc_udp_socket *sock = tevent_req_callback_data(subreq,
     110             :                                       struct kdc_udp_socket);
     111             :         struct kdc_udp_call *call;
     112             :         uint8_t *buf;
     113             :         ssize_t len;
     114             :         int sys_errno;
     115             :         kdc_code ret;
     116             : 
     117       16937 :         call = talloc(sock, struct kdc_udp_call);
     118       16937 :         if (call == NULL) {
     119           0 :                 talloc_free(call);
     120           0 :                 goto done;
     121             :         }
     122       16937 :         call->sock = sock;
     123             : 
     124       16937 :         len = tdgram_recvfrom_recv(subreq, &sys_errno,
     125             :                                    call, &buf, &call->src);
     126       16937 :         TALLOC_FREE(subreq);
     127       16937 :         if (len == -1) {
     128           0 :                 talloc_free(call);
     129           0 :                 goto done;
     130             :         }
     131             : 
     132       16937 :         call->in.data = buf;
     133       16937 :         call->in.length = len;
     134             : 
     135       16937 :         DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
     136             :                  (long)call->in.length,
     137             :                  tsocket_address_string(call->src, call)));
     138             : 
     139             :         /* Call krb5 */
     140       16937 :         ret = sock->kdc_socket->process(sock->kdc_socket->kdc,
     141             :                                        call,
     142             :                                        &call->in,
     143             :                                        &call->out,
     144             :                                        call->src,
     145       16937 :                                        sock->kdc_socket->local_address,
     146             :                                        1 /* Datagram */);
     147       16937 :         if (ret == KDC_ERROR) {
     148           0 :                 talloc_free(call);
     149           0 :                 goto done;
     150             :         }
     151             : 
     152       16937 :         if (ret == KDC_PROXY_REQUEST) {
     153             :                 uint16_t port;
     154             : 
     155         939 :                 if (!sock->kdc_socket->kdc->am_rodc) {
     156           0 :                         DEBUG(0,("kdc_udp_call_loop: proxying requested when not RODC"));
     157           0 :                         talloc_free(call);
     158           0 :                         goto done;
     159             :                 }
     160             : 
     161         939 :                 port = tsocket_address_inet_port(sock->kdc_socket->local_address);
     162             : 
     163         939 :                 subreq = kdc_udp_proxy_send(call,
     164         939 :                                             sock->kdc_socket->kdc->task->event_ctx,
     165         939 :                                             sock->kdc_socket->kdc,
     166             :                                             port,
     167             :                                             call->in);
     168         939 :                 if (subreq == NULL) {
     169           0 :                         talloc_free(call);
     170           0 :                         goto done;
     171             :                 }
     172         939 :                 tevent_req_set_callback(subreq, kdc_udp_call_proxy_done, call);
     173         939 :                 goto done;
     174             :         }
     175             : 
     176       15998 :         subreq = tdgram_sendto_queue_send(call,
     177       15998 :                                           sock->kdc_socket->kdc->task->event_ctx,
     178             :                                           sock->dgram,
     179             :                                           sock->send_queue,
     180       15998 :                                           call->out.data,
     181             :                                           call->out.length,
     182             :                                           call->src);
     183       15998 :         if (subreq == NULL) {
     184           0 :                 talloc_free(call);
     185           0 :                 goto done;
     186             :         }
     187       15998 :         tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
     188             : 
     189       16937 : done:
     190       16937 :         subreq = tdgram_recvfrom_send(sock,
     191       16937 :                                       sock->kdc_socket->kdc->task->event_ctx,
     192             :                                       sock->dgram);
     193       16937 :         if (subreq == NULL) {
     194           0 :                 task_server_terminate(sock->kdc_socket->kdc->task,
     195             :                                       "no memory for tdgram_recvfrom_send",
     196             :                                       true);
     197           0 :                 return;
     198             :         }
     199       16937 :         tevent_req_set_callback(subreq, kdc_udp_call_loop, sock);
     200             : }
     201             : 
     202         939 : static void kdc_udp_call_proxy_done(struct tevent_req *subreq)
     203             : {
     204             :         struct kdc_udp_call *call =
     205         939 :                 tevent_req_callback_data(subreq,
     206             :                 struct kdc_udp_call);
     207             :         NTSTATUS status;
     208             : 
     209         939 :         status = kdc_udp_proxy_recv(subreq, call, &call->out);
     210         939 :         TALLOC_FREE(subreq);
     211         939 :         if (!NT_STATUS_IS_OK(status)) {
     212             :                 /* generate an error packet */
     213           0 :                 status = kdc_proxy_unavailable_error(call->sock->kdc_socket->kdc,
     214             :                                                      call, &call->out);
     215             :         }
     216             : 
     217         939 :         if (!NT_STATUS_IS_OK(status)) {
     218           0 :                 talloc_free(call);
     219           0 :                 return;
     220             :         }
     221             : 
     222         939 :         subreq = tdgram_sendto_queue_send(call,
     223         939 :                                           call->sock->kdc_socket->kdc->task->event_ctx,
     224         939 :                                           call->sock->dgram,
     225         939 :                                           call->sock->send_queue,
     226         939 :                                           call->out.data,
     227             :                                           call->out.length,
     228             :                                           call->src);
     229         939 :         if (subreq == NULL) {
     230           0 :                 talloc_free(call);
     231           0 :                 return;
     232             :         }
     233             : 
     234         939 :         tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
     235             : }
     236             : 
     237       16937 : static void kdc_udp_call_sendto_done(struct tevent_req *subreq)
     238             : {
     239       16937 :         struct kdc_udp_call *call = tevent_req_callback_data(subreq,
     240             :                                        struct kdc_udp_call);
     241             :         int sys_errno;
     242             : 
     243       16937 :         tdgram_sendto_queue_recv(subreq, &sys_errno);
     244             : 
     245             :         /* We don't care about errors */
     246             : 
     247       16937 :         talloc_free(call);
     248       16937 : }
     249             : 
     250      108624 : static void kdc_tcp_call_loop(struct tevent_req *subreq)
     251             : {
     252      108624 :         struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq,
     253             :                                       struct kdc_tcp_connection);
     254             :         struct kdc_tcp_call *call;
     255             :         NTSTATUS status;
     256             :         kdc_code ret;
     257             : 
     258      108624 :         call = talloc(kdc_conn, struct kdc_tcp_call);
     259      108624 :         if (call == NULL) {
     260           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     261             :                                 "no memory for kdc_tcp_call");
     262       56421 :                 return;
     263             :         }
     264      108624 :         call->kdc_conn = kdc_conn;
     265             : 
     266      108624 :         status = tstream_read_pdu_blob_recv(subreq,
     267             :                                             call,
     268             :                                             &call->in);
     269      108624 :         TALLOC_FREE(subreq);
     270      108624 :         if (!NT_STATUS_IS_OK(status)) {
     271             :                 const char *reason;
     272             : 
     273       54312 :                 reason = talloc_asprintf(call, "kdc_tcp_call_loop: "
     274             :                                          "tstream_read_pdu_blob_recv() - %s",
     275             :                                          nt_errstr(status));
     276       54312 :                 if (!reason) {
     277           0 :                         reason = nt_errstr(status);
     278             :                 }
     279             : 
     280       54312 :                 kdc_tcp_terminate_connection(kdc_conn, reason);
     281       54312 :                 return;
     282             :         }
     283             : 
     284       54312 :         DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
     285             :                  (long) call->in.length,
     286             :                  tsocket_address_string(kdc_conn->conn->remote_address, call)));
     287             : 
     288             :         /* skip length header */
     289       54312 :         call->in.data +=4;
     290       54312 :         call->in.length -= 4;
     291             : 
     292             :         /* Call krb5 */
     293       54312 :         ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
     294             :                                            call,
     295             :                                            &call->in,
     296             :                                            &call->out,
     297       54312 :                                            kdc_conn->conn->remote_address,
     298       54312 :                                            kdc_conn->conn->local_address,
     299             :                                            0 /* Stream */);
     300       54312 :         if (ret == KDC_ERROR) {
     301           0 :                 kdc_tcp_terminate_connection(kdc_conn,
     302             :                                 "kdc_tcp_call_loop: process function failed");
     303           0 :                 return;
     304             :         }
     305             : 
     306       54312 :         if (ret == KDC_PROXY_REQUEST) {
     307             :                 uint16_t port;
     308             : 
     309        2109 :                 if (!kdc_conn->kdc_socket->kdc->am_rodc) {
     310           0 :                         kdc_tcp_terminate_connection(kdc_conn,
     311             :                                                      "kdc_tcp_call_loop: proxying requested when not RODC");
     312           0 :                         return;
     313             :                 }
     314        2109 :                 port = tsocket_address_inet_port(kdc_conn->conn->local_address);
     315             : 
     316        2109 :                 subreq = kdc_tcp_proxy_send(call,
     317        2109 :                                             kdc_conn->conn->event.ctx,
     318        2109 :                                             kdc_conn->kdc_socket->kdc,
     319             :                                             port,
     320             :                                             call->in);
     321        2109 :                 if (subreq == NULL) {
     322           0 :                         kdc_tcp_terminate_connection(kdc_conn,
     323             :                                 "kdc_tcp_call_loop: kdc_tcp_proxy_send failed");
     324           0 :                         return;
     325             :                 }
     326        2109 :                 tevent_req_set_callback(subreq, kdc_tcp_call_proxy_done, call);
     327        2109 :                 return;
     328             :         }
     329             : 
     330             :         /* First add the length of the out buffer */
     331       52203 :         RSIVAL(call->out_hdr, 0, call->out.length);
     332       52203 :         call->out_iov[0].iov_base = (char *) call->out_hdr;
     333       52203 :         call->out_iov[0].iov_len = 4;
     334             : 
     335       52203 :         call->out_iov[1].iov_base = (char *) call->out.data;
     336       52203 :         call->out_iov[1].iov_len = call->out.length;
     337             : 
     338       52203 :         subreq = tstream_writev_queue_send(call,
     339       52203 :                                            kdc_conn->conn->event.ctx,
     340             :                                            kdc_conn->tstream,
     341             :                                            kdc_conn->send_queue,
     342       52203 :                                            call->out_iov, 2);
     343       52203 :         if (subreq == NULL) {
     344           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     345             :                                 "no memory for tstream_writev_queue_send");
     346           0 :                 return;
     347             :         }
     348       52203 :         tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
     349             : 
     350             :         /*
     351             :          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
     352             :          * packet_full_request_u32 provides the pdu length then.
     353             :          */
     354       52203 :         subreq = tstream_read_pdu_blob_send(kdc_conn,
     355       52203 :                                             kdc_conn->conn->event.ctx,
     356             :                                             kdc_conn->tstream,
     357             :                                             4, /* initial_read_size */
     358             :                                             packet_full_request_u32,
     359             :                                             kdc_conn);
     360       52203 :         if (subreq == NULL) {
     361           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     362             :                                 "no memory for tstream_read_pdu_blob_send");
     363           0 :                 return;
     364             :         }
     365       52203 :         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     366             : }
     367             : 
     368        2109 : static void kdc_tcp_call_proxy_done(struct tevent_req *subreq)
     369             : {
     370        2109 :         struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
     371             :                         struct kdc_tcp_call);
     372        2109 :         struct kdc_tcp_connection *kdc_conn = call->kdc_conn;
     373             :         NTSTATUS status;
     374             : 
     375        2109 :         status = kdc_tcp_proxy_recv(subreq, call, &call->out);
     376        2109 :         TALLOC_FREE(subreq);
     377        2109 :         if (!NT_STATUS_IS_OK(status)) {
     378             :                 /* generate an error packet */
     379           0 :                 status = kdc_proxy_unavailable_error(kdc_conn->kdc_socket->kdc,
     380             :                                                      call, &call->out);
     381             :         }
     382             : 
     383        2109 :         if (!NT_STATUS_IS_OK(status)) {
     384             :                 const char *reason;
     385             : 
     386           0 :                 reason = talloc_asprintf(call, "kdc_tcp_call_proxy_done: "
     387             :                                          "kdc_proxy_unavailable_error - %s",
     388             :                                          nt_errstr(status));
     389           0 :                 if (!reason) {
     390           0 :                         reason = "kdc_tcp_call_proxy_done: kdc_proxy_unavailable_error() failed";
     391             :                 }
     392             : 
     393           0 :                 kdc_tcp_terminate_connection(call->kdc_conn, reason);
     394           0 :                 return;
     395             :         }
     396             : 
     397             :         /* First add the length of the out buffer */
     398        2109 :         RSIVAL(call->out_hdr, 0, call->out.length);
     399        2109 :         call->out_iov[0].iov_base = (char *) call->out_hdr;
     400        2109 :         call->out_iov[0].iov_len = 4;
     401             : 
     402        2109 :         call->out_iov[1].iov_base = (char *) call->out.data;
     403        2109 :         call->out_iov[1].iov_len = call->out.length;
     404             : 
     405        2109 :         subreq = tstream_writev_queue_send(call,
     406        2109 :                                            kdc_conn->conn->event.ctx,
     407             :                                            kdc_conn->tstream,
     408             :                                            kdc_conn->send_queue,
     409        2109 :                                            call->out_iov, 2);
     410        2109 :         if (subreq == NULL) {
     411           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     412             :                                 "no memory for tstream_writev_queue_send");
     413           0 :                 return;
     414             :         }
     415        2109 :         tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
     416             : 
     417             :         /*
     418             :          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
     419             :          * packet_full_request_u32 provides the pdu length then.
     420             :          */
     421        2109 :         subreq = tstream_read_pdu_blob_send(kdc_conn,
     422        2109 :                                             kdc_conn->conn->event.ctx,
     423             :                                             kdc_conn->tstream,
     424             :                                             4, /* initial_read_size */
     425             :                                             packet_full_request_u32,
     426             :                                             kdc_conn);
     427        2109 :         if (subreq == NULL) {
     428           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     429             :                                 "no memory for tstream_read_pdu_blob_send");
     430           0 :                 return;
     431             :         }
     432        2109 :         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     433             : }
     434             : 
     435       54312 : static void kdc_tcp_call_writev_done(struct tevent_req *subreq)
     436             : {
     437       54312 :         struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
     438             :                         struct kdc_tcp_call);
     439             :         int sys_errno;
     440             :         int rc;
     441             : 
     442       54312 :         rc = tstream_writev_queue_recv(subreq, &sys_errno);
     443       54312 :         TALLOC_FREE(subreq);
     444       54312 :         if (rc == -1) {
     445             :                 const char *reason;
     446             : 
     447           0 :                 reason = talloc_asprintf(call, "kdc_tcp_call_writev_done: "
     448             :                                          "tstream_writev_queue_recv() - %d:%s",
     449             :                                          sys_errno, strerror(sys_errno));
     450           0 :                 if (!reason) {
     451           0 :                         reason = "kdc_tcp_call_writev_done: tstream_writev_queue_recv() failed";
     452             :                 }
     453             : 
     454           0 :                 kdc_tcp_terminate_connection(call->kdc_conn, reason);
     455           0 :                 return;
     456             :         }
     457             : 
     458             :         /* We don't care about errors */
     459             : 
     460       54312 :         talloc_free(call);
     461             : }
     462             : 
     463             : /*
     464             :   called when we get a new connection
     465             : */
     466       54312 : static void kdc_tcp_accept(struct stream_connection *conn)
     467             : {
     468             :         struct kdc_socket *kdc_socket;
     469             :         struct kdc_tcp_connection *kdc_conn;
     470             :         struct tevent_req *subreq;
     471             :         int rc;
     472             : 
     473       54312 :         kdc_conn = talloc_zero(conn, struct kdc_tcp_connection);
     474       54312 :         if (kdc_conn == NULL) {
     475           0 :                 stream_terminate_connection(conn,
     476             :                                 "kdc_tcp_accept: out of memory");
     477           0 :                 return;
     478             :         }
     479             : 
     480       54312 :         kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept");
     481       54312 :         if (kdc_conn->send_queue == NULL) {
     482           0 :                 stream_terminate_connection(conn,
     483             :                                 "kdc_tcp_accept: out of memory");
     484           0 :                 return;
     485             :         }
     486             : 
     487       54312 :         kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);
     488             : 
     489       54312 :         TALLOC_FREE(conn->event.fde);
     490             : 
     491       54312 :         rc = tstream_bsd_existing_socket(kdc_conn,
     492             :                         socket_get_fd(conn->socket),
     493             :                         &kdc_conn->tstream);
     494       54312 :         if (rc < 0) {
     495           0 :                 stream_terminate_connection(conn,
     496             :                                 "kdc_tcp_accept: out of memory");
     497           0 :                 return;
     498             :         }
     499             : 
     500       54312 :         kdc_conn->conn = conn;
     501       54312 :         kdc_conn->kdc_socket = kdc_socket;
     502       54312 :         conn->private_data = kdc_conn;
     503             : 
     504             :         /*
     505             :          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
     506             :          * packet_full_request_u32 provides the pdu length then.
     507             :          */
     508       54312 :         subreq = tstream_read_pdu_blob_send(kdc_conn,
     509       54312 :                                             kdc_conn->conn->event.ctx,
     510             :                                             kdc_conn->tstream,
     511             :                                             4, /* initial_read_size */
     512             :                                             packet_full_request_u32,
     513             :                                             kdc_conn);
     514       54312 :         if (subreq == NULL) {
     515           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_accept: "
     516             :                                 "no memory for tstream_read_pdu_blob_send");
     517           0 :                 return;
     518             :         }
     519       54312 :         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     520             : }
     521             : 
     522           0 : static void kdc_tcp_recv(struct stream_connection *conn, uint16_t flags)
     523             : {
     524           0 :         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
     525             :                                                              struct kdc_tcp_connection);
     526             :         /* this should never be triggered! */
     527           0 :         kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_recv: called");
     528           0 : }
     529             : 
     530           0 : static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
     531             : {
     532           0 :         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
     533             :                                                              struct kdc_tcp_connection);
     534             :         /* this should never be triggered! */
     535           0 :         kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_send: called");
     536           0 : }
     537             : 
     538             : static const struct stream_server_ops kdc_tcp_stream_ops = {
     539             :         .name                   = "kdc_tcp",
     540             :         .accept_connection      = kdc_tcp_accept,
     541             :         .recv_handler           = kdc_tcp_recv,
     542             :         .send_handler           = kdc_tcp_send
     543             : };
     544             : 
     545             : /*
     546             :  * Start listening on the given address
     547             :  */
     548         327 : NTSTATUS kdc_add_socket(struct kdc_server *kdc,
     549             :                         const struct model_ops *model_ops,
     550             :                         const char *name,
     551             :                         const char *address,
     552             :                         uint16_t port,
     553             :                         kdc_process_fn_t process,
     554             :                         bool udp_only)
     555             : {
     556             :         struct kdc_socket *kdc_socket;
     557             :         struct kdc_udp_socket *kdc_udp_socket;
     558             :         struct tevent_req *udpsubreq;
     559             :         NTSTATUS status;
     560             :         int ret;
     561             : 
     562         327 :         kdc_socket = talloc(kdc, struct kdc_socket);
     563         327 :         NT_STATUS_HAVE_NO_MEMORY(kdc_socket);
     564             : 
     565         327 :         kdc_socket->kdc = kdc;
     566         327 :         kdc_socket->process = process;
     567             : 
     568         327 :         ret = tsocket_address_inet_from_strings(kdc_socket, "ip",
     569             :                                                 address, port,
     570             :                                                 &kdc_socket->local_address);
     571         327 :         if (ret != 0) {
     572           0 :                 status = map_nt_error_from_unix_common(errno);
     573           0 :                 return status;
     574             :         }
     575             : 
     576         327 :         if (!udp_only) {
     577         340 :                 status = stream_setup_socket(kdc->task,
     578         170 :                                              kdc->task->event_ctx,
     579         170 :                                              kdc->task->lp_ctx,
     580             :                                              model_ops,
     581             :                                              &kdc_tcp_stream_ops,
     582             :                                              "ip", address, &port,
     583         170 :                                              lpcfg_socket_options(kdc->task->lp_ctx),
     584             :                                              kdc_socket,
     585         170 :                                              kdc->task->process_context);
     586         170 :                 if (!NT_STATUS_IS_OK(status)) {
     587           0 :                         DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
     588             :                                  address, port, nt_errstr(status)));
     589           0 :                         talloc_free(kdc_socket);
     590           0 :                         return status;
     591             :                 }
     592             :         }
     593             : 
     594         327 :         kdc_udp_socket = talloc(kdc_socket, struct kdc_udp_socket);
     595         327 :         NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket);
     596             : 
     597         327 :         kdc_udp_socket->kdc_socket = kdc_socket;
     598             : 
     599         327 :         ret = tdgram_inet_udp_socket(kdc_socket->local_address,
     600             :                                      NULL,
     601             :                                      kdc_udp_socket,
     602             :                                      &kdc_udp_socket->dgram);
     603         327 :         if (ret != 0) {
     604           0 :                 status = map_nt_error_from_unix_common(errno);
     605           0 :                 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
     606             :                          address, port, nt_errstr(status)));
     607           0 :                 return status;
     608             :         }
     609             : 
     610         327 :         kdc_udp_socket->send_queue = tevent_queue_create(kdc_udp_socket,
     611             :                                                          "kdc_udp_send_queue");
     612         327 :         NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket->send_queue);
     613             : 
     614         327 :         udpsubreq = tdgram_recvfrom_send(kdc_udp_socket,
     615         327 :                                          kdc->task->event_ctx,
     616             :                                          kdc_udp_socket->dgram);
     617         327 :         NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
     618         327 :         tevent_req_set_callback(udpsubreq, kdc_udp_call_loop, kdc_udp_socket);
     619             : 
     620         327 :         return NT_STATUS_OK;
     621             : }

Generated by: LCOV version 1.14