root/source4/smb_server/smb_server.c

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

DEFINITIONS

This source file includes following definitions.
  1. smbsrv_recv_generic_request
  2. smbsrv_terminate_connection
  3. smbsrv_recv
  4. smbsrv_send
  5. smbsrv_recv_error
  6. smbsrv_accept
  7. smbsrv_add_socket
  8. smbsrv_preopen_ldb
  9. smbsrv_task_init
  10. server_service_smb_init

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    process incoming packets - main loop
   4    Copyright (C) Andrew Tridgell        2004-2005
   5    Copyright (C) Stefan Metzmacher      2004-2005
   6    
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 #include "smbd/service_task.h"
  23 #include "smbd/service_stream.h"
  24 #include "smbd/service.h"
  25 #include "smb_server/smb_server.h"
  26 #include "smb_server/service_smb_proto.h"
  27 #include "lib/messaging/irpc.h"
  28 #include "lib/stream/packet.h"
  29 #include "libcli/smb2/smb2.h"
  30 #include "smb_server/smb2/smb2_server.h"
  31 #include "system/network.h"
  32 #include "lib/socket/netif.h"
  33 #include "param/share.h"
  34 #include "dsdb/samdb/samdb.h"
  35 #include "param/param.h"
  36 
  37 static NTSTATUS smbsrv_recv_generic_request(void *private_data, DATA_BLOB blob)
     /* [<][>][^][v][top][bottom][index][help] */
  38 {
  39         NTSTATUS status;
  40         struct smbsrv_connection *smb_conn = talloc_get_type(private_data, struct smbsrv_connection);
  41         uint32_t protocol_version;
  42 
  43         /* see if its a special NBT packet */
  44         if (CVAL(blob.data,0) != 0) {
  45                 status = smbsrv_init_smb_connection(smb_conn, smb_conn->lp_ctx);
  46                 NT_STATUS_NOT_OK_RETURN(status);
  47                 packet_set_callback(smb_conn->packet, smbsrv_recv_smb_request);
  48                 return smbsrv_recv_smb_request(smb_conn, blob);
  49         }
  50 
  51         if (blob.length < (NBT_HDR_SIZE + MIN_SMB_SIZE)) {
  52                 DEBUG(2,("Invalid SMB packet length count %ld\n", (long)blob.length));
  53                 smbsrv_terminate_connection(smb_conn, "Invalid SMB packet");
  54                 return NT_STATUS_OK;
  55         }
  56 
  57         protocol_version = IVAL(blob.data, NBT_HDR_SIZE);
  58 
  59         switch (protocol_version) {
  60         case SMB_MAGIC:
  61                 status = smbsrv_init_smb_connection(smb_conn, smb_conn->lp_ctx);
  62                 NT_STATUS_NOT_OK_RETURN(status);
  63                 packet_set_callback(smb_conn->packet, smbsrv_recv_smb_request);
  64                 return smbsrv_recv_smb_request(smb_conn, blob);
  65         case SMB2_MAGIC:
  66                 if (lp_srv_maxprotocol(smb_conn->lp_ctx) < PROTOCOL_SMB2) break;
  67                 status = smbsrv_init_smb2_connection(smb_conn);
  68                 NT_STATUS_NOT_OK_RETURN(status);
  69                 packet_set_callback(smb_conn->packet, smbsrv_recv_smb2_request);
  70                 return smbsrv_recv_smb2_request(smb_conn, blob);
  71         }
  72 
  73         DEBUG(2,("Invalid SMB packet: protocol prefix: 0x%08X\n", protocol_version));
  74         smbsrv_terminate_connection(smb_conn, "NON-SMB packet");
  75         return NT_STATUS_OK;
  76 }
  77 
  78 /*
  79   close the socket and shutdown a server_context
  80 */
  81 void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char *reason)
     /* [<][>][^][v][top][bottom][index][help] */
  82 {
  83         stream_terminate_connection(smb_conn->connection, reason);
  84 }
  85 
  86 /*
  87   called when a SMB socket becomes readable
  88 */
  89 static void smbsrv_recv(struct stream_connection *conn, uint16_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
  90 {
  91         struct smbsrv_connection *smb_conn = talloc_get_type(conn->private_data,
  92                                                              struct smbsrv_connection);
  93 
  94         DEBUG(10,("smbsrv_recv\n"));
  95 
  96         packet_recv(smb_conn->packet);
  97 }
  98 
  99 /*
 100   called when a SMB socket becomes writable
 101 */
 102 static void smbsrv_send(struct stream_connection *conn, uint16_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104         struct smbsrv_connection *smb_conn = talloc_get_type(conn->private_data,
 105                                                              struct smbsrv_connection);
 106         packet_queue_run(smb_conn->packet);
 107 }
 108 
 109 /*
 110   handle socket recv errors
 111 */
 112 static void smbsrv_recv_error(void *private_data, NTSTATUS status)
     /* [<][>][^][v][top][bottom][index][help] */
 113 {
 114         struct smbsrv_connection *smb_conn = talloc_get_type(private_data, struct smbsrv_connection);
 115         
 116         smbsrv_terminate_connection(smb_conn, nt_errstr(status));
 117 }
 118 
 119 /*
 120   initialise a server_context from a open socket and register a event handler
 121   for reading from that socket
 122 */
 123 static void smbsrv_accept(struct stream_connection *conn)
     /* [<][>][^][v][top][bottom][index][help] */
 124 {
 125         struct smbsrv_connection *smb_conn;
 126 
 127         DEBUG(5,("smbsrv_accept\n"));
 128 
 129         smb_conn = talloc_zero(conn, struct smbsrv_connection);
 130         if (!smb_conn) {
 131                 stream_terminate_connection(conn, "out of memory");
 132                 return;
 133         }
 134 
 135         smb_conn->packet = packet_init(smb_conn);
 136         if (!smb_conn->packet) {
 137                 smbsrv_terminate_connection(smb_conn, "out of memory");
 138                 return;
 139         }
 140         packet_set_private(smb_conn->packet, smb_conn);
 141         packet_set_socket(smb_conn->packet, conn->socket);
 142         packet_set_callback(smb_conn->packet, smbsrv_recv_generic_request);
 143         packet_set_full_request(smb_conn->packet, packet_full_request_nbt);
 144         packet_set_error_handler(smb_conn->packet, smbsrv_recv_error);
 145         packet_set_event_context(smb_conn->packet, conn->event.ctx);
 146         packet_set_fde(smb_conn->packet, conn->event.fde);
 147         packet_set_serialise(smb_conn->packet);
 148 
 149         smb_conn->lp_ctx = conn->lp_ctx;
 150         smb_conn->connection = conn;
 151         conn->private_data = smb_conn;
 152 
 153         smb_conn->statistics.connect_time = timeval_current();
 154 
 155         smbsrv_management_init(smb_conn);
 156 
 157         irpc_add_name(conn->msg_ctx, "smb_server");
 158 
 159         if (!NT_STATUS_IS_OK(share_get_context_by_name(smb_conn, lp_share_backend(smb_conn->lp_ctx), 
 160                                                        smb_conn->connection->event.ctx,
 161                                                        smb_conn->lp_ctx, &(smb_conn->share_context)))) {
 162                 smbsrv_terminate_connection(smb_conn, "share_init failed!");
 163                 return;
 164         }
 165 }
 166 
 167 static const struct stream_server_ops smb_stream_ops = {
 168         .name                   = "smbsrv",
 169         .accept_connection      = smbsrv_accept,
 170         .recv_handler           = smbsrv_recv,
 171         .send_handler           = smbsrv_send,
 172 };
 173 
 174 /*
 175   setup a listening socket on all the SMB ports for a particular address
 176 */
 177 _PUBLIC_ NTSTATUS smbsrv_add_socket(struct tevent_context *event_context,
     /* [<][>][^][v][top][bottom][index][help] */
 178                                     struct loadparm_context *lp_ctx,
 179                                const struct model_ops *model_ops,
 180                                const char *address)
 181 {
 182         const char **ports = lp_smb_ports(lp_ctx);
 183         int i;
 184         NTSTATUS status;
 185 
 186         for (i=0;ports[i];i++) {
 187                 uint16_t port = atoi(ports[i]);
 188                 if (port == 0) continue;
 189                 status = stream_setup_socket(event_context, lp_ctx, 
 190                                              model_ops, &smb_stream_ops, 
 191                                              "ipv4", address, &port, 
 192                                              lp_socket_options(lp_ctx), 
 193                                              NULL);
 194                 NT_STATUS_NOT_OK_RETURN(status);
 195         }
 196 
 197         return NT_STATUS_OK;
 198 }
 199 
 200 
 201 /*
 202   pre-open some of our ldb databases, to prevent an explosion of memory usage
 203   when we fork
 204  */
 205 static void smbsrv_preopen_ldb(struct task_server *task)
     /* [<][>][^][v][top][bottom][index][help] */
 206 {
 207         /* yes, this looks strange. It is a hack to preload the
 208            schema. I'd like to share most of the ldb context with the
 209            child too. That will come later */
 210         talloc_free(samdb_connect(task, task->event_ctx, task->lp_ctx, NULL));
 211 }
 212 
 213 /*
 214   open the smb server sockets
 215 */
 216 static void smbsrv_task_init(struct task_server *task)
     /* [<][>][^][v][top][bottom][index][help] */
 217 {       
 218         NTSTATUS status;
 219 
 220         task_server_set_title(task, "task[smbsrv]");
 221 
 222         if (lp_interfaces(task->lp_ctx) && lp_bind_interfaces_only(task->lp_ctx)) {
 223                 int num_interfaces;
 224                 int i;
 225                 struct interface *ifaces;
 226 
 227                 load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces);
 228 
 229                 num_interfaces = iface_count(ifaces);
 230 
 231                 /* We have been given an interfaces line, and been 
 232                    told to only bind to those interfaces. Create a
 233                    socket per interface and bind to only these.
 234                 */
 235                 for(i = 0; i < num_interfaces; i++) {
 236                         const char *address = iface_n_ip(ifaces, i);
 237                         status = smbsrv_add_socket(task->event_ctx, task->lp_ctx, task->model_ops, address);
 238                         if (!NT_STATUS_IS_OK(status)) goto failed;
 239                 }
 240         } else {
 241                 /* Just bind to lp_socket_address() (usually 0.0.0.0) */
 242                 status = smbsrv_add_socket(task->event_ctx, task->lp_ctx, task->model_ops, 
 243                                            lp_socket_address(task->lp_ctx));
 244                 if (!NT_STATUS_IS_OK(status)) goto failed;
 245         }
 246 
 247         smbsrv_preopen_ldb(task);
 248 
 249         return;
 250 failed:
 251         task_server_terminate(task, "Failed to startup smb server task");       
 252 }
 253 
 254 /* called at smbd startup - register ourselves as a server service */
 255 NTSTATUS server_service_smb_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 256 {
 257         share_init();
 258         return register_server_service("smb", smbsrv_task_init);
 259 }

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