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 37static NTSTATUS smbsrv_recv_generic_request(void *private_data, DATA_BLOB blob) 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*/ 81void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char *reason) 82{ 83 stream_terminate_connection(smb_conn->connection, reason); 84} 85 86/* 87 called when a SMB socket becomes readable 88*/ 89static void smbsrv_recv(struct stream_connection *conn, uint16_t flags) 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*/ 102static void smbsrv_send(struct stream_connection *conn, uint16_t flags) 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*/ 112static void smbsrv_recv_error(void *private_data, NTSTATUS status) 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*/ 123static void smbsrv_accept(struct stream_connection *conn) 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 packet_set_initial_read(smb_conn->packet, 4); 149 150 smb_conn->lp_ctx = conn->lp_ctx; 151 smb_conn->connection = conn; 152 conn->private_data = smb_conn; 153 154 smb_conn->statistics.connect_time = timeval_current(); 155 156 smbsrv_management_init(smb_conn); 157 158 irpc_add_name(conn->msg_ctx, "smb_server"); 159 160 if (!NT_STATUS_IS_OK(share_get_context_by_name(smb_conn, lp_share_backend(smb_conn->lp_ctx), 161 smb_conn->connection->event.ctx, 162 smb_conn->lp_ctx, &(smb_conn->share_context)))) { 163 smbsrv_terminate_connection(smb_conn, "share_init failed!"); 164 return; 165 } 166} 167 168static const struct stream_server_ops smb_stream_ops = { 169 .name = "smbsrv", 170 .accept_connection = smbsrv_accept, 171 .recv_handler = smbsrv_recv, 172 .send_handler = smbsrv_send, 173}; 174 175/* 176 setup a listening socket on all the SMB ports for a particular address 177*/ 178_PUBLIC_ NTSTATUS smbsrv_add_socket(struct tevent_context *event_context, 179 struct loadparm_context *lp_ctx, 180 const struct model_ops *model_ops, 181 const char *address) 182{ 183 const char **ports = lp_smb_ports(lp_ctx); 184 int i; 185 NTSTATUS status; 186 187 for (i=0;ports[i];i++) { 188 uint16_t port = atoi(ports[i]); 189 if (port == 0) continue; 190 status = stream_setup_socket(event_context, lp_ctx, 191 model_ops, &smb_stream_ops, 192 "ipv4", address, &port, 193 lp_socket_options(lp_ctx), 194 NULL); 195 NT_STATUS_NOT_OK_RETURN(status); 196 } 197 198 return NT_STATUS_OK; 199} 200 201 202/* 203 pre-open some of our ldb databases, to prevent an explosion of memory usage 204 when we fork 205 */ 206static void smbsrv_preopen_ldb(struct task_server *task) 207{ 208 /* yes, this looks strange. It is a hack to preload the 209 schema. I'd like to share most of the ldb context with the 210 child too. That will come later */ 211 talloc_free(samdb_connect(task, task->event_ctx, task->lp_ctx, NULL)); 212} 213 214/* 215 open the smb server sockets 216*/ 217static void smbsrv_task_init(struct task_server *task) 218{ 219 NTSTATUS status; 220 221 task_server_set_title(task, "task[smbsrv]"); 222 223 if (lp_interfaces(task->lp_ctx) && lp_bind_interfaces_only(task->lp_ctx)) { 224 int num_interfaces; 225 int i; 226 struct interface *ifaces; 227 228 load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces); 229 230 num_interfaces = iface_count(ifaces); 231 232 /* We have been given an interfaces line, and been 233 told to only bind to those interfaces. Create a 234 socket per interface and bind to only these. 235 */ 236 for(i = 0; i < num_interfaces; i++) { 237 const char *address = iface_n_ip(ifaces, i); 238 status = smbsrv_add_socket(task->event_ctx, task->lp_ctx, task->model_ops, address); 239 if (!NT_STATUS_IS_OK(status)) goto failed; 240 } 241 } else { 242 /* Just bind to lp_socket_address() (usually 0.0.0.0) */ 243 status = smbsrv_add_socket(task->event_ctx, task->lp_ctx, task->model_ops, 244 lp_socket_address(task->lp_ctx)); 245 if (!NT_STATUS_IS_OK(status)) goto failed; 246 } 247 248 smbsrv_preopen_ldb(task); 249 250 return; 251failed: 252 task_server_terminate(task, "Failed to startup smb server task", true); 253} 254 255/* called at smbd startup - register ourselves as a server service */ 256NTSTATUS server_service_smb_init(void) 257{ 258 share_init(); 259 return register_server_service("smb", smbsrv_task_init); 260} 261