LCOV - code coverage report
Current view: top level - source4/kdc - kdc-server.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 188 278 67.6 %
Date: 2023-11-21 12:31:41 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       75687 : static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdc_conn,
      73             :                                          const char *reason)
      74             : {
      75       75687 :         stream_terminate_connection(kdc_conn->conn, reason);
      76       73444 : }
      77             : 
      78           0 : static NTSTATUS kdc_proxy_unavailable_error(struct kdc_server *kdc,
      79             :                                             TALLOC_CTX *mem_ctx,
      80             :                                             DATA_BLOB *out)
      81             : {
      82           0 :         krb5_error_code code;
      83           0 :         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       25873 : static void kdc_udp_call_loop(struct tevent_req *subreq)
     108             : {
     109       25873 :         struct kdc_udp_socket *sock = tevent_req_callback_data(subreq,
     110             :                                       struct kdc_udp_socket);
     111        1170 :         struct kdc_udp_call *call;
     112        1170 :         uint8_t *buf;
     113        1170 :         ssize_t len;
     114        1170 :         int sys_errno;
     115        1170 :         kdc_code ret;
     116             : 
     117       25873 :         call = talloc(sock, struct kdc_udp_call);
     118       25873 :         if (call == NULL) {
     119           0 :                 talloc_free(call);
     120           0 :                 goto done;
     121             :         }
     122       25873 :         call->sock = sock;
     123             : 
     124       25873 :         len = tdgram_recvfrom_recv(subreq, &sys_errno,
     125             :                                    call, &buf, &call->src);
     126       25873 :         TALLOC_FREE(subreq);
     127       25873 :         if (len == -1) {
     128           0 :                 talloc_free(call);
     129           0 :                 goto done;
     130             :         }
     131             : 
     132       25873 :         call->in.data = buf;
     133       25873 :         call->in.length = len;
     134             : 
     135       25873 :         DBG_DEBUG("Received krb5 UDP packet of length %zu from %s\n",
     136             :                   call->in.length,
     137             :                   tsocket_address_string(call->src, call));
     138             : 
     139             :         /* Call krb5 */
     140       25873 :         ret = sock->kdc_socket->process(sock->kdc_socket->kdc,
     141             :                                        call,
     142             :                                        &call->in,
     143             :                                        &call->out,
     144             :                                        call->src,
     145       24703 :                                        sock->kdc_socket->local_address,
     146             :                                        1 /* Datagram */);
     147       25873 :         if (ret == KDC_ERROR) {
     148           0 :                 talloc_free(call);
     149           0 :                 goto done;
     150             :         }
     151             : 
     152       25873 :         if (ret == KDC_PROXY_REQUEST) {
     153           0 :                 uint16_t port;
     154             : 
     155         933 :                 if (!sock->kdc_socket->kdc->am_rodc) {
     156           0 :                         DBG_ERR("proxying requested when not RODC\n");
     157           0 :                         talloc_free(call);
     158           0 :                         goto done;
     159             :                 }
     160             : 
     161         933 :                 port = tsocket_address_inet_port(sock->kdc_socket->local_address);
     162             : 
     163         933 :                 subreq = kdc_udp_proxy_send(call,
     164         933 :                                             sock->kdc_socket->kdc->task->event_ctx,
     165         933 :                                             sock->kdc_socket->kdc,
     166             :                                             port,
     167             :                                             call->in);
     168         933 :                 if (subreq == NULL) {
     169           0 :                         talloc_free(call);
     170           0 :                         goto done;
     171             :                 }
     172         933 :                 tevent_req_set_callback(subreq, kdc_udp_call_proxy_done, call);
     173         933 :                 goto done;
     174             :         }
     175             : 
     176       26110 :         subreq = tdgram_sendto_queue_send(call,
     177       24940 :                                           sock->kdc_socket->kdc->task->event_ctx,
     178             :                                           sock->dgram,
     179             :                                           sock->send_queue,
     180       24940 :                                           call->out.data,
     181             :                                           call->out.length,
     182             :                                           call->src);
     183       24940 :         if (subreq == NULL) {
     184           0 :                 talloc_free(call);
     185           0 :                 goto done;
     186             :         }
     187       24940 :         tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
     188             : 
     189       25873 : done:
     190       27043 :         subreq = tdgram_recvfrom_send(sock,
     191       25873 :                                       sock->kdc_socket->kdc->task->event_ctx,
     192             :                                       sock->dgram);
     193       25873 :         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       25873 :         tevent_req_set_callback(subreq, kdc_udp_call_loop, sock);
     200             : }
     201             : 
     202         933 : static void kdc_udp_call_proxy_done(struct tevent_req *subreq)
     203             : {
     204           0 :         struct kdc_udp_call *call =
     205         933 :                 tevent_req_callback_data(subreq,
     206             :                 struct kdc_udp_call);
     207           0 :         NTSTATUS status;
     208             : 
     209         933 :         status = kdc_udp_proxy_recv(subreq, call, &call->out);
     210         933 :         TALLOC_FREE(subreq);
     211         933 :         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         933 :         if (!NT_STATUS_IS_OK(status)) {
     218           0 :                 talloc_free(call);
     219           0 :                 return;
     220             :         }
     221             : 
     222         933 :         subreq = tdgram_sendto_queue_send(call,
     223         933 :                                           call->sock->kdc_socket->kdc->task->event_ctx,
     224         933 :                                           call->sock->dgram,
     225         933 :                                           call->sock->send_queue,
     226         933 :                                           call->out.data,
     227             :                                           call->out.length,
     228             :                                           call->src);
     229         933 :         if (subreq == NULL) {
     230           0 :                 talloc_free(call);
     231           0 :                 return;
     232             :         }
     233             : 
     234         933 :         tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
     235             : }
     236             : 
     237       25873 : static void kdc_udp_call_sendto_done(struct tevent_req *subreq)
     238             : {
     239       25873 :         struct kdc_udp_call *call = tevent_req_callback_data(subreq,
     240             :                                        struct kdc_udp_call);
     241        1170 :         int sys_errno;
     242             : 
     243       25873 :         tdgram_sendto_queue_recv(subreq, &sys_errno);
     244             : 
     245             :         /* We don't care about errors */
     246             : 
     247       25873 :         talloc_free(call);
     248       25873 : }
     249             : 
     250      151374 : static void kdc_tcp_call_loop(struct tevent_req *subreq)
     251             : {
     252      151374 :         struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq,
     253             :                                       struct kdc_tcp_connection);
     254        4486 :         struct kdc_tcp_call *call;
     255        4486 :         NTSTATUS status;
     256        4486 :         kdc_code ret;
     257             : 
     258      151374 :         call = talloc(kdc_conn, struct kdc_tcp_call);
     259      151374 :         if (call == NULL) {
     260           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     261             :                                 "no memory for kdc_tcp_call");
     262       77794 :                 return;
     263             :         }
     264      151374 :         call->kdc_conn = kdc_conn;
     265             : 
     266      151374 :         status = tstream_read_pdu_blob_recv(subreq,
     267             :                                             call,
     268             :                                             &call->in);
     269      151374 :         TALLOC_FREE(subreq);
     270      151374 :         if (!NT_STATUS_IS_OK(status)) {
     271        2243 :                 const char *reason;
     272             : 
     273       75687 :                 reason = talloc_asprintf(call, "kdc_tcp_call_loop: "
     274             :                                          "tstream_read_pdu_blob_recv() - %s",
     275             :                                          nt_errstr(status));
     276       75687 :                 if (!reason) {
     277           0 :                         reason = nt_errstr(status);
     278             :                 }
     279             : 
     280       75687 :                 kdc_tcp_terminate_connection(kdc_conn, reason);
     281       75687 :                 return;
     282             :         }
     283             : 
     284       75687 :         DBG_DEBUG("Received krb5 TCP packet of length %zu from %s\n",
     285             :                   call->in.length,
     286             :                   tsocket_address_string(kdc_conn->conn->remote_address, call));
     287             : 
     288             :         /* skip length header */
     289       75687 :         call->in.data +=4;
     290       75687 :         call->in.length -= 4;
     291             : 
     292             :         /* Call krb5 */
     293       77930 :         ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
     294             :                                            call,
     295             :                                            &call->in,
     296             :                                            &call->out,
     297       73444 :                                            kdc_conn->conn->remote_address,
     298       75687 :                                            kdc_conn->conn->local_address,
     299             :                                            0 /* Stream */);
     300       75687 :         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       75687 :         if (ret == KDC_PROXY_REQUEST) {
     307           0 :                 uint16_t port;
     308             : 
     309        2107 :                 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        2107 :                 port = tsocket_address_inet_port(kdc_conn->conn->local_address);
     315             : 
     316        2107 :                 subreq = kdc_tcp_proxy_send(call,
     317        2107 :                                             kdc_conn->conn->event.ctx,
     318        2107 :                                             kdc_conn->kdc_socket->kdc,
     319             :                                             port,
     320             :                                             call->in);
     321        2107 :                 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        2107 :                 tevent_req_set_callback(subreq, kdc_tcp_call_proxy_done, call);
     327        2107 :                 return;
     328             :         }
     329             : 
     330             :         /* First add the length of the out buffer */
     331       73580 :         RSIVAL(call->out_hdr, 0, call->out.length);
     332       73580 :         call->out_iov[0].iov_base = (char *) call->out_hdr;
     333       73580 :         call->out_iov[0].iov_len = 4;
     334             : 
     335       73580 :         call->out_iov[1].iov_base = (char *) call->out.data;
     336       73580 :         call->out_iov[1].iov_len = call->out.length;
     337             : 
     338       75823 :         subreq = tstream_writev_queue_send(call,
     339       73580 :                                            kdc_conn->conn->event.ctx,
     340             :                                            kdc_conn->tstream,
     341             :                                            kdc_conn->send_queue,
     342       73580 :                                            call->out_iov, 2);
     343       73580 :         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       73580 :         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             :          * tstream_full_request_u32 provides the pdu length then.
     353             :          */
     354       75823 :         subreq = tstream_read_pdu_blob_send(kdc_conn,
     355       73580 :                                             kdc_conn->conn->event.ctx,
     356             :                                             kdc_conn->tstream,
     357             :                                             4, /* initial_read_size */
     358             :                                             tstream_full_request_u32,
     359             :                                             kdc_conn);
     360       73580 :         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       73580 :         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     366             : }
     367             : 
     368        2107 : static void kdc_tcp_call_proxy_done(struct tevent_req *subreq)
     369             : {
     370        2107 :         struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
     371             :                         struct kdc_tcp_call);
     372        2107 :         struct kdc_tcp_connection *kdc_conn = call->kdc_conn;
     373           0 :         NTSTATUS status;
     374             : 
     375        2107 :         status = kdc_tcp_proxy_recv(subreq, call, &call->out);
     376        2107 :         TALLOC_FREE(subreq);
     377        2107 :         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        2107 :         if (!NT_STATUS_IS_OK(status)) {
     384           0 :                 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        2107 :         RSIVAL(call->out_hdr, 0, call->out.length);
     399        2107 :         call->out_iov[0].iov_base = (char *) call->out_hdr;
     400        2107 :         call->out_iov[0].iov_len = 4;
     401             : 
     402        2107 :         call->out_iov[1].iov_base = (char *) call->out.data;
     403        2107 :         call->out_iov[1].iov_len = call->out.length;
     404             : 
     405        2107 :         subreq = tstream_writev_queue_send(call,
     406        2107 :                                            kdc_conn->conn->event.ctx,
     407             :                                            kdc_conn->tstream,
     408             :                                            kdc_conn->send_queue,
     409        2107 :                                            call->out_iov, 2);
     410        2107 :         if (subreq == NULL) {
     411           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_proxy_done: "
     412             :                                 "no memory for tstream_writev_queue_send");
     413           0 :                 return;
     414             :         }
     415        2107 :         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             :          * tstream_full_request_u32 provides the pdu length then.
     420             :          */
     421        2107 :         subreq = tstream_read_pdu_blob_send(kdc_conn,
     422        2107 :                                             kdc_conn->conn->event.ctx,
     423             :                                             kdc_conn->tstream,
     424             :                                             4, /* initial_read_size */
     425             :                                             tstream_full_request_u32,
     426             :                                             kdc_conn);
     427        2107 :         if (subreq == NULL) {
     428           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_proxy_done: "
     429             :                                 "no memory for tstream_read_pdu_blob_send");
     430           0 :                 return;
     431             :         }
     432        2107 :         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     433             : }
     434             : 
     435       75687 : static void kdc_tcp_call_writev_done(struct tevent_req *subreq)
     436             : {
     437       75687 :         struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
     438             :                         struct kdc_tcp_call);
     439        2243 :         int sys_errno;
     440        2243 :         int rc;
     441             : 
     442       75687 :         rc = tstream_writev_queue_recv(subreq, &sys_errno);
     443       75687 :         TALLOC_FREE(subreq);
     444       75687 :         if (rc == -1) {
     445           0 :                 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       75687 :         talloc_free(call);
     461             : }
     462             : 
     463             : /*
     464             :   called when we get a new connection
     465             : */
     466       75687 : static void kdc_tcp_accept(struct stream_connection *conn)
     467             : {
     468        2243 :         struct kdc_socket *kdc_socket;
     469        2243 :         struct kdc_tcp_connection *kdc_conn;
     470        2243 :         struct tevent_req *subreq;
     471        2243 :         int rc;
     472             : 
     473       75687 :         kdc_conn = talloc_zero(conn, struct kdc_tcp_connection);
     474       75687 :         if (kdc_conn == NULL) {
     475           0 :                 stream_terminate_connection(conn,
     476             :                                 "kdc_tcp_accept: out of memory");
     477           0 :                 return;
     478             :         }
     479             : 
     480       75687 :         kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept");
     481       75687 :         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       75687 :         kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);
     488             : 
     489       75687 :         TALLOC_FREE(conn->event.fde);
     490             : 
     491       75687 :         rc = tstream_bsd_existing_socket(kdc_conn,
     492             :                         socket_get_fd(conn->socket),
     493             :                         &kdc_conn->tstream);
     494       75687 :         if (rc < 0) {
     495           0 :                 stream_terminate_connection(conn,
     496             :                                 "kdc_tcp_accept: out of memory");
     497           0 :                 return;
     498             :         }
     499             :         /* as server we want to fail early */
     500       75687 :         tstream_bsd_fail_readv_first_error(kdc_conn->tstream, true);
     501             : 
     502       75687 :         kdc_conn->conn = conn;
     503       75687 :         kdc_conn->kdc_socket = kdc_socket;
     504       75687 :         conn->private_data = kdc_conn;
     505             : 
     506             :         /*
     507             :          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
     508             :          * tstream_full_request_u32 provides the pdu length then.
     509             :          */
     510       75687 :         subreq = tstream_read_pdu_blob_send(kdc_conn,
     511       73444 :                                             kdc_conn->conn->event.ctx,
     512             :                                             kdc_conn->tstream,
     513             :                                             4, /* initial_read_size */
     514             :                                             tstream_full_request_u32,
     515             :                                             kdc_conn);
     516       75687 :         if (subreq == NULL) {
     517           0 :                 kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_accept: "
     518             :                                 "no memory for tstream_read_pdu_blob_send");
     519           0 :                 return;
     520             :         }
     521       75687 :         tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     522             : }
     523             : 
     524           0 : static void kdc_tcp_recv(struct stream_connection *conn, uint16_t flags)
     525             : {
     526           0 :         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
     527             :                                                              struct kdc_tcp_connection);
     528             :         /* this should never be triggered! */
     529           0 :         kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_recv: called");
     530           0 : }
     531             : 
     532           0 : static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
     533             : {
     534           0 :         struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
     535             :                                                              struct kdc_tcp_connection);
     536             :         /* this should never be triggered! */
     537           0 :         kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_send: called");
     538           0 : }
     539             : 
     540             : static const struct stream_server_ops kdc_tcp_stream_ops = {
     541             :         .name                   = "kdc_tcp",
     542             :         .accept_connection      = kdc_tcp_accept,
     543             :         .recv_handler           = kdc_tcp_recv,
     544             :         .send_handler           = kdc_tcp_send
     545             : };
     546             : 
     547             : /*
     548             :  * Start listening on the given address
     549             :  */
     550         387 : NTSTATUS kdc_add_socket(struct kdc_server *kdc,
     551             :                         const struct model_ops *model_ops,
     552             :                         const char *name,
     553             :                         const char *address,
     554             :                         uint16_t port,
     555             :                         kdc_process_fn_t process,
     556             :                         bool udp_only)
     557             : {
     558          16 :         struct kdc_socket *kdc_socket;
     559          16 :         struct kdc_udp_socket *kdc_udp_socket;
     560          16 :         struct tevent_req *udpsubreq;
     561          16 :         NTSTATUS status;
     562          16 :         int ret;
     563             : 
     564         387 :         kdc_socket = talloc(kdc, struct kdc_socket);
     565         387 :         NT_STATUS_HAVE_NO_MEMORY(kdc_socket);
     566             : 
     567         387 :         kdc_socket->kdc = kdc;
     568         387 :         kdc_socket->process = process;
     569             : 
     570         387 :         ret = tsocket_address_inet_from_strings(kdc_socket, "ip",
     571             :                                                 address, port,
     572             :                                                 &kdc_socket->local_address);
     573         387 :         if (ret != 0) {
     574           0 :                 status = map_nt_error_from_unix_common(errno);
     575           0 :                 return status;
     576             :         }
     577             : 
     578         387 :         if (!udp_only) {
     579         404 :                 status = stream_setup_socket(kdc->task,
     580         194 :                                              kdc->task->event_ctx,
     581         202 :                                              kdc->task->lp_ctx,
     582             :                                              model_ops,
     583             :                                              &kdc_tcp_stream_ops,
     584             :                                              "ip", address, &port,
     585         194 :                                              lpcfg_socket_options(kdc->task->lp_ctx),
     586             :                                              kdc_socket,
     587         202 :                                              kdc->task->process_context);
     588         202 :                 if (!NT_STATUS_IS_OK(status)) {
     589           0 :                         DBG_ERR("Failed to bind to %s:%u TCP - %s\n",
     590             :                                 address, port, nt_errstr(status));
     591           0 :                         talloc_free(kdc_socket);
     592           0 :                         return status;
     593             :                 }
     594             :         }
     595             : 
     596         387 :         kdc_udp_socket = talloc(kdc_socket, struct kdc_udp_socket);
     597         387 :         NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket);
     598             : 
     599         387 :         kdc_udp_socket->kdc_socket = kdc_socket;
     600             : 
     601         387 :         ret = tdgram_inet_udp_socket(kdc_socket->local_address,
     602             :                                      NULL,
     603             :                                      kdc_udp_socket,
     604             :                                      &kdc_udp_socket->dgram);
     605         387 :         if (ret != 0) {
     606           0 :                 status = map_nt_error_from_unix_common(errno);
     607           0 :                 DBG_ERR("Failed to bind to %s:%u UDP - %s\n",
     608             :                         address, port, nt_errstr(status));
     609           0 :                 return status;
     610             :         }
     611             : 
     612         387 :         kdc_udp_socket->send_queue = tevent_queue_create(kdc_udp_socket,
     613             :                                                          "kdc_udp_send_queue");
     614         387 :         NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket->send_queue);
     615             : 
     616         403 :         udpsubreq = tdgram_recvfrom_send(kdc_udp_socket,
     617         387 :                                          kdc->task->event_ctx,
     618             :                                          kdc_udp_socket->dgram);
     619         387 :         NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
     620         387 :         tevent_req_set_callback(udpsubreq, kdc_udp_call_loop, kdc_udp_socket);
     621             : 
     622         387 :         return NT_STATUS_OK;
     623             : }

Generated by: LCOV version 1.14