root/source4/rpc_server/service_rpc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dcerpc_write_fn
  2. dcesrv_terminate_connection
  3. dcesrv_sock_report_output_data
  4. dcesrv_sock_get_my_addr
  5. dcesrv_sock_get_peer_addr
  6. dcesrv_sock_accept
  7. dcesrv_sock_recv
  8. dcesrv_sock_send
  9. dcesrv_add_ep_unix
  10. dcesrv_add_ep_ncalrpc
  11. dcesrv_add_ep_np
  12. add_socket_rpc_tcp_iface
  13. dcesrv_add_ep_tcp
  14. dcesrv_add_ep
  15. dcesrv_task_init
  16. server_service_rpc_init

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    smbd-specific dcerpc server code
   5 
   6    Copyright (C) Andrew Tridgell 2003-2005
   7    Copyright (C) Stefan (metze) Metzmacher 2004-2005
   8    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2004,2007
   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 "librpc/gen_ndr/ndr_dcerpc.h"
  26 #include "auth/auth.h"
  27 #include "auth/gensec/gensec.h"
  28 #include "../lib/util/dlinklist.h"
  29 #include "rpc_server/dcerpc_server.h"
  30 #include "rpc_server/dcerpc_server_proto.h"
  31 #include "lib/events/events.h"
  32 #include "smbd/service_task.h"
  33 #include "smbd/service_stream.h"
  34 #include "smbd/service.h"
  35 #include "system/filesys.h"
  36 #include "libcli/security/security.h"
  37 #include "lib/socket/socket.h"
  38 #include "lib/messaging/irpc.h"
  39 #include "system/network.h"
  40 #include "lib/socket/netif.h"
  41 #include "param/param.h"
  42 
  43 struct dcesrv_socket_context {
  44         const struct dcesrv_endpoint *endpoint;
  45         struct dcesrv_context *dcesrv_ctx;
  46 };
  47 
  48 /*
  49   write_fn callback for dcesrv_output()
  50 */
  51 static NTSTATUS dcerpc_write_fn(void *private_data, DATA_BLOB *out, size_t *nwritten)
     /* [<][>][^][v][top][bottom][index][help] */
  52 {
  53         NTSTATUS status;
  54         struct socket_context *sock = talloc_get_type(private_data, struct socket_context);
  55         size_t sendlen;
  56 
  57         status = socket_send(sock, out, &sendlen);
  58         NT_STATUS_IS_ERR_RETURN(status);
  59 
  60         *nwritten = sendlen;
  61         return status;
  62 }
  63 
  64 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
     /* [<][>][^][v][top][bottom][index][help] */
  65 {
  66         struct stream_connection *srv_conn;
  67         srv_conn = talloc_get_type(dce_conn->transport.private_data,
  68                                    struct stream_connection);
  69 
  70         stream_terminate_connection(srv_conn, reason);
  71 }
  72 
  73 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dcesrv_conn)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75         struct stream_connection *srv_conn;
  76         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
  77                                    struct stream_connection);
  78 
  79         if (srv_conn && srv_conn->event.fde) {
  80                 EVENT_FD_WRITEABLE(srv_conn->event.fde);
  81         }
  82 }
  83 
  84 static struct socket_address *dcesrv_sock_get_my_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
  85 {
  86         struct stream_connection *srv_conn;
  87         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
  88                                    struct stream_connection);
  89 
  90         return socket_get_my_addr(srv_conn->socket, mem_ctx);
  91 }
  92 
  93 static struct socket_address *dcesrv_sock_get_peer_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
  94 {
  95         struct stream_connection *srv_conn;
  96         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
  97                                    struct stream_connection);
  98 
  99         return socket_get_peer_addr(srv_conn->socket, mem_ctx);
 100 }
 101 
 102 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104         NTSTATUS status;
 105         struct dcesrv_socket_context *dcesrv_sock = 
 106                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
 107         struct dcesrv_connection *dcesrv_conn = NULL;
 108 
 109         if (!srv_conn->session_info) {
 110                 status = auth_anonymous_session_info(srv_conn,
 111                                                      srv_conn->event.ctx,
 112                                                      srv_conn->lp_ctx,
 113                                                      &srv_conn->session_info);
 114                 if (!NT_STATUS_IS_OK(status)) {
 115                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
 116                                 nt_errstr(status)));
 117                         stream_terminate_connection(srv_conn, nt_errstr(status));
 118                         return;
 119                 }
 120         }
 121 
 122         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
 123                                          srv_conn,
 124                                          dcesrv_sock->endpoint,
 125                                          srv_conn->session_info,
 126                                          srv_conn->event.ctx,
 127                                          srv_conn->msg_ctx,
 128                                          srv_conn->server_id,
 129                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
 130                                          &dcesrv_conn);
 131         if (!NT_STATUS_IS_OK(status)) {
 132                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n", 
 133                         nt_errstr(status)));
 134                 stream_terminate_connection(srv_conn, nt_errstr(status));
 135                 return;
 136         }
 137 
 138         dcesrv_conn->transport.private_data             = srv_conn;
 139         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
 140         dcesrv_conn->transport.get_my_addr              = dcesrv_sock_get_my_addr;
 141         dcesrv_conn->transport.get_peer_addr            = dcesrv_sock_get_peer_addr;
 142 
 143         if (dcesrv_sock->endpoint->ep_description->transport == NCACN_NP) {
 144                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
 145         }
 146 
 147         srv_conn->private_data = dcesrv_conn;
 148 
 149         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
 150 
 151         return; 
 152 }
 153 
 154 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 155 {
 156         NTSTATUS status;
 157         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data, struct dcesrv_connection);
 158         DATA_BLOB tmp_blob;
 159         size_t nread;
 160 
 161         if (dce_conn->processing) {
 162                 EVENT_FD_NOT_READABLE(conn->event.fde);
 163                 return;
 164         }
 165 
 166         tmp_blob = data_blob_talloc(conn->socket, NULL, 0x1000);
 167         if (tmp_blob.data == NULL) {
 168                 dcesrv_terminate_connection(dce_conn, "out of memory");
 169                 return;
 170         }
 171 
 172         status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread);
 173         if (NT_STATUS_IS_ERR(status)) {
 174                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
 175                 return;
 176         }
 177         if (nread == 0) {
 178                 talloc_free(tmp_blob.data);
 179                 return;
 180         }
 181 
 182         tmp_blob.length = nread;
 183 
 184         dce_conn->processing = true;
 185         status = dcesrv_input(dce_conn, &tmp_blob);
 186         dce_conn->processing = false;
 187         talloc_free(tmp_blob.data);
 188 
 189         EVENT_FD_READABLE(conn->event.fde);
 190 
 191         if (!NT_STATUS_IS_OK(status)) {
 192                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
 193                 return;
 194         }
 195 
 196         if (dce_conn->call_list && dce_conn->call_list->replies) {
 197                 EVENT_FD_WRITEABLE(conn->event.fde);
 198         }
 199 }
 200 
 201 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 202 {
 203         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data, struct dcesrv_connection);
 204         NTSTATUS status;
 205 
 206         status = dcesrv_output(dce_conn, conn->socket, dcerpc_write_fn);
 207         if (NT_STATUS_IS_ERR(status)) {
 208                 dcesrv_terminate_connection(dce_conn, "eof on socket");
 209                 return;
 210         }
 211 
 212         if (!dce_conn->call_list || !dce_conn->call_list->replies) {
 213                 EVENT_FD_NOT_WRITEABLE(conn->event.fde);
 214         }
 215 }
 216 
 217 
 218 static const struct stream_server_ops dcesrv_stream_ops = {
 219         .name                   = "rpc",
 220         .accept_connection      = dcesrv_sock_accept,
 221         .recv_handler           = dcesrv_sock_recv,
 222         .send_handler           = dcesrv_sock_send,
 223 };
 224 
 225 
 226 
 227 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 228                                    struct loadparm_context *lp_ctx,
 229                                    struct dcesrv_endpoint *e,
 230                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
 231 {
 232         struct dcesrv_socket_context *dcesrv_sock;
 233         uint16_t port = 1;
 234         NTSTATUS status;
 235 
 236         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
 237         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 238 
 239         /* remember the endpoint of this socket */
 240         dcesrv_sock->endpoint           = e;
 241         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
 242 
 243         status = stream_setup_socket(event_ctx, lp_ctx,
 244                                      model_ops, &dcesrv_stream_ops, 
 245                                      "unix", e->ep_description->endpoint, &port, 
 246                                      lp_socket_options(lp_ctx), 
 247                                      dcesrv_sock);
 248         if (!NT_STATUS_IS_OK(status)) {
 249                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
 250                          e->ep_description->endpoint, nt_errstr(status)));
 251         }
 252 
 253         return status;
 254 }
 255 
 256 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 257                                       struct loadparm_context *lp_ctx,
 258                                       struct dcesrv_endpoint *e,
 259                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
 260 {
 261         struct dcesrv_socket_context *dcesrv_sock;
 262         uint16_t port = 1;
 263         char *full_path;
 264         NTSTATUS status;
 265 
 266         if (!e->ep_description->endpoint) {
 267                 /* No identifier specified: use DEFAULT. 
 268                  * DO NOT hardcode this value anywhere else. Rather, specify 
 269                  * no endpoint and let the epmapper worry about it. */
 270                 e->ep_description->endpoint = talloc_strdup(dce_ctx, "DEFAULT");
 271         }
 272 
 273         full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(lp_ctx), 
 274                                     e->ep_description->endpoint);
 275 
 276         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
 277         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 278 
 279         /* remember the endpoint of this socket */
 280         dcesrv_sock->endpoint           = e;
 281         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
 282 
 283         status = stream_setup_socket(event_ctx, lp_ctx,
 284                                      model_ops, &dcesrv_stream_ops, 
 285                                      "unix", full_path, &port, 
 286                                      lp_socket_options(lp_ctx), 
 287                                      dcesrv_sock);
 288         if (!NT_STATUS_IS_OK(status)) {
 289                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
 290                          e->ep_description->endpoint, full_path, nt_errstr(status)));
 291         }
 292         return status;
 293 }
 294 
 295 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 296                                  struct loadparm_context *lp_ctx,
 297                                  struct dcesrv_endpoint *e,
 298                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
 299 {
 300         struct dcesrv_socket_context *dcesrv_sock;
 301         NTSTATUS status;
 302                         
 303         if (e->ep_description->endpoint == NULL) {
 304                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
 305                 return NT_STATUS_INVALID_PARAMETER;
 306         }
 307 
 308         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
 309         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 310 
 311         /* remember the endpoint of this socket */
 312         dcesrv_sock->endpoint           = e;
 313         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
 314 
 315         status = stream_setup_named_pipe(event_ctx, lp_ctx,
 316                                          model_ops, &dcesrv_stream_ops,
 317                                          e->ep_description->endpoint, dcesrv_sock);
 318         if (!NT_STATUS_IS_OK(status)) {
 319                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
 320                          e->ep_description->endpoint, nt_errstr(status)));
 321                 return status;
 322         }
 323 
 324         return NT_STATUS_OK;
 325 }
 326 
 327 /*
 328   add a socket address to the list of events, one event per dcerpc endpoint
 329 */
 330 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
     /* [<][>][^][v][top][bottom][index][help] */
 331                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
 332                                          const char *address)
 333 {
 334         struct dcesrv_socket_context *dcesrv_sock;
 335         uint16_t port = 0;
 336         NTSTATUS status;
 337                         
 338         if (e->ep_description->endpoint) {
 339                 port = atoi(e->ep_description->endpoint);
 340         }
 341 
 342         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
 343         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
 344 
 345         /* remember the endpoint of this socket */
 346         dcesrv_sock->endpoint           = e;
 347         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
 348 
 349         status = stream_setup_socket(event_ctx, dce_ctx->lp_ctx,
 350                                      model_ops, &dcesrv_stream_ops, 
 351                                      "ipv4", address, &port, 
 352                                      lp_socket_options(dce_ctx->lp_ctx), 
 353                                      dcesrv_sock);
 354         if (!NT_STATUS_IS_OK(status)) {
 355                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n", 
 356                          address, port, nt_errstr(status)));
 357         }
 358 
 359         if (e->ep_description->endpoint == NULL) {
 360                 e->ep_description->endpoint = talloc_asprintf(dce_ctx, "%d", port);
 361         }
 362 
 363         return status;
 364 }
 365 
 366 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 367                                   struct loadparm_context *lp_ctx,
 368                                   struct dcesrv_endpoint *e,
 369                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
 370 {
 371         NTSTATUS status;
 372 
 373         /* Add TCP/IP sockets */
 374         if (lp_interfaces(lp_ctx) && lp_bind_interfaces_only(lp_ctx)) {
 375                 int num_interfaces;
 376                 int i;
 377                 struct interface *ifaces;
 378 
 379                 load_interfaces(dce_ctx, lp_interfaces(lp_ctx), &ifaces);
 380 
 381                 num_interfaces = iface_count(ifaces);
 382                 for(i = 0; i < num_interfaces; i++) {
 383                         const char *address = iface_n_ip(ifaces, i);
 384                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
 385                         NT_STATUS_NOT_OK_RETURN(status);
 386                 }
 387         } else {
 388                 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, 
 389                                                   lp_socket_address(lp_ctx));
 390                 NT_STATUS_NOT_OK_RETURN(status);
 391         }
 392 
 393         return NT_STATUS_OK;
 394 }
 395 
 396 
 397 static NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 398                               struct loadparm_context *lp_ctx,
 399                               struct dcesrv_endpoint *e,
 400                           struct tevent_context *event_ctx, const struct model_ops *model_ops)
 401 {
 402         switch (e->ep_description->transport) {
 403         case NCACN_UNIX_STREAM:
 404                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
 405 
 406         case NCALRPC:
 407                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
 408 
 409         case NCACN_IP_TCP:
 410                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
 411 
 412         case NCACN_NP:
 413                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
 414 
 415         default:
 416                 return NT_STATUS_NOT_SUPPORTED;
 417         }
 418 }
 419 
 420 /*
 421   open the dcerpc server sockets
 422 */
 423 static void dcesrv_task_init(struct task_server *task)
     /* [<][>][^][v][top][bottom][index][help] */
 424 {
 425         NTSTATUS status;
 426         struct dcesrv_context *dce_ctx;
 427         struct dcesrv_endpoint *e;
 428 
 429         dcerpc_server_init(task->lp_ctx);
 430 
 431         task_server_set_title(task, "task[dcesrv]");
 432 
 433         status = dcesrv_init_context(task->event_ctx,
 434                                      task->lp_ctx,
 435                                      lp_dcerpc_endpoint_servers(task->lp_ctx),
 436                                      &dce_ctx);
 437         if (!NT_STATUS_IS_OK(status)) goto failed;
 438 
 439         /* Make sure the directory for NCALRPC exists */
 440         if (!directory_exist(lp_ncalrpc_dir(task->lp_ctx))) {
 441                 mkdir(lp_ncalrpc_dir(task->lp_ctx), 0755);
 442         }
 443 
 444         for (e=dce_ctx->endpoint_list;e;e=e->next) {
 445                 status = dcesrv_add_ep(dce_ctx, task->lp_ctx, e, task->event_ctx, task->model_ops);
 446                 if (!NT_STATUS_IS_OK(status)) goto failed;
 447         }
 448 
 449         return;
 450 failed:
 451         task_server_terminate(task, "Failed to startup dcerpc server task");    
 452 }
 453 
 454 NTSTATUS server_service_rpc_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 455 {
 456 
 457         return register_server_service("rpc", dcesrv_task_init);
 458 }

/* [<][>][^][v][top][bottom][index][help] */