Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : NBT datagram netlogon server
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "nbt_server/nbt_server.h"
25 : #include "lib/socket/socket.h"
26 : #include <ldb.h>
27 : #include "dsdb/samdb/samdb.h"
28 : #include "auth/auth.h"
29 : #include "param/param.h"
30 : #include "samba/service_task.h"
31 : #include "dsdb/samdb/ldb_modules/util.h"
32 : #include "libcli/security/security.h"
33 : #include "nbt_server/dgram/proto.h"
34 : #include "libds/common/roles.h"
35 :
36 : /*
37 : reply to a GETDC request
38 : */
39 9 : static NTSTATUS nbtd_netlogon_getdc(struct nbtd_server *nbtsrv,
40 : struct nbt_name *dst_name,
41 : struct nbt_netlogon_packet *netlogon,
42 : TALLOC_CTX *mem_ctx,
43 : struct nbt_netlogon_response **presponse,
44 : char **preply_mailslot)
45 : {
46 0 : struct nbt_netlogon_response_from_pdc *pdc;
47 0 : struct ldb_context *samctx;
48 9 : struct nbt_netlogon_response *response = NULL;
49 9 : char *reply_mailslot = NULL;
50 :
51 : /* only answer getdc requests on the PDC or LOGON names */
52 9 : if ((dst_name->type != NBT_NAME_PDC) &&
53 9 : (dst_name->type != NBT_NAME_LOGON)) {
54 0 : return NT_STATUS_NOT_SUPPORTED;
55 : }
56 :
57 9 : samctx = nbtsrv->sam_ctx;
58 :
59 9 : if (lpcfg_server_role(nbtsrv->task->lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC
60 9 : || !samdb_is_pdc(samctx)) {
61 0 : DEBUG(2, ("Not a PDC, so not processing LOGON_PRIMARY_QUERY\n"));
62 0 : return NT_STATUS_NOT_SUPPORTED;
63 : }
64 :
65 9 : if (strcasecmp_m(dst_name->name,
66 9 : lpcfg_workgroup(nbtsrv->task->lp_ctx)) != 0) {
67 0 : DBG_INFO("GetDC requested for a domain %s that we don't "
68 : "host\n", dst_name->name);
69 0 : return NT_STATUS_NOT_SUPPORTED;
70 : }
71 :
72 9 : reply_mailslot = talloc_strdup(
73 : mem_ctx, netlogon->req.pdc.mailslot_name);
74 9 : if (reply_mailslot == NULL) {
75 0 : goto nomem;
76 : }
77 :
78 : /* setup a GETDC reply */
79 9 : response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
80 9 : if (response == NULL) {
81 0 : goto nomem;
82 : }
83 9 : response->response_type = NETLOGON_GET_PDC;
84 9 : pdc = &response->data.get_pdc;
85 :
86 9 : pdc->command = NETLOGON_RESPONSE_FROM_PDC;
87 :
88 9 : pdc->pdc_name = talloc_strdup(
89 9 : response, lpcfg_netbios_name(nbtsrv->task->lp_ctx));
90 9 : if (pdc->pdc_name == NULL) {
91 0 : goto nomem;
92 : }
93 :
94 9 : pdc->unicode_pdc_name = pdc->pdc_name;
95 :
96 9 : pdc->domain_name = talloc_strdup(
97 9 : response, lpcfg_workgroup(nbtsrv->task->lp_ctx));
98 9 : if (pdc->domain_name == NULL) {
99 0 : goto nomem;
100 : }
101 :
102 9 : pdc->nt_version = 1;
103 9 : pdc->lmnt_token = 0xFFFF;
104 9 : pdc->lm20_token = 0xFFFF;
105 :
106 9 : *presponse = response;
107 9 : *preply_mailslot = reply_mailslot;
108 9 : return NT_STATUS_OK;
109 :
110 0 : nomem:
111 0 : TALLOC_FREE(response);
112 0 : TALLOC_FREE(reply_mailslot);
113 0 : return NT_STATUS_NO_MEMORY;
114 : }
115 :
116 : /*
117 : reply to a ADS style GETDC request
118 : */
119 36 : static NTSTATUS nbtd_netlogon_samlogon(
120 : struct nbtd_server *nbtsrv,
121 : struct nbt_name *dst_name,
122 : const struct socket_address *src,
123 : struct nbt_netlogon_packet *netlogon,
124 : TALLOC_CTX *mem_ctx,
125 : struct nbt_netlogon_response **presponse,
126 : char **preply_mailslot)
127 : {
128 0 : struct ldb_context *samctx;
129 36 : struct dom_sid *sid = NULL;
130 36 : struct nbt_netlogon_response *response = NULL;
131 36 : char *reply_mailslot = NULL;
132 0 : NTSTATUS status;
133 :
134 : /* only answer getdc requests on the PDC or LOGON names */
135 36 : if ((dst_name->type != NBT_NAME_PDC) &&
136 36 : (dst_name->type != NBT_NAME_LOGON)) {
137 0 : return NT_STATUS_NOT_SUPPORTED;
138 : }
139 :
140 36 : samctx = nbtsrv->sam_ctx;
141 :
142 36 : if (netlogon->req.logon.sid_size != 0) {
143 16 : sid = &netlogon->req.logon.sid;
144 : }
145 :
146 36 : reply_mailslot = talloc_strdup(
147 : mem_ctx, netlogon->req.logon.mailslot_name);
148 36 : if (reply_mailslot == NULL) {
149 0 : return NT_STATUS_NO_MEMORY;
150 : }
151 :
152 36 : response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
153 36 : if (response == NULL) {
154 0 : TALLOC_FREE(reply_mailslot);
155 0 : return NT_STATUS_NO_MEMORY;
156 : }
157 36 : response->response_type = NETLOGON_SAMLOGON;
158 :
159 36 : status = fill_netlogon_samlogon_response(
160 : samctx, response, NULL, dst_name->name, sid, NULL,
161 : netlogon->req.logon.user_name,
162 36 : netlogon->req.logon.acct_control, src->addr,
163 36 : netlogon->req.logon.nt_version, nbtsrv->task->lp_ctx,
164 : &response->data.samlogon, false);
165 36 : if (!NT_STATUS_IS_OK(status)) {
166 0 : struct dom_sid_buf buf;
167 :
168 0 : DBG_NOTICE("NBT netlogon query failed domain=%s sid=%s "
169 : "version=%d - %s\n",
170 : dst_name->name,
171 : dom_sid_str_buf(sid, &buf),
172 : netlogon->req.logon.nt_version,
173 : nt_errstr(status));
174 0 : TALLOC_FREE(reply_mailslot);
175 0 : TALLOC_FREE(response);
176 0 : return status;
177 : }
178 :
179 36 : *presponse = response;
180 36 : *preply_mailslot = reply_mailslot;
181 36 : return NT_STATUS_OK;
182 : }
183 :
184 45 : static NTSTATUS nbtd_mailslot_netlogon_reply(
185 : struct nbtd_interface *iface,
186 : struct nbt_dgram_packet *packet,
187 : struct socket_address *src,
188 : TALLOC_CTX *mem_ctx,
189 : struct nbt_netlogon_response **presponse,
190 : char **preply_mailslot)
191 : {
192 0 : struct nbt_netlogon_packet *netlogon;
193 45 : struct nbt_name *dst_name = &packet->data.msg.dest_name;
194 45 : struct nbt_netlogon_response *response = NULL;
195 0 : struct nbtd_iface_name *iname;
196 45 : char *reply_mailslot = NULL;
197 0 : NTSTATUS status;
198 :
199 : /*
200 : see if the we are listening on the destination netbios name
201 : */
202 45 : iname = nbtd_find_iname(iface, dst_name, 0);
203 45 : if (iname == NULL) {
204 0 : return NT_STATUS_BAD_NETWORK_NAME;
205 : }
206 :
207 45 : netlogon = talloc(mem_ctx, struct nbt_netlogon_packet);
208 45 : if (netlogon == NULL) {
209 0 : return NT_STATUS_NO_MEMORY;
210 : }
211 :
212 45 : status = dgram_mailslot_netlogon_parse_request(netlogon, packet,
213 : netlogon);
214 45 : if (!NT_STATUS_IS_OK(status)) {
215 0 : goto failed;
216 : }
217 :
218 45 : switch (netlogon->command) {
219 9 : case LOGON_PRIMARY_QUERY:
220 9 : status = nbtd_netlogon_getdc(
221 : iface->nbtsrv, &packet->data.msg.dest_name,
222 : netlogon, mem_ctx, &response, &reply_mailslot);
223 9 : break;
224 36 : case LOGON_SAM_LOGON_REQUEST:
225 36 : status = nbtd_netlogon_samlogon(
226 : iface->nbtsrv, &packet->data.msg.dest_name, src,
227 : netlogon, mem_ctx, &response, &reply_mailslot);
228 36 : break;
229 0 : default:
230 0 : DEBUG(2,("unknown netlogon op %d from %s:%d\n",
231 : netlogon->command, src->addr, src->port));
232 0 : NDR_PRINT_DEBUG(nbt_netlogon_packet, netlogon);
233 0 : status = NT_STATUS_NOT_SUPPORTED;
234 0 : break;
235 : }
236 :
237 45 : if (!NT_STATUS_IS_OK(status)) {
238 0 : DBG_DEBUG("Calculating reply failed: %s\n",
239 : nt_errstr(status));
240 0 : goto failed;
241 : }
242 :
243 45 : *presponse = response;
244 45 : *preply_mailslot = reply_mailslot;
245 45 : return NT_STATUS_OK;
246 :
247 0 : failed:
248 0 : TALLOC_FREE(reply_mailslot);
249 0 : TALLOC_FREE(netlogon);
250 0 : return status;
251 : }
252 :
253 : /*
254 : handle incoming netlogon mailslot requests
255 : */
256 45 : void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot,
257 : struct nbt_dgram_packet *packet,
258 : struct socket_address *src)
259 : {
260 45 : NTSTATUS status = NT_STATUS_NO_MEMORY;
261 0 : struct nbtd_interface *iface =
262 45 : talloc_get_type(dgmslot->private_data, struct nbtd_interface);
263 45 : struct nbtd_interface *reply_iface = nbtd_find_reply_iface(
264 45 : iface, src->addr, false);
265 45 : struct nbt_netlogon_response *response = NULL;
266 45 : char *reply_mailslot = NULL;
267 :
268 45 : if (reply_iface->ip_address == NULL) {
269 0 : DBG_WARNING("Could not obtain own IP address for datagram "
270 : "socket\n");
271 0 : return;
272 : }
273 :
274 45 : status = nbtd_mailslot_netlogon_reply(
275 : iface, packet, src, dgmslot, &response, &reply_mailslot);
276 :
277 45 : if (NT_STATUS_IS_OK(status)) {
278 45 : dgram_mailslot_netlogon_reply(
279 : reply_iface->dgmsock, packet,
280 45 : lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx),
281 : reply_mailslot, response);
282 : }
283 :
284 45 : TALLOC_FREE(response);
285 45 : TALLOC_FREE(reply_mailslot);
286 : }
|