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 3 : 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 : struct nbt_netlogon_response_from_pdc *pdc;
47 : struct ldb_context *samctx;
48 3 : struct nbt_netlogon_response *response = NULL;
49 3 : char *reply_mailslot = NULL;
50 :
51 : /* only answer getdc requests on the PDC or LOGON names */
52 6 : if ((dst_name->type != NBT_NAME_PDC) &&
53 3 : (dst_name->type != NBT_NAME_LOGON)) {
54 0 : return NT_STATUS_NOT_SUPPORTED;
55 : }
56 :
57 3 : samctx = nbtsrv->sam_ctx;
58 :
59 3 : if (lpcfg_server_role(nbtsrv->task->lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC
60 3 : || !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 3 : if (strcasecmp_m(dst_name->name,
66 3 : 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 3 : reply_mailslot = talloc_strdup(
73 : mem_ctx, netlogon->req.pdc.mailslot_name);
74 3 : if (reply_mailslot == NULL) {
75 0 : goto nomem;
76 : }
77 :
78 : /* setup a GETDC reply */
79 3 : response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
80 3 : if (response == NULL) {
81 0 : goto nomem;
82 : }
83 3 : response->response_type = NETLOGON_GET_PDC;
84 3 : pdc = &response->data.get_pdc;
85 :
86 3 : pdc->command = NETLOGON_RESPONSE_FROM_PDC;
87 :
88 3 : pdc->pdc_name = talloc_strdup(
89 3 : response, lpcfg_netbios_name(nbtsrv->task->lp_ctx));
90 3 : if (pdc->pdc_name == NULL) {
91 0 : goto nomem;
92 : }
93 :
94 3 : pdc->unicode_pdc_name = pdc->pdc_name;
95 :
96 3 : pdc->domain_name = talloc_strdup(
97 3 : response, lpcfg_workgroup(nbtsrv->task->lp_ctx));
98 3 : if (pdc->domain_name == NULL) {
99 0 : goto nomem;
100 : }
101 :
102 3 : pdc->nt_version = 1;
103 3 : pdc->lmnt_token = 0xFFFF;
104 3 : pdc->lm20_token = 0xFFFF;
105 :
106 3 : *presponse = response;
107 3 : *preply_mailslot = reply_mailslot;
108 3 : 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 7 : 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 : struct ldb_context *samctx;
129 7 : struct dom_sid *sid = NULL;
130 7 : struct nbt_netlogon_response *response = NULL;
131 7 : char *reply_mailslot = NULL;
132 : NTSTATUS status;
133 :
134 : /* only answer getdc requests on the PDC or LOGON names */
135 14 : if ((dst_name->type != NBT_NAME_PDC) &&
136 7 : (dst_name->type != NBT_NAME_LOGON)) {
137 0 : return NT_STATUS_NOT_SUPPORTED;
138 : }
139 :
140 7 : samctx = nbtsrv->sam_ctx;
141 :
142 7 : if (netlogon->req.logon.sid_size != 0) {
143 4 : sid = &netlogon->req.logon.sid;
144 : }
145 :
146 7 : reply_mailslot = talloc_strdup(
147 : mem_ctx, netlogon->req.logon.mailslot_name);
148 7 : if (reply_mailslot == NULL) {
149 0 : return NT_STATUS_NO_MEMORY;
150 : }
151 :
152 7 : response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
153 7 : if (response == NULL) {
154 0 : TALLOC_FREE(reply_mailslot);
155 0 : return NT_STATUS_NO_MEMORY;
156 : }
157 7 : response->response_type = NETLOGON_SAMLOGON;
158 :
159 21 : status = fill_netlogon_samlogon_response(
160 : samctx, response, NULL, dst_name->name, sid, NULL,
161 : netlogon->req.logon.user_name,
162 7 : netlogon->req.logon.acct_control, src->addr,
163 7 : netlogon->req.logon.nt_version, nbtsrv->task->lp_ctx,
164 : &response->data.samlogon, false);
165 7 : if (!NT_STATUS_IS_OK(status)) {
166 : 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 7 : *presponse = response;
180 7 : *preply_mailslot = reply_mailslot;
181 7 : return NT_STATUS_OK;
182 : }
183 :
184 10 : 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 : struct nbt_netlogon_packet *netlogon;
193 10 : struct nbt_name *dst_name = &packet->data.msg.dest_name;
194 10 : struct nbt_netlogon_response *response = NULL;
195 : struct nbtd_iface_name *iname;
196 10 : char *reply_mailslot = NULL;
197 : NTSTATUS status;
198 :
199 : /*
200 : see if the we are listening on the destination netbios name
201 : */
202 10 : iname = nbtd_find_iname(iface, dst_name, 0);
203 10 : if (iname == NULL) {
204 0 : return NT_STATUS_BAD_NETWORK_NAME;
205 : }
206 :
207 10 : netlogon = talloc(mem_ctx, struct nbt_netlogon_packet);
208 10 : if (netlogon == NULL) {
209 0 : return NT_STATUS_NO_MEMORY;
210 : }
211 :
212 10 : status = dgram_mailslot_netlogon_parse_request(netlogon, packet,
213 : netlogon);
214 10 : if (!NT_STATUS_IS_OK(status)) {
215 0 : goto failed;
216 : }
217 :
218 10 : switch (netlogon->command) {
219 3 : case LOGON_PRIMARY_QUERY:
220 3 : status = nbtd_netlogon_getdc(
221 : iface->nbtsrv, &packet->data.msg.dest_name,
222 : netlogon, mem_ctx, &response, &reply_mailslot);
223 3 : break;
224 7 : case LOGON_SAM_LOGON_REQUEST:
225 7 : status = nbtd_netlogon_samlogon(
226 : iface->nbtsrv, &packet->data.msg.dest_name, src,
227 : netlogon, mem_ctx, &response, &reply_mailslot);
228 7 : 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 10 : 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 10 : *presponse = response;
244 10 : *preply_mailslot = reply_mailslot;
245 10 : 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 10 : void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot,
257 : struct nbt_dgram_packet *packet,
258 : struct socket_address *src)
259 : {
260 10 : NTSTATUS status = NT_STATUS_NO_MEMORY;
261 10 : struct nbtd_interface *iface =
262 10 : talloc_get_type(dgmslot->private_data, struct nbtd_interface);
263 10 : struct nbtd_interface *reply_iface = nbtd_find_reply_iface(
264 10 : iface, src->addr, false);
265 10 : struct nbt_netlogon_response *response = NULL;
266 10 : char *reply_mailslot = NULL;
267 :
268 10 : 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 10 : status = nbtd_mailslot_netlogon_reply(
275 : iface, packet, src, dgmslot, &response, &reply_mailslot);
276 :
277 10 : if (NT_STATUS_IS_OK(status)) {
278 20 : dgram_mailslot_netlogon_reply(
279 : reply_iface->dgmsock, packet,
280 10 : lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx),
281 : reply_mailslot, response);
282 : }
283 :
284 10 : TALLOC_FREE(response);
285 10 : TALLOC_FREE(reply_mailslot);
286 : }
|