Line data Source code
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 "samba/service_task.h"
23 : #include "samba/service_stream.h"
24 : #include "samba/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 2559 : static NTSTATUS smbsrv_recv_generic_request(void *private_data, DATA_BLOB blob)
38 : {
39 0 : NTSTATUS status;
40 2559 : struct smbsrv_connection *smb_conn = talloc_get_type(private_data, struct smbsrv_connection);
41 0 : uint32_t protocol_version;
42 :
43 : /* see if its a special NBT packet */
44 2559 : if (CVAL(blob.data,0) != 0) {
45 6 : status = smbsrv_init_smb_connection(smb_conn, smb_conn->lp_ctx);
46 6 : NT_STATUS_NOT_OK_RETURN(status);
47 6 : return smbsrv_recv_smb_request(smb_conn, blob);
48 : }
49 :
50 2553 : if (blob.length < (NBT_HDR_SIZE + MIN_SMB_SIZE)) {
51 0 : DEBUG(2,("Invalid SMB packet length count %ld\n", (long)blob.length));
52 0 : smbsrv_terminate_connection(smb_conn, "Invalid SMB packet");
53 0 : return NT_STATUS_OK;
54 : }
55 :
56 2553 : protocol_version = IVAL(blob.data, NBT_HDR_SIZE);
57 :
58 2553 : switch (protocol_version) {
59 2159 : case SMB_MAGIC:
60 2159 : status = smbsrv_init_smb_connection(smb_conn, smb_conn->lp_ctx);
61 2159 : NT_STATUS_NOT_OK_RETURN(status);
62 2159 : packet_set_callback(smb_conn->packet, smbsrv_recv_smb_request);
63 2159 : return smbsrv_recv_smb_request(smb_conn, blob);
64 394 : case SMB2_MAGIC:
65 394 : if (lpcfg_server_max_protocol(smb_conn->lp_ctx) < PROTOCOL_SMB2_02) break;
66 394 : status = smbsrv_init_smb2_connection(smb_conn);
67 394 : NT_STATUS_NOT_OK_RETURN(status);
68 394 : packet_set_callback(smb_conn->packet, smbsrv_recv_smb2_request);
69 394 : return smbsrv_recv_smb2_request(smb_conn, blob);
70 : }
71 :
72 0 : DEBUG(2,("Invalid SMB packet: protocol prefix: 0x%08X\n", protocol_version));
73 0 : smbsrv_terminate_connection(smb_conn, "NON-SMB packet");
74 0 : return NT_STATUS_OK;
75 : }
76 :
77 : /*
78 : close the socket and shutdown a server_context
79 : */
80 2574 : void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char *reason)
81 : {
82 2574 : stream_terminate_connection(smb_conn->connection, reason);
83 2574 : }
84 :
85 : /*
86 : called when a SMB socket becomes readable
87 : */
88 1715959 : static void smbsrv_recv(struct stream_connection *conn, uint16_t flags)
89 : {
90 1715959 : struct smbsrv_connection *smb_conn = talloc_get_type(conn->private_data,
91 : struct smbsrv_connection);
92 :
93 1715959 : DEBUG(10,("smbsrv_recv\n"));
94 :
95 1715959 : packet_recv(smb_conn->packet);
96 1715959 : }
97 :
98 : /*
99 : called when a SMB socket becomes writable
100 : */
101 886656 : static void smbsrv_send(struct stream_connection *conn, uint16_t flags)
102 : {
103 886656 : struct smbsrv_connection *smb_conn = talloc_get_type(conn->private_data,
104 : struct smbsrv_connection);
105 886656 : packet_queue_run(smb_conn->packet);
106 886656 : }
107 :
108 : /*
109 : handle socket recv errors
110 : */
111 2569 : static void smbsrv_recv_error(void *private_data, NTSTATUS status)
112 : {
113 2569 : struct smbsrv_connection *smb_conn = talloc_get_type(private_data, struct smbsrv_connection);
114 :
115 2569 : smbsrv_terminate_connection(smb_conn, nt_errstr(status));
116 2569 : }
117 :
118 : /*
119 : initialise a server_context from a open socket and register a event handler
120 : for reading from that socket
121 : */
122 2579 : static void smbsrv_accept(struct stream_connection *conn)
123 : {
124 0 : struct smbsrv_connection *smb_conn;
125 :
126 2579 : DEBUG(5,("smbsrv_accept\n"));
127 :
128 2579 : smb_conn = talloc_zero(conn, struct smbsrv_connection);
129 2579 : if (!smb_conn) {
130 0 : stream_terminate_connection(conn, "out of memory");
131 0 : return;
132 : }
133 :
134 2579 : smb_conn->packet = packet_init(smb_conn);
135 2579 : if (!smb_conn->packet) {
136 0 : smbsrv_terminate_connection(smb_conn, "out of memory");
137 0 : return;
138 : }
139 2579 : packet_set_private(smb_conn->packet, smb_conn);
140 2579 : packet_set_socket(smb_conn->packet, conn->socket);
141 2579 : packet_set_callback(smb_conn->packet, smbsrv_recv_generic_request);
142 2579 : packet_set_full_request(smb_conn->packet, packet_full_request_nbt);
143 2579 : packet_set_error_handler(smb_conn->packet, smbsrv_recv_error);
144 2579 : packet_set_event_context(smb_conn->packet, conn->event.ctx);
145 2579 : packet_set_fde(smb_conn->packet, conn->event.fde);
146 2579 : packet_set_serialise(smb_conn->packet);
147 2579 : packet_set_initial_read(smb_conn->packet, 4);
148 :
149 2579 : smb_conn->lp_ctx = conn->lp_ctx;
150 2579 : smb_conn->connection = conn;
151 2579 : conn->private_data = smb_conn;
152 :
153 2579 : smb_conn->statistics.connect_time = timeval_current();
154 :
155 2579 : smbsrv_management_init(smb_conn);
156 :
157 2579 : irpc_add_name(conn->msg_ctx, "smb_server");
158 :
159 2579 : if (!NT_STATUS_IS_OK(share_get_context(smb_conn,
160 : smb_conn->lp_ctx,
161 : &(smb_conn->share_context)))) {
162 0 : smbsrv_terminate_connection(smb_conn, "share_init failed!");
163 0 : 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 32 : _PUBLIC_ NTSTATUS smbsrv_add_socket(TALLOC_CTX *mem_ctx,
178 : struct tevent_context *event_context,
179 : struct loadparm_context *lp_ctx,
180 : const struct model_ops *model_ops,
181 : const char *address,
182 : void *process_context)
183 : {
184 32 : const char **ports = lpcfg_smb_ports(lp_ctx);
185 0 : int i;
186 0 : NTSTATUS status;
187 :
188 96 : for (i=0;ports[i];i++) {
189 64 : uint16_t port = atoi(ports[i]);
190 64 : if (port == 0) continue;
191 64 : status = stream_setup_socket(mem_ctx, event_context, lp_ctx,
192 : model_ops, &smb_stream_ops,
193 : "ip", address, &port,
194 : lpcfg_socket_options(lp_ctx),
195 : NULL, process_context);
196 64 : NT_STATUS_NOT_OK_RETURN(status);
197 : }
198 :
199 32 : return NT_STATUS_OK;
200 : }
201 :
202 :
203 :
|