ede3e77c9653529b0542cbdee31e1740de6d477c
[sfrench/samba-autobuild/.git] / source4 / nbt_server / dgram / netlogon.c
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 "smbd/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 static NTSTATUS nbtd_netlogon_getdc(struct nbtd_interface *iface,
40                                     struct nbt_dgram_packet *packet,
41                                     const struct socket_address *src,
42                                     struct nbt_netlogon_packet *netlogon,
43                                     TALLOC_CTX *mem_ctx,
44                                     struct nbt_netlogon_response **presponse)
45 {
46         struct nbt_name *name = &packet->data.msg.dest_name;
47         struct nbt_netlogon_response_from_pdc *pdc;
48         struct ldb_context *samctx;
49         struct nbt_netlogon_response *response;
50
51         /* only answer getdc requests on the PDC or LOGON names */
52         if (name->type != NBT_NAME_PDC && name->type != NBT_NAME_LOGON) {
53                 return NT_STATUS_NOT_SUPPORTED;
54         }
55
56         samctx = iface->nbtsrv->sam_ctx;
57
58         if (lpcfg_server_role(iface->nbtsrv->task->lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC
59             || !samdb_is_pdc(samctx)) {
60                 DEBUG(2, ("Not a PDC, so not processing LOGON_PRIMARY_QUERY\n"));
61                 return NT_STATUS_NOT_SUPPORTED;
62         }
63
64         if (strcasecmp_m(name->name, lpcfg_workgroup(iface->nbtsrv->task->lp_ctx)) != 0) {
65                 DEBUG(5,("GetDC requested for a domian %s that we don't host\n", name->name));
66                 return NT_STATUS_NOT_SUPPORTED;
67         }
68
69         /* setup a GETDC reply */
70         response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
71         if (response == NULL) {
72                 return NT_STATUS_NO_MEMORY;
73         }
74         response->response_type = NETLOGON_GET_PDC;
75         pdc = &response->data.get_pdc;
76
77         pdc->command = NETLOGON_RESPONSE_FROM_PDC;
78
79         pdc->pdc_name = talloc_strdup(
80                 response, lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx));
81         if (pdc->pdc_name == NULL) {
82                 TALLOC_FREE(response);
83                 return NT_STATUS_NO_MEMORY;
84         }
85
86         pdc->unicode_pdc_name = pdc->pdc_name;
87
88         pdc->domain_name = talloc_strdup(
89                 response, lpcfg_workgroup(iface->nbtsrv->task->lp_ctx));
90         if (pdc->domain_name == NULL) {
91                 TALLOC_FREE(response);
92                 return NT_STATUS_NO_MEMORY;
93         }
94
95         pdc->nt_version       = 1;
96         pdc->lmnt_token       = 0xFFFF;
97         pdc->lm20_token       = 0xFFFF;
98
99         *presponse = response;
100         return NT_STATUS_OK;
101 }
102
103 /*
104   reply to a ADS style GETDC request
105  */
106 static NTSTATUS nbtd_netlogon_samlogon(
107         struct nbtd_interface *iface,
108         struct nbt_dgram_packet *packet,
109         const struct socket_address *src,
110         struct nbt_netlogon_packet *netlogon,
111         TALLOC_CTX *mem_ctx,
112         struct nbt_netlogon_response **presponse)
113 {
114         struct nbt_name *name = &packet->data.msg.dest_name;
115         struct ldb_context *samctx;
116         struct dom_sid *sid;
117         struct nbt_netlogon_response *response;
118         NTSTATUS status;
119
120         /* only answer getdc requests on the PDC or LOGON names */
121         if (name->type != NBT_NAME_PDC && name->type != NBT_NAME_LOGON) {
122                 return NT_STATUS_NOT_SUPPORTED;
123         }
124
125         samctx = iface->nbtsrv->sam_ctx;
126
127         if (netlogon->req.logon.sid_size) {
128                 sid = &netlogon->req.logon.sid;
129         } else {
130                 sid = NULL;
131         }
132
133         response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
134         if (response == NULL) {
135                 return NT_STATUS_NO_MEMORY;
136         }
137         response->response_type = NETLOGON_SAMLOGON;
138
139         status = fill_netlogon_samlogon_response(
140                 samctx, response, NULL, name->name, sid, NULL,
141                 netlogon->req.logon.user_name,
142                 netlogon->req.logon.acct_control, src->addr,
143                 netlogon->req.logon.nt_version, iface->nbtsrv->task->lp_ctx,
144                 &response->data.samlogon, false);
145         if (!NT_STATUS_IS_OK(status)) {
146                 DEBUG(2,("NBT netlogon query failed domain=%s sid=%s version=%d - %s\n",
147                          name->name, dom_sid_string(packet, sid), netlogon->req.logon.nt_version, nt_errstr(status)));
148                 TALLOC_FREE(response);
149                 return status;
150         }
151
152         *presponse = response;
153         return NT_STATUS_OK;
154 }
155
156 /*
157   handle incoming netlogon mailslot requests
158 */
159 void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot, 
160                                     struct nbt_dgram_packet *packet, 
161                                     struct socket_address *src)
162 {
163         NTSTATUS status = NT_STATUS_NO_MEMORY;
164         struct nbtd_interface *iface = 
165                 talloc_get_type(dgmslot->private_data, struct nbtd_interface);
166         struct nbt_netlogon_packet *netlogon = NULL;
167         struct nbtd_interface *reply_iface = nbtd_find_reply_iface(
168                 iface, src->addr, false);
169         struct nbtd_iface_name *iname;
170         struct nbt_name *name = &packet->data.msg.dest_name;
171         struct nbt_netlogon_response *response;
172
173         if (reply_iface->ip_address == NULL) {
174                 DBG_WARNING("Could not obtain own IP address for datagram "
175                             "socket\n");
176                 goto failed;
177         }
178
179         netlogon = talloc(dgmslot, struct nbt_netlogon_packet);
180         if (netlogon == NULL) {
181                 goto failed;
182         }
183
184         /*
185           see if the we are listening on the destination netbios name
186         */
187         iname = nbtd_find_iname(iface, name, 0);
188         if (iname == NULL) {
189                 status = NT_STATUS_BAD_NETWORK_NAME;
190                 goto failed;
191         }
192
193         DEBUG(5,("netlogon request to %s from %s:%d\n",
194                  nbt_name_string(netlogon, name), src->addr, src->port));
195         status = dgram_mailslot_netlogon_parse_request(netlogon, packet,
196                                                        netlogon);
197         if (!NT_STATUS_IS_OK(status)) goto failed;
198
199         switch (netlogon->command) {
200         case LOGON_PRIMARY_QUERY:
201                 status = nbtd_netlogon_getdc(iface, packet, src, netlogon,
202                                              netlogon, &response);
203                 break;
204         case LOGON_SAM_LOGON_REQUEST:
205                 status = nbtd_netlogon_samlogon(iface, packet, src, netlogon,
206                                                 netlogon, &response);
207                 break;
208         default:
209                 DEBUG(2,("unknown netlogon op %d from %s:%d\n", 
210                          netlogon->command, src->addr, src->port));
211                 NDR_PRINT_DEBUG(nbt_netlogon_packet, netlogon);
212                 status = NT_STATUS_NOT_SUPPORTED;
213                 break;
214         }
215
216         if (NT_STATUS_IS_OK(status)) {
217                 dgram_mailslot_netlogon_reply(
218                         reply_iface->dgmsock, packet,
219                         lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx),
220                         netlogon->req.logon.mailslot_name, response);
221         }
222
223         talloc_free(netlogon);
224         return;
225
226 failed:
227         DEBUG(2,("nbtd netlogon handler failed from %s:%d to %s - %s\n",
228                  src->addr, src->port, nbt_name_string(netlogon, name),
229                  nt_errstr(status)));
230         talloc_free(netlogon);
231 }