Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source4/kdc/kdc.c

    r414 r740  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33
     
    1212   the Free Software Foundation; either version 3 of the License, or
    1313   (at your option) any later version.
    14    
     14
    1515   This program is distributed in the hope that it will be useful,
    1616   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1717   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1818   GNU General Public License for more details.
    19    
     19
    2020   You should have received a copy of the GNU General Public License
    2121   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2323
    2424#include "includes.h"
    25 #include "smbd/service_task.h"
    26 #include "smbd/service.h"
    27 #include "smbd/service_stream.h"
    2825#include "smbd/process_model.h"
    29 #include "lib/events/events.h"
    30 #include "lib/socket/socket.h"
    31 #include "system/network.h"
    32 #include "../lib/util/dlinklist.h"
     26#include "lib/tsocket/tsocket.h"
     27#include "libcli/util/tstream.h"
    3328#include "lib/messaging/irpc.h"
    34 #include "lib/stream/packet.h"
    35 #include "librpc/gen_ndr/samr.h"
    3629#include "librpc/gen_ndr/ndr_irpc.h"
    3730#include "librpc/gen_ndr/ndr_krb5pac.h"
     31#include "lib/stream/packet.h"
    3832#include "lib/socket/netif.h"
    3933#include "param/param.h"
    40 #include "kdc/kdc.h"
    41 #include "librpc/gen_ndr/ndr_misc.h"
    42 
    43 
    44 /* Disgusting hack to get a mem_ctx and lp_ctx into the hdb plugin, when
    45  * used as a keytab */
    46 TALLOC_CTX *hdb_samba4_mem_ctx;
    47 struct tevent_context *hdb_samba4_ev_ctx;
    48 struct loadparm_context *hdb_samba4_lp_ctx;
    49 
    50 /* hold all the info needed to send a reply */
    51 struct kdc_reply {
    52         struct kdc_reply *next, *prev;
    53         struct socket_address *dest;
    54         DATA_BLOB packet;
    55 };
    56 
    57 typedef bool (*kdc_process_fn_t)(struct kdc_server *kdc,
    58                                  TALLOC_CTX *mem_ctx,
    59                                  DATA_BLOB *input,
    60                                  DATA_BLOB *reply,
    61                                  struct socket_address *peer_addr,
    62                                  struct socket_address *my_addr,
    63                                  int datagram);
     34#include "kdc/kdc-glue.h"
     35#include "dsdb/samdb/samdb.h"
     36#include "auth/session.h"
     37
     38extern struct krb5plugin_windc_ftable windc_plugin_table;
     39extern struct hdb_method hdb_samba4;
     40
     41static NTSTATUS kdc_proxy_unavailable_error(struct kdc_server *kdc,
     42                                            TALLOC_CTX *mem_ctx,
     43                                            DATA_BLOB *out)
     44{
     45        int kret;
     46        krb5_data k5_error_blob;
     47
     48        kret = krb5_mk_error(kdc->smb_krb5_context->krb5_context,
     49                             KRB5KDC_ERR_SVC_UNAVAILABLE, NULL, NULL,
     50                             NULL, NULL, NULL, NULL, &k5_error_blob);
     51        if (kret != 0) {
     52                DEBUG(2,(__location__ ": Unable to form krb5 error reply\n"));
     53                return NT_STATUS_INTERNAL_ERROR;
     54        }
     55
     56        *out = data_blob_talloc(mem_ctx, k5_error_blob.data, k5_error_blob.length);
     57        krb5_data_free(&k5_error_blob);
     58        if (!out->data) {
     59                return NT_STATUS_NO_MEMORY;
     60        }
     61
     62        return NT_STATUS_OK;
     63}
     64
     65typedef enum kdc_process_ret (*kdc_process_fn_t)(struct kdc_server *kdc,
     66                                                 TALLOC_CTX *mem_ctx,
     67                                                 DATA_BLOB *input,
     68                                                 DATA_BLOB *reply,
     69                                                 struct tsocket_address *peer_addr,
     70                                                 struct tsocket_address *my_addr,
     71                                                 int datagram);
    6472
    6573/* hold information about one kdc socket */
    6674struct kdc_socket {
    67         struct socket_context *sock;
    6875        struct kdc_server *kdc;
    69         struct tevent_fd *fde;
    70 
    71         /* a queue of outgoing replies that have been deferred */
    72         struct kdc_reply *send_queue;
    73 
     76        struct tsocket_address *local_address;
    7477        kdc_process_fn_t process;
    7578};
     79
     80struct kdc_tcp_call {
     81        struct kdc_tcp_connection *kdc_conn;
     82        DATA_BLOB in;
     83        DATA_BLOB out;
     84        uint8_t out_hdr[4];
     85        struct iovec out_iov[2];
     86};
     87
    7688/*
    7789  state of an open tcp connection
     
    8294
    8395        /* the kdc_server the connection belongs to */
    84         struct kdc_server *kdc;
    85 
    86         struct packet_context *packet;
    87 
    88         kdc_process_fn_t process;
     96        struct kdc_socket *kdc_socket;
     97
     98        struct tstream_context *tstream;
     99
     100        struct tevent_queue *send_queue;
    89101};
    90102
    91 /*
    92   handle fd send events on a KDC socket
    93 */
    94 static void kdc_send_handler(struct kdc_socket *kdc_socket)
    95 {
    96         while (kdc_socket->send_queue) {
    97                 struct kdc_reply *rep = kdc_socket->send_queue;
    98                 NTSTATUS status;
    99                 size_t sendlen;
    100 
    101                 status = socket_sendto(kdc_socket->sock, &rep->packet, &sendlen,
    102                                        rep->dest);
    103                 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
    104                         break;
    105                 }
    106                 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_BUFFER_SIZE)) {
    107                         /* Replace with a krb err, response to big */
    108                 }
    109                
    110                 DLIST_REMOVE(kdc_socket->send_queue, rep);
    111                 talloc_free(rep);
    112         }
    113 
    114         if (kdc_socket->send_queue == NULL) {
    115                 EVENT_FD_NOT_WRITEABLE(kdc_socket->fde);
    116         }
    117 }
    118 
    119 
    120 /*
    121   handle fd recv events on a KDC socket
    122 */
    123 static void kdc_recv_handler(struct kdc_socket *kdc_socket)
    124 {
    125         NTSTATUS status;
    126         TALLOC_CTX *tmp_ctx = talloc_new(kdc_socket);
    127         DATA_BLOB blob;
    128         struct kdc_reply *rep;
    129         DATA_BLOB reply;
    130         size_t nread, dsize;
    131         struct socket_address *src;
    132         struct socket_address *my_addr;
    133         int ret;
    134 
    135         status = socket_pending(kdc_socket->sock, &dsize);
    136         if (!NT_STATUS_IS_OK(status)) {
    137                 talloc_free(tmp_ctx);
    138                 return;
    139         }
    140 
    141         blob = data_blob_talloc(tmp_ctx, NULL, dsize);
    142         if (blob.data == NULL) {
    143                 /* hope this is a temporary low memory condition */
    144                 talloc_free(tmp_ctx);
    145                 return;
    146         }
    147 
    148         status = socket_recvfrom(kdc_socket->sock, blob.data, blob.length, &nread,
    149                                  tmp_ctx, &src);
    150         if (!NT_STATUS_IS_OK(status)) {
    151                 talloc_free(tmp_ctx);
    152                 return;
    153         }
    154         blob.length = nread;
    155        
    156         DEBUG(10,("Received krb5 UDP packet of length %lu from %s:%u\n",
    157                  (long)blob.length, src->addr, (uint16_t)src->port));
    158        
    159         my_addr = socket_get_my_addr(kdc_socket->sock, tmp_ctx);
    160         if (!my_addr) {
    161                 talloc_free(tmp_ctx);
    162                 return;
    163         }
    164 
    165 
    166         /* Call krb5 */
    167         ret = kdc_socket->process(kdc_socket->kdc,
    168                                   tmp_ctx,
    169                                   &blob, 
    170                                   &reply,
    171                                   src, my_addr,
    172                                   1 /* Datagram */);
    173         if (!ret) {
    174                 talloc_free(tmp_ctx);
    175                 return;
    176         }
    177 
    178         /* queue a pending reply */
    179         rep = talloc(kdc_socket, struct kdc_reply);
    180         if (rep == NULL) {
    181                 talloc_free(tmp_ctx);
    182                 return;
    183         }
    184         rep->dest         = talloc_steal(rep, src);
    185         rep->packet       = reply;
    186         talloc_steal(rep, reply.data);
    187 
    188         if (rep->packet.data == NULL) {
    189                 talloc_free(rep);
    190                 talloc_free(tmp_ctx);
    191                 return;
    192         }
    193 
    194         DLIST_ADD_END(kdc_socket->send_queue, rep, struct kdc_reply *);
    195         EVENT_FD_WRITEABLE(kdc_socket->fde);
    196         talloc_free(tmp_ctx);
    197 }
    198 
    199 /*
    200   handle fd events on a KDC socket
    201 */
    202 static void kdc_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
    203                                uint16_t flags, void *private_data)
    204 {
    205         struct kdc_socket *kdc_socket = talloc_get_type(private_data, struct kdc_socket);
    206         if (flags & EVENT_FD_WRITE) {
    207                 kdc_send_handler(kdc_socket);
    208         }
    209         if (flags & EVENT_FD_READ) {
    210                 kdc_recv_handler(kdc_socket);
    211         }
    212 }
    213103
    214104static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdcconn, const char *reason)
     
    217107}
    218108
    219 /*
    220   receive a full packet on a KDC connection
    221 */
    222 static NTSTATUS kdc_tcp_recv(void *private_data, DATA_BLOB blob)
    223 {
    224         struct kdc_tcp_connection *kdcconn = talloc_get_type(private_data,
    225                                                              struct kdc_tcp_connection);
    226         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    227         TALLOC_CTX *tmp_ctx = talloc_new(kdcconn);
    228         int ret;
    229         DATA_BLOB input, reply;
    230         struct socket_address *src_addr;
    231         struct socket_address *my_addr;
    232 
    233         talloc_steal(tmp_ctx, blob.data);
    234 
    235         src_addr = socket_get_peer_addr(kdcconn->conn->socket, tmp_ctx);
    236         if (!src_addr) {
    237                 talloc_free(tmp_ctx);
    238                 return NT_STATUS_NO_MEMORY;
    239         }
    240 
    241         my_addr = socket_get_my_addr(kdcconn->conn->socket, tmp_ctx);
    242         if (!my_addr) {
    243                 talloc_free(tmp_ctx);
    244                 return NT_STATUS_NO_MEMORY;
    245         }
    246 
    247         /* Call krb5 */
    248         input = data_blob_const(blob.data + 4, blob.length - 4);
    249 
    250         ret = kdcconn->process(kdcconn->kdc,
    251                                tmp_ctx,
    252                                &input,
    253                                &reply,
    254                                src_addr,
    255                                my_addr,
    256                                0 /* Not datagram */);
    257         if (!ret) {
    258                 talloc_free(tmp_ctx);
    259                 return NT_STATUS_INTERNAL_ERROR;
    260         }
    261 
    262         /* and now encode the reply */
    263         blob = data_blob_talloc(kdcconn, NULL, reply.length + 4);
    264         if (!blob.data) {
    265                 talloc_free(tmp_ctx);
    266                 return NT_STATUS_NO_MEMORY;
    267         }
    268 
    269         RSIVAL(blob.data, 0, reply.length);
    270         memcpy(blob.data + 4, reply.data, reply.length);       
    271 
    272         status = packet_send(kdcconn->packet, blob);
    273         if (!NT_STATUS_IS_OK(status)) {
    274                 talloc_free(tmp_ctx);
    275                 return status;
    276         }
    277 
    278         /* the call isn't needed any more */
    279         talloc_free(tmp_ctx);
    280         return NT_STATUS_OK;
    281 }
    282 
    283 /*
    284   receive some data on a KDC connection
    285 */
    286 static void kdc_tcp_recv_handler(struct stream_connection *conn, uint16_t flags)
     109static void kdc_tcp_recv(struct stream_connection *conn, uint16_t flags)
    287110{
    288111        struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
    289112                                                             struct kdc_tcp_connection);
    290         packet_recv(kdcconn->packet);
    291 }
    292 
    293 /*
    294   called on a tcp recv error
    295 */
    296 static void kdc_tcp_recv_error(void *private_data, NTSTATUS status)
    297 {
    298         struct kdc_tcp_connection *kdcconn = talloc_get_type(private_data,
    299                                              struct kdc_tcp_connection);
    300         kdc_tcp_terminate_connection(kdcconn, nt_errstr(status));
    301 }
    302 
    303 /*
    304   called when we can write to a connection
    305 */
     113        /* this should never be triggered! */
     114        kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_recv: called");
     115}
     116
    306117static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
    307118{
    308119        struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
    309120                                                             struct kdc_tcp_connection);
    310         packet_queue_run(kdcconn->packet);
     121        /* this should never be triggered! */
     122        kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_send: called");
    311123}
    312124
     
    316128*/
    317129
    318 static bool kdc_process(struct kdc_server *kdc,
    319                         TALLOC_CTX *mem_ctx,
    320                         DATA_BLOB *input,
    321                         DATA_BLOB *reply,
    322                         struct socket_address *peer_addr,
    323                         struct socket_address *my_addr,
    324                         int datagram_reply)
    325 {
    326         int ret;       
     130static enum kdc_process_ret kdc_process(struct kdc_server *kdc,
     131                                        TALLOC_CTX *mem_ctx,
     132                                        DATA_BLOB *input,
     133                                        DATA_BLOB *reply,
     134                                        struct tsocket_address *peer_addr,
     135                                        struct tsocket_address *my_addr,
     136                                        int datagram_reply)
     137{
     138        int ret;
     139        char *pa;
     140        struct sockaddr_storage ss;
    327141        krb5_data k5_reply;
    328142        krb5_data_zero(&k5_reply);
     
    330144        krb5_kdc_update_time(NULL);
    331145
    332         DEBUG(10,("Received KDC packet of length %lu from %s:%d\n",
    333                   (long)input->length - 4, peer_addr->addr, peer_addr->port));
    334 
    335         ret = krb5_kdc_process_krb5_request(kdc->smb_krb5_context->krb5_context,
     146        ret = tsocket_address_bsd_sockaddr(peer_addr, (struct sockaddr *) &ss,
     147                                sizeof(struct sockaddr_storage));
     148        if (ret < 0) {
     149                return KDC_PROCESS_FAILED;
     150        }
     151        pa = tsocket_address_string(peer_addr, mem_ctx);
     152        if (pa == NULL) {
     153                return KDC_PROCESS_FAILED;
     154        }
     155
     156        DEBUG(10,("Received KDC packet of length %lu from %s\n",
     157                                (long)input->length - 4, pa));
     158
     159        ret = krb5_kdc_process_krb5_request(kdc->smb_krb5_context->krb5_context,
    336160                                            kdc->config,
    337161                                            input->data, input->length,
    338162                                            &k5_reply,
    339                                             peer_addr->addr,
    340                                             peer_addr->sockaddr,
     163                                            pa,
     164                                            (struct sockaddr *) &ss,
    341165                                            datagram_reply);
    342166        if (ret == -1) {
    343167                *reply = data_blob(NULL, 0);
    344                 return false;
    345         }
     168                return KDC_PROCESS_FAILED;
     169        }
     170
     171        if (ret == HDB_ERR_NOT_FOUND_HERE) {
     172                *reply = data_blob(NULL, 0);
     173                return KDC_PROCESS_PROXY;
     174        }
     175
    346176        if (k5_reply.length) {
    347177                *reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length);
    348178                krb5_data_free(&k5_reply);
    349179        } else {
    350                 *reply = data_blob(NULL, 0);   
    351         }
    352         return true;
     180                *reply = data_blob(NULL, 0);
     181        }
     182        return KDC_PROCESS_OK;
     183}
     184
     185static void kdc_tcp_call_proxy_done(struct tevent_req *subreq);
     186static void kdc_tcp_call_writev_done(struct tevent_req *subreq);
     187
     188static void kdc_tcp_call_loop(struct tevent_req *subreq)
     189{
     190        struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq,
     191                                      struct kdc_tcp_connection);
     192        struct kdc_tcp_call *call;
     193        NTSTATUS status;
     194        enum kdc_process_ret ret;
     195
     196        call = talloc(kdc_conn, struct kdc_tcp_call);
     197        if (call == NULL) {
     198                kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     199                                "no memory for kdc_tcp_call");
     200                return;
     201        }
     202        call->kdc_conn = kdc_conn;
     203
     204        status = tstream_read_pdu_blob_recv(subreq,
     205                                            call,
     206                                            &call->in);
     207        TALLOC_FREE(subreq);
     208        if (!NT_STATUS_IS_OK(status)) {
     209                const char *reason;
     210
     211                reason = talloc_asprintf(call, "kdc_tcp_call_loop: "
     212                                         "tstream_read_pdu_blob_recv() - %s",
     213                                         nt_errstr(status));
     214                if (!reason) {
     215                        reason = nt_errstr(status);
     216                }
     217
     218                kdc_tcp_terminate_connection(kdc_conn, reason);
     219                return;
     220        }
     221
     222        DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
     223                 (long) call->in.length,
     224                 tsocket_address_string(kdc_conn->conn->remote_address, call)));
     225
     226        /* skip length header */
     227        call->in.data +=4;
     228        call->in.length -= 4;
     229
     230        /* Call krb5 */
     231        ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
     232                                           call,
     233                                           &call->in,
     234                                           &call->out,
     235                                           kdc_conn->conn->remote_address,
     236                                           kdc_conn->conn->local_address,
     237                                           0 /* Stream */);
     238        if (ret == KDC_PROCESS_FAILED) {
     239                kdc_tcp_terminate_connection(kdc_conn,
     240                                "kdc_tcp_call_loop: process function failed");
     241                return;
     242        }
     243
     244        if (ret == KDC_PROCESS_PROXY) {
     245                uint16_t port;
     246
     247                if (!kdc_conn->kdc_socket->kdc->am_rodc) {
     248                        kdc_tcp_terminate_connection(kdc_conn,
     249                                                     "kdc_tcp_call_loop: proxying requested when not RODC");
     250                        return;
     251                }
     252                port = tsocket_address_inet_port(kdc_conn->conn->local_address);
     253
     254                subreq = kdc_tcp_proxy_send(call,
     255                                            kdc_conn->conn->event.ctx,
     256                                            kdc_conn->kdc_socket->kdc,
     257                                            port,
     258                                            call->in);
     259                if (subreq == NULL) {
     260                        kdc_tcp_terminate_connection(kdc_conn,
     261                                "kdc_tcp_call_loop: kdc_tcp_proxy_send failed");
     262                        return;
     263                }
     264                tevent_req_set_callback(subreq, kdc_tcp_call_proxy_done, call);
     265                return;
     266        }
     267
     268        /* First add the length of the out buffer */
     269        RSIVAL(call->out_hdr, 0, call->out.length);
     270        call->out_iov[0].iov_base = (char *) call->out_hdr;
     271        call->out_iov[0].iov_len = 4;
     272
     273        call->out_iov[1].iov_base = (char *) call->out.data;
     274        call->out_iov[1].iov_len = call->out.length;
     275
     276        subreq = tstream_writev_queue_send(call,
     277                                           kdc_conn->conn->event.ctx,
     278                                           kdc_conn->tstream,
     279                                           kdc_conn->send_queue,
     280                                           call->out_iov, 2);
     281        if (subreq == NULL) {
     282                kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     283                                "no memory for tstream_writev_queue_send");
     284                return;
     285        }
     286        tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
     287
     288        /*
     289         * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
     290         * packet_full_request_u32 provides the pdu length then.
     291         */
     292        subreq = tstream_read_pdu_blob_send(kdc_conn,
     293                                            kdc_conn->conn->event.ctx,
     294                                            kdc_conn->tstream,
     295                                            4, /* initial_read_size */
     296                                            packet_full_request_u32,
     297                                            kdc_conn);
     298        if (subreq == NULL) {
     299                kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     300                                "no memory for tstream_read_pdu_blob_send");
     301                return;
     302        }
     303        tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     304}
     305
     306static void kdc_tcp_call_proxy_done(struct tevent_req *subreq)
     307{
     308        struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
     309                        struct kdc_tcp_call);
     310        struct kdc_tcp_connection *kdc_conn = call->kdc_conn;
     311        NTSTATUS status;
     312
     313        status = kdc_tcp_proxy_recv(subreq, call, &call->out);
     314        TALLOC_FREE(subreq);
     315        if (!NT_STATUS_IS_OK(status)) {
     316                /* generate an error packet */
     317                status = kdc_proxy_unavailable_error(kdc_conn->kdc_socket->kdc,
     318                                                     call, &call->out);
     319        }
     320
     321        if (!NT_STATUS_IS_OK(status)) {
     322                const char *reason;
     323
     324                reason = talloc_asprintf(call, "kdc_tcp_call_proxy_done: "
     325                                         "kdc_proxy_unavailable_error - %s",
     326                                         nt_errstr(status));
     327                if (!reason) {
     328                        reason = "kdc_tcp_call_proxy_done: kdc_proxy_unavailable_error() failed";
     329                }
     330
     331                kdc_tcp_terminate_connection(call->kdc_conn, reason);
     332                return;
     333        }
     334
     335        /* First add the length of the out buffer */
     336        RSIVAL(call->out_hdr, 0, call->out.length);
     337        call->out_iov[0].iov_base = (char *) call->out_hdr;
     338        call->out_iov[0].iov_len = 4;
     339
     340        call->out_iov[1].iov_base = (char *) call->out.data;
     341        call->out_iov[1].iov_len = call->out.length;
     342
     343        subreq = tstream_writev_queue_send(call,
     344                                           kdc_conn->conn->event.ctx,
     345                                           kdc_conn->tstream,
     346                                           kdc_conn->send_queue,
     347                                           call->out_iov, 2);
     348        if (subreq == NULL) {
     349                kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     350                                "no memory for tstream_writev_queue_send");
     351                return;
     352        }
     353        tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
     354
     355        /*
     356         * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
     357         * packet_full_request_u32 provides the pdu length then.
     358         */
     359        subreq = tstream_read_pdu_blob_send(kdc_conn,
     360                                            kdc_conn->conn->event.ctx,
     361                                            kdc_conn->tstream,
     362                                            4, /* initial_read_size */
     363                                            packet_full_request_u32,
     364                                            kdc_conn);
     365        if (subreq == NULL) {
     366                kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
     367                                "no memory for tstream_read_pdu_blob_send");
     368                return;
     369        }
     370        tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
     371}
     372
     373static void kdc_tcp_call_writev_done(struct tevent_req *subreq)
     374{
     375        struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
     376                        struct kdc_tcp_call);
     377        int sys_errno;
     378        int rc;
     379
     380        rc = tstream_writev_queue_recv(subreq, &sys_errno);
     381        TALLOC_FREE(subreq);
     382        if (rc == -1) {
     383                const char *reason;
     384
     385                reason = talloc_asprintf(call, "kdc_tcp_call_writev_done: "
     386                                         "tstream_writev_queue_recv() - %d:%s",
     387                                         sys_errno, strerror(sys_errno));
     388                if (!reason) {
     389                        reason = "kdc_tcp_call_writev_done: tstream_writev_queue_recv() failed";
     390                }
     391
     392                kdc_tcp_terminate_connection(call->kdc_conn, reason);
     393                return;
     394        }
     395
     396        /* We don't care about errors */
     397
     398        talloc_free(call);
    353399}
    354400
     
    356402  called when we get a new connection
    357403*/
    358 static void kdc_tcp_generic_accept(struct stream_connection *conn, kdc_process_fn_t process_fn)
    359 {
    360         struct kdc_server *kdc = talloc_get_type(conn->private_data, struct kdc_server);
    361         struct kdc_tcp_connection *kdcconn;
    362 
    363         kdcconn = talloc_zero(conn, struct kdc_tcp_connection);
    364         if (!kdcconn) {
    365                 stream_terminate_connection(conn, "kdc_tcp_accept: out of memory");
    366                 return;
    367         }
    368         kdcconn->conn    = conn;
    369         kdcconn->kdc     = kdc;
    370         kdcconn->process = process_fn;
    371         conn->private_data    = kdcconn;
    372 
    373         kdcconn->packet = packet_init(kdcconn);
    374         if (kdcconn->packet == NULL) {
    375                 kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_accept: out of memory");
    376                 return;
    377         }
    378         packet_set_private(kdcconn->packet, kdcconn);
    379         packet_set_socket(kdcconn->packet, conn->socket);
    380         packet_set_callback(kdcconn->packet, kdc_tcp_recv);
    381         packet_set_full_request(kdcconn->packet, packet_full_request_u32);
    382         packet_set_error_handler(kdcconn->packet, kdc_tcp_recv_error);
    383         packet_set_event_context(kdcconn->packet, conn->event.ctx);
    384         packet_set_fde(kdcconn->packet, conn->event.fde);
    385         packet_set_serialise(kdcconn->packet);
    386 }
    387 
    388404static void kdc_tcp_accept(struct stream_connection *conn)
    389405{
    390         kdc_tcp_generic_accept(conn, kdc_process);
     406        struct kdc_socket *kdc_socket;
     407        struct kdc_tcp_connection *kdc_conn;
     408        struct tevent_req *subreq;
     409        int rc;
     410
     411        kdc_conn = talloc_zero(conn, struct kdc_tcp_connection);
     412        if (kdc_conn == NULL) {
     413                stream_terminate_connection(conn,
     414                                "kdc_tcp_accept: out of memory");
     415                return;
     416        }
     417
     418        kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept");
     419        if (kdc_conn->send_queue == NULL) {
     420                stream_terminate_connection(conn,
     421                                "kdc_tcp_accept: out of memory");
     422                return;
     423        }
     424
     425        kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);
     426
     427        TALLOC_FREE(conn->event.fde);
     428
     429        rc = tstream_bsd_existing_socket(kdc_conn,
     430                        socket_get_fd(conn->socket),
     431                        &kdc_conn->tstream);
     432        if (rc < 0) {
     433                stream_terminate_connection(conn,
     434                                "kdc_tcp_accept: out of memory");
     435                return;
     436        }
     437
     438        kdc_conn->conn = conn;
     439        kdc_conn->kdc_socket = kdc_socket;
     440        conn->private_data = kdc_conn;
     441
     442        /*
     443         * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
     444         * packet_full_request_u32 provides the pdu length then.
     445         */
     446        subreq = tstream_read_pdu_blob_send(kdc_conn,
     447                                            kdc_conn->conn->event.ctx,
     448                                            kdc_conn->tstream,
     449                                            4, /* initial_read_size */
     450                                            packet_full_request_u32,
     451                                            kdc_conn);
     452        if (subreq == NULL) {
     453                kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_accept: "
     454                                "no memory for tstream_read_pdu_blob_send");
     455                return;
     456        }
     457        tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
    391458}
    392459
     
    394461        .name                   = "kdc_tcp",
    395462        .accept_connection      = kdc_tcp_accept,
    396         .recv_handler           = kdc_tcp_recv_handler,
     463        .recv_handler           = kdc_tcp_recv,
    397464        .send_handler           = kdc_tcp_send
    398465};
    399466
    400 static void kpasswdd_tcp_accept(struct stream_connection *conn)
    401 {
    402         kdc_tcp_generic_accept(conn, kpasswdd_process);
    403 }
    404 
    405 static const struct stream_server_ops kpasswdd_tcp_stream_ops = {
    406         .name                   = "kpasswdd_tcp",
    407         .accept_connection      = kpasswdd_tcp_accept,
    408         .recv_handler           = kdc_tcp_recv_handler,
    409         .send_handler           = kdc_tcp_send
     467/* hold information about one kdc/kpasswd udp socket */
     468struct kdc_udp_socket {
     469        struct kdc_socket *kdc_socket;
     470        struct tdgram_context *dgram;
     471        struct tevent_queue *send_queue;
    410472};
     473
     474struct kdc_udp_call {
     475        struct kdc_udp_socket *sock;
     476        struct tsocket_address *src;
     477        DATA_BLOB in;
     478        DATA_BLOB out;
     479};
     480
     481static void kdc_udp_call_proxy_done(struct tevent_req *subreq);
     482static void kdc_udp_call_sendto_done(struct tevent_req *subreq);
     483
     484static void kdc_udp_call_loop(struct tevent_req *subreq)
     485{
     486        struct kdc_udp_socket *sock = tevent_req_callback_data(subreq,
     487                                      struct kdc_udp_socket);
     488        struct kdc_udp_call *call;
     489        uint8_t *buf;
     490        ssize_t len;
     491        int sys_errno;
     492        enum kdc_process_ret ret;
     493
     494        call = talloc(sock, struct kdc_udp_call);
     495        if (call == NULL) {
     496                talloc_free(call);
     497                goto done;
     498        }
     499        call->sock = sock;
     500
     501        len = tdgram_recvfrom_recv(subreq, &sys_errno,
     502                                   call, &buf, &call->src);
     503        TALLOC_FREE(subreq);
     504        if (len == -1) {
     505                talloc_free(call);
     506                goto done;
     507        }
     508
     509        call->in.data = buf;
     510        call->in.length = len;
     511
     512        DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
     513                 (long)call->in.length,
     514                 tsocket_address_string(call->src, call)));
     515
     516        /* Call krb5 */
     517        ret = sock->kdc_socket->process(sock->kdc_socket->kdc,
     518                                       call,
     519                                       &call->in,
     520                                       &call->out,
     521                                       call->src,
     522                                       sock->kdc_socket->local_address,
     523                                       1 /* Datagram */);
     524        if (ret == KDC_PROCESS_FAILED) {
     525                talloc_free(call);
     526                goto done;
     527        }
     528
     529        if (ret == KDC_PROCESS_PROXY) {
     530                uint16_t port;
     531
     532                if (!sock->kdc_socket->kdc->am_rodc) {
     533                        DEBUG(0,("kdc_udp_call_loop: proxying requested when not RODC"));
     534                        talloc_free(call);
     535                        goto done;
     536                }
     537
     538                port = tsocket_address_inet_port(sock->kdc_socket->local_address);
     539
     540                subreq = kdc_udp_proxy_send(call,
     541                                            sock->kdc_socket->kdc->task->event_ctx,
     542                                            sock->kdc_socket->kdc,
     543                                            port,
     544                                            call->in);
     545                if (subreq == NULL) {
     546                        talloc_free(call);
     547                        goto done;
     548                }
     549                tevent_req_set_callback(subreq, kdc_udp_call_proxy_done, call);
     550                goto done;
     551        }
     552
     553        subreq = tdgram_sendto_queue_send(call,
     554                                          sock->kdc_socket->kdc->task->event_ctx,
     555                                          sock->dgram,
     556                                          sock->send_queue,
     557                                          call->out.data,
     558                                          call->out.length,
     559                                          call->src);
     560        if (subreq == NULL) {
     561                talloc_free(call);
     562                goto done;
     563        }
     564        tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
     565
     566done:
     567        subreq = tdgram_recvfrom_send(sock,
     568                                      sock->kdc_socket->kdc->task->event_ctx,
     569                                      sock->dgram);
     570        if (subreq == NULL) {
     571                task_server_terminate(sock->kdc_socket->kdc->task,
     572                                      "no memory for tdgram_recvfrom_send",
     573                                      true);
     574                return;
     575        }
     576        tevent_req_set_callback(subreq, kdc_udp_call_loop, sock);
     577}
     578
     579static void kdc_udp_call_proxy_done(struct tevent_req *subreq)
     580{
     581        struct kdc_udp_call *call =
     582                tevent_req_callback_data(subreq,
     583                struct kdc_udp_call);
     584        NTSTATUS status;
     585
     586        status = kdc_udp_proxy_recv(subreq, call, &call->out);
     587        TALLOC_FREE(subreq);
     588        if (!NT_STATUS_IS_OK(status)) {
     589                /* generate an error packet */
     590                status = kdc_proxy_unavailable_error(call->sock->kdc_socket->kdc,
     591                                                     call, &call->out);
     592        }
     593
     594        if (!NT_STATUS_IS_OK(status)) {
     595                talloc_free(call);
     596                return;
     597        }
     598
     599        subreq = tdgram_sendto_queue_send(call,
     600                                          call->sock->kdc_socket->kdc->task->event_ctx,
     601                                          call->sock->dgram,
     602                                          call->sock->send_queue,
     603                                          call->out.data,
     604                                          call->out.length,
     605                                          call->src);
     606        if (subreq == NULL) {
     607                talloc_free(call);
     608                return;
     609        }
     610
     611        tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
     612}
     613
     614static void kdc_udp_call_sendto_done(struct tevent_req *subreq)
     615{
     616        struct kdc_udp_call *call = tevent_req_callback_data(subreq,
     617                                       struct kdc_udp_call);
     618        ssize_t ret;
     619        int sys_errno;
     620
     621        ret = tdgram_sendto_queue_recv(subreq, &sys_errno);
     622
     623        /* We don't care about errors */
     624
     625        talloc_free(call);
     626}
    411627
    412628/*
    413629  start listening on the given address
    414630*/
    415 static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address,
    416                                uint16_t kdc_port, uint16_t kpasswd_port)
    417 {
    418         const struct model_ops *model_ops;
    419         struct kdc_socket *kdc_socket;
    420         struct kdc_socket *kpasswd_socket;
    421         struct socket_address *kdc_address, *kpasswd_address;
     631static NTSTATUS kdc_add_socket(struct kdc_server *kdc,
     632                               const struct model_ops *model_ops,
     633                               const char *name,
     634                               const char *address,
     635                               uint16_t port,
     636                               kdc_process_fn_t process,
     637                               bool udp_only)
     638{
     639        struct kdc_socket *kdc_socket;
     640        struct kdc_udp_socket *kdc_udp_socket;
     641        struct tevent_req *udpsubreq;
    422642        NTSTATUS status;
     643        int ret;
    423644
    424645        kdc_socket = talloc(kdc, struct kdc_socket);
    425646        NT_STATUS_HAVE_NO_MEMORY(kdc_socket);
    426647
    427         kpasswd_socket = talloc(kdc, struct kdc_socket);
    428         NT_STATUS_HAVE_NO_MEMORY(kpasswd_socket);
    429 
    430         status = socket_create("ip", SOCKET_TYPE_DGRAM, &kdc_socket->sock, 0);
    431         if (!NT_STATUS_IS_OK(status)) {
    432                 talloc_free(kdc_socket);
     648        kdc_socket->kdc = kdc;
     649        kdc_socket->process = process;
     650
     651        ret = tsocket_address_inet_from_strings(kdc_socket, "ip",
     652                                                address, port,
     653                                                &kdc_socket->local_address);
     654        if (ret != 0) {
     655                status = map_nt_error_from_unix(errno);
    433656                return status;
    434657        }
    435658
    436         status = socket_create("ip", SOCKET_TYPE_DGRAM, &kpasswd_socket->sock, 0);
    437         if (!NT_STATUS_IS_OK(status)) {
    438                 talloc_free(kpasswd_socket);
     659        if (!udp_only) {
     660                status = stream_setup_socket(kdc->task,
     661                                             kdc->task->event_ctx,
     662                                             kdc->task->lp_ctx,
     663                                             model_ops,
     664                                             &kdc_tcp_stream_ops,
     665                                             "ip", address, &port,
     666                                             lpcfg_socket_options(kdc->task->lp_ctx),
     667                                             kdc_socket);
     668                if (!NT_STATUS_IS_OK(status)) {
     669                        DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
     670                                 address, port, nt_errstr(status)));
     671                        talloc_free(kdc_socket);
     672                        return status;
     673                }
     674        }
     675
     676        kdc_udp_socket = talloc(kdc_socket, struct kdc_udp_socket);
     677        NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket);
     678
     679        kdc_udp_socket->kdc_socket = kdc_socket;
     680
     681        ret = tdgram_inet_udp_socket(kdc_socket->local_address,
     682                                     NULL,
     683                                     kdc_udp_socket,
     684                                     &kdc_udp_socket->dgram);
     685        if (ret != 0) {
     686                status = map_nt_error_from_unix(errno);
     687                DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
     688                         address, port, nt_errstr(status)));
    439689                return status;
    440690        }
    441691
    442         kdc_socket->kdc = kdc;
    443         kdc_socket->send_queue = NULL;
    444         kdc_socket->process = kdc_process;
    445 
    446         talloc_steal(kdc_socket, kdc_socket->sock);
    447 
    448         kdc_socket->fde = event_add_fd(kdc->task->event_ctx, kdc,
    449                                        socket_get_fd(kdc_socket->sock), EVENT_FD_READ,
    450                                        kdc_socket_handler, kdc_socket);
    451 
    452         kdc_address = socket_address_from_strings(kdc_socket, kdc_socket->sock->backend_name,
    453                                                   address, kdc_port);
    454         NT_STATUS_HAVE_NO_MEMORY(kdc_address);
    455 
    456         status = socket_listen(kdc_socket->sock, kdc_address, 0, 0);
    457         if (!NT_STATUS_IS_OK(status)) {
    458                 DEBUG(0,("Failed to bind to %s:%d UDP for kdc - %s\n",
    459                          address, kdc_port, nt_errstr(status)));
    460                 talloc_free(kdc_socket);
    461                 return status;
    462         }
    463 
    464         kpasswd_socket->kdc = kdc;
    465         kpasswd_socket->send_queue = NULL;
    466         kpasswd_socket->process = kpasswdd_process;
    467 
    468         talloc_steal(kpasswd_socket, kpasswd_socket->sock);
    469 
    470         kpasswd_socket->fde = event_add_fd(kdc->task->event_ctx, kdc,
    471                                            socket_get_fd(kpasswd_socket->sock), EVENT_FD_READ,
    472                                            kdc_socket_handler, kpasswd_socket);
    473        
    474         kpasswd_address = socket_address_from_strings(kpasswd_socket, kpasswd_socket->sock->backend_name,
    475                                                       address, kpasswd_port);
    476         NT_STATUS_HAVE_NO_MEMORY(kpasswd_address);
    477 
    478         status = socket_listen(kpasswd_socket->sock, kpasswd_address, 0, 0);
    479         if (!NT_STATUS_IS_OK(status)) {
    480                 DEBUG(0,("Failed to bind to %s:%d UDP for kpasswd - %s\n",
    481                          address, kpasswd_port, nt_errstr(status)));
    482                 talloc_free(kpasswd_socket);
    483                 return status;
    484         }
    485 
    486         /* within the kdc task we want to be a single process, so
    487            ask for the single process model ops and pass these to the
    488            stream_setup_socket() call. */
    489         model_ops = process_model_startup(kdc->task->event_ctx, "single");
    490         if (!model_ops) {
    491                 DEBUG(0,("Can't find 'single' process model_ops\n"));
    492                 talloc_free(kdc_socket);
    493                 return NT_STATUS_INTERNAL_ERROR;
    494         }
    495 
    496         status = stream_setup_socket(kdc->task->event_ctx,
    497                                      kdc->task->lp_ctx,
    498                                      model_ops,
    499                                      &kdc_tcp_stream_ops,
    500                                      "ip", address, &kdc_port,
    501                                      lp_socket_options(kdc->task->lp_ctx),
    502                                      kdc);
    503         if (!NT_STATUS_IS_OK(status)) {
    504                 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
    505                          address, kdc_port, nt_errstr(status)));
    506                 talloc_free(kdc_socket);
    507                 return status;
    508         }
    509 
    510         status = stream_setup_socket(kdc->task->event_ctx,
    511                                      kdc->task->lp_ctx,
    512                                      model_ops,
    513                                      &kpasswdd_tcp_stream_ops,
    514                                      "ip", address, &kpasswd_port,
    515                                      lp_socket_options(kdc->task->lp_ctx),
    516                                      kdc);
    517         if (!NT_STATUS_IS_OK(status)) {
    518                 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
    519                          address, kpasswd_port, nt_errstr(status)));
    520                 talloc_free(kdc_socket);
    521                 return status;
    522         }
     692        kdc_udp_socket->send_queue = tevent_queue_create(kdc_udp_socket,
     693                                                         "kdc_udp_send_queue");
     694        NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket->send_queue);
     695
     696        udpsubreq = tdgram_recvfrom_send(kdc_udp_socket,
     697                                         kdc->task->event_ctx,
     698                                         kdc_udp_socket->dgram);
     699        NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
     700        tevent_req_set_callback(udpsubreq, kdc_udp_call_loop, kdc_udp_socket);
    523701
    524702        return NT_STATUS_OK;
     
    532710                                       struct interface *ifaces)
    533711{
     712        const struct model_ops *model_ops;
    534713        int num_interfaces;
    535714        TALLOC_CTX *tmp_ctx = talloc_new(kdc);
    536715        NTSTATUS status;
    537716        int i;
     717        uint16_t kdc_port = lpcfg_krb5_port(lp_ctx);
     718        uint16_t kpasswd_port = lpcfg_kpasswd_port(lp_ctx);
     719        bool done_wildcard = false;
     720
     721        /* within the kdc task we want to be a single process, so
     722           ask for the single process model ops and pass these to the
     723           stream_setup_socket() call. */
     724        model_ops = process_model_startup("single");
     725        if (!model_ops) {
     726                DEBUG(0,("Can't find 'single' process model_ops\n"));
     727                return NT_STATUS_INTERNAL_ERROR;
     728        }
    538729
    539730        num_interfaces = iface_count(ifaces);
    540        
     731
     732        /* if we are allowing incoming packets from any address, then
     733           we need to bind to the wildcard address */
     734        if (!lpcfg_bind_interfaces_only(lp_ctx)) {
     735                if (kdc_port) {
     736                        status = kdc_add_socket(kdc, model_ops,
     737                                                "kdc", "0.0.0.0", kdc_port,
     738                                                kdc_process, false);
     739                        NT_STATUS_NOT_OK_RETURN(status);
     740                }
     741
     742                if (kpasswd_port) {
     743                        status = kdc_add_socket(kdc, model_ops,
     744                                                "kpasswd", "0.0.0.0", kpasswd_port,
     745                                                kpasswdd_process, false);
     746                        NT_STATUS_NOT_OK_RETURN(status);
     747                }
     748                done_wildcard = true;
     749        }
     750
    541751        for (i=0; i<num_interfaces; i++) {
    542752                const char *address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
    543                 status = kdc_add_socket(kdc, address, lp_krb5_port(lp_ctx),
    544                                         lp_kpasswd_port(lp_ctx));
    545                 NT_STATUS_NOT_OK_RETURN(status);
     753
     754                if (kdc_port) {
     755                        status = kdc_add_socket(kdc, model_ops,
     756                                                "kdc", address, kdc_port,
     757                                                kdc_process, done_wildcard);
     758                        NT_STATUS_NOT_OK_RETURN(status);
     759                }
     760
     761                if (kpasswd_port) {
     762                        status = kdc_add_socket(kdc, model_ops,
     763                                                "kpasswd", address, kpasswd_port,
     764                                                kpasswdd_process, done_wildcard);
     765                        NT_STATUS_NOT_OK_RETURN(status);
     766                }
    546767        }
    547768
     
    552773
    553774
    554 static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, 
     775static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg,
    555776                                 struct kdc_check_generic_kerberos *r)
    556777{
     
    570791        r->out.generic_reply = data_blob(NULL, 0);
    571792
    572         ndr_err = ndr_pull_struct_blob(&r->in.generic_request, msg,
    573                                        lp_iconv_convenience(kdc->task->lp_ctx),
    574                                        &pac_validate,
     793        ndr_err = ndr_pull_struct_blob(&r->in.generic_request, msg, &pac_validate,
    575794                                       (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
    576795        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    577796                return NT_STATUS_INVALID_PARAMETER;
    578797        }
    579        
     798
    580799        if (pac_validate.MessageType != 3) {
    581800                /* We don't implement any other message types - such as certificate validation - yet */
     
    588807                return NT_STATUS_INVALID_PARAMETER;
    589808        }
    590        
    591         srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data, 
     809
     810        srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data,
    592811                                  pac_validate.ChecksumLength);
    593        
     812
    594813        if (pac_validate.SignatureType == CKSUMTYPE_HMAC_MD5) {
    595814                etype = ETYPE_ARCFOUR_HMAC_MD5;
     
    602821        }
    603822
    604         ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal, 
    605                                   lp_realm(kdc->task->lp_ctx),
    606                                   "krbtgt", lp_realm(kdc->task->lp_ctx),
     823        ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal,
     824                                  lpcfg_realm(kdc->task->lp_ctx),
     825                                  "krbtgt", lpcfg_realm(kdc->task->lp_ctx),
    607826                                  NULL);
    608827
     
    611830        }
    612831
    613         ret = kdc->config->db[0]->hdb_fetch(kdc->smb_krb5_context->krb5_context,
    614                                             kdc->config->db[0],
    615                                             principal,
    616                                             HDB_F_GET_KRBTGT | HDB_F_DECRYPT,
    617                                             &ent);
    618 
     832        ret = kdc->config->db[0]->hdb_fetch_kvno(kdc->smb_krb5_context->krb5_context,
     833                                                 kdc->config->db[0],
     834                                                 principal,
     835                                                 HDB_F_GET_KRBTGT | HDB_F_DECRYPT,
     836                                                 0,
     837                                                 &ent);
     838       
    619839        if (ret != 0) {
    620840                hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
    621841                krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);
    622        
     842
    623843                return NT_STATUS_LOGON_FAILURE;
    624844        }
    625        
     845
    626846        ret = hdb_enctype2key(kdc->smb_krb5_context->krb5_context, &ent.entry, etype, &key);
    627847
     
    633853
    634854        keyblock = key->key;
    635        
     855
    636856        kdc_sig.type = pac_validate.SignatureType;
    637857        kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength],
    638858                                            pac_validate.SignatureLength);
    639         ret = check_pac_checksum(msg, srv_sig, &kdc_sig, 
     859        ret = check_pac_checksum(msg, srv_sig, &kdc_sig,
    640860                           kdc->smb_krb5_context->krb5_context, &keyblock);
    641861
     
    646866                return NT_STATUS_LOGON_FAILURE;
    647867        }
    648        
     868
    649869        return NT_STATUS_OK;
    650870}
     
    660880        krb5_error_code ret;
    661881        struct interface *ifaces;
    662 
    663         switch (lp_server_role(task->lp_ctx)) {
     882        int ldb_ret;
     883
     884        switch (lpcfg_server_role(task->lp_ctx)) {
    664885        case ROLE_STANDALONE:
    665886                task_server_terminate(task, "kdc: no KDC required in standalone configuration", false);
     
    673894        }
    674895
    675         load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces);
     896        load_interfaces(task, lpcfg_interfaces(task->lp_ctx), &ifaces);
    676897
    677898        if (iface_count(ifaces) == 0) {
     
    682903        task_server_set_title(task, "task[kdc]");
    683904
    684         kdc = talloc(task, struct kdc_server);
     905        kdc = talloc_zero(task, struct kdc_server);
    685906        if (kdc == NULL) {
    686907                task_server_terminate(task, "kdc: out of memory", true);
     
    690911        kdc->task = task;
    691912
     913
     914        /* get a samdb connection */
     915        kdc->samdb = samdb_connect(kdc, kdc->task->event_ctx, kdc->task->lp_ctx,
     916                                   system_session(kdc->task->lp_ctx), 0);
     917        if (!kdc->samdb) {
     918                DEBUG(1,("kdc_task_init: unable to connect to samdb\n"));
     919                task_server_terminate(task, "kdc: krb5_init_context samdb connect failed", true);
     920                return;
     921        }
     922
     923        ldb_ret = samdb_rodc(kdc->samdb, &kdc->am_rodc);
     924        if (ldb_ret != LDB_SUCCESS) {
     925                DEBUG(1, ("kdc_task_init: Cannot determine if we are an RODC: %s\n",
     926                          ldb_errstring(kdc->samdb)));
     927                task_server_terminate(task, "kdc: krb5_init_context samdb RODC connect failed", true);
     928                return;
     929        }
     930
     931        kdc->proxy_timeout = lpcfg_parm_int(kdc->task->lp_ctx, NULL, "kdc", "proxy timeout", 5);
     932
    692933        initialize_krb5_error_table();
    693934
    694935        ret = smb_krb5_init_context(kdc, task->event_ctx, task->lp_ctx, &kdc->smb_krb5_context);
    695936        if (ret) {
    696                 DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", 
     937                DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n",
    697938                         error_message(ret)));
    698939                task_server_terminate(task, "kdc: krb5_init_context failed", true);
    699                 return; 
     940                return;
    700941        }
    701942
    702943        krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r);
    703944
    704         ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context, 
     945        ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context,
    705946                                  &kdc->config);
    706947        if(ret) {
     
    708949                return;
    709950        }
    710  
     951
    711952        kdc->config->logf = kdc->smb_krb5_context->logf;
    712953        kdc->config->db = talloc(kdc, struct HDB *);
     
    716957        }
    717958        kdc->config->num_db = 1;
    718                
    719         status = hdb_samba4_create_kdc(kdc, task->event_ctx, task->lp_ctx,
    720                                        kdc->smb_krb5_context->krb5_context,
     959
     960        /* Register hdb-samba4 hooks for use as a keytab */
     961
     962        kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context);
     963        if (!kdc->base_ctx) {
     964                task_server_terminate(task, "kdc: out of memory", true);
     965                return;
     966        }
     967
     968        kdc->base_ctx->ev_ctx = task->event_ctx;
     969        kdc->base_ctx->lp_ctx = task->lp_ctx;
     970
     971        status = hdb_samba4_create_kdc(kdc->base_ctx,
     972                                       kdc->smb_krb5_context->krb5_context,
    721973                                       &kdc->config->db[0]);
    722974        if (!NT_STATUS_IS_OK(status)) {
    723975                task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true);
    724                 return;
    725         }
    726 
    727         /* Register hdb-samba4 hooks for use as a keytab */
    728 
    729         kdc->hdb_samba4_context = talloc(kdc, struct hdb_samba4_context);
    730         if (!kdc->hdb_samba4_context) {
    731                 task_server_terminate(task, "kdc: out of memory", true);
    732                 return;
    733         }
    734 
    735         kdc->hdb_samba4_context->ev_ctx = task->event_ctx;
    736         kdc->hdb_samba4_context->lp_ctx = task->lp_ctx;
    737 
    738         ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
     976                return;
     977        }
     978
     979        ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
    739980                                   PLUGIN_TYPE_DATA, "hdb",
    740981                                   &hdb_samba4);
    741982        if(ret) {
    742                 task_server_terminate(task, "kdc: failed to register hdb keytab", true);
     983                task_server_terminate(task, "kdc: failed to register hdb plugin", true);
    743984                return;
    744985        }
     
    746987        ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops);
    747988        if(ret) {
    748                 task_server_terminate(task, "kdc: failed to register hdb keytab", true);
    749                 return;
    750         }
    751 
    752         /* Registar WinDC hooks */
    753         ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, 
     989                task_server_terminate(task, "kdc: failed to register keytab plugin", true);
     990                return;
     991        }
     992
     993        /* Register WinDC hooks */
     994        ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context,
    754995                                   PLUGIN_TYPE_DATA, "windc",
    755996                                   &windc_plugin_table);
    756997        if(ret) {
    757                 task_server_terminate(task, "kdc: failed to register hdb keytab", true);
    758                 return;
    759         }
    760 
    761         krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context);
     998                task_server_terminate(task, "kdc: failed to register windc plugin", true);
     999                return;
     1000        }
     1001
     1002        ret = krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context);
     1003
     1004        if(ret) {
     1005                task_server_terminate(task, "kdc: failed to init windc plugin", true);
     1006                return;
     1007        }
     1008
     1009        ret = krb5_kdc_pkinit_config(kdc->smb_krb5_context->krb5_context, kdc->config);
     1010
     1011        if(ret) {
     1012                task_server_terminate(task, "kdc: failed to init kdc pkinit subsystem", true);
     1013                return;
     1014        }
    7621015
    7631016        /* start listening on the configured network interfaces */
     
    7681021        }
    7691022
    770         status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS, 
     1023        status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS,
    7711024                               kdc_check_generic_kerberos, kdc);
    7721025        if (!NT_STATUS_IS_OK(status)) {
    773                 task_server_terminate(task, "nbtd failed to setup monitoring", true);
     1026                task_server_terminate(task, "kdc failed to setup monitoring", true);
    7741027                return;
    7751028        }
Note: See TracChangeset for help on using the changeset viewer.