LCOV - code coverage report
Current view: top level - source4/kdc - kdc-server.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 171 248 69.0 %
Date: 2021-09-23 10:06:22 Functions: 9 13 69.2 %

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

Generated by: LCOV version 1.13