r19699: - use better names for the site strings
[Samba/ekacnet.git] / source4 / cldap_server / netlogon.c
blobf5090df8376bf39ef732fe1128c0eeca89873fa4
1 /*
2 Unix SMB/CIFS implementation.
4 CLDAP server - netlogon handling
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "libcli/ldap/ldap.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "lib/events/events.h"
28 #include "lib/socket/socket.h"
29 #include "smbd/service_task.h"
30 #include "cldap_server/cldap_server.h"
31 #include "librpc/gen_ndr/ndr_misc.h"
32 #include "dsdb/samdb/samdb.h"
33 #include "auth/auth.h"
34 #include "db_wrap.h"
35 #include "system/network.h"
36 #include "lib/socket/netif.h"
39 fill in the cldap netlogon union for a given version
41 static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd,
42 TALLOC_CTX *mem_ctx,
43 const char *domain,
44 const char *domain_guid,
45 const char *user,
46 const char *src_address,
47 uint32_t version,
48 union nbt_cldap_netlogon *netlogon)
50 const char *ref_attrs[] = {"nETBIOSName", "dnsRoot", "ncName", NULL};
51 const char *dom_attrs[] = {"objectGUID", NULL};
52 struct ldb_message **ref_res, **dom_res;
53 int ret, count = 0;
54 const char **services = lp_server_services();
55 uint32_t server_type;
56 const char *pdc_name;
57 struct GUID domain_uuid;
58 const char *realm;
59 const char *dns_domain;
60 const char *pdc_dns_name;
61 const char *flatname;
62 const char *server_site;
63 const char *client_site;
64 const char *pdc_ip;
65 const struct ldb_dn *partitions_basedn;
67 if (cldapd->samctx == NULL) {
68 cldapd->samctx = samdb_connect(cldapd, anonymous_session(cldapd));
69 if (cldapd->samctx == NULL) {
70 DEBUG(2,("Unable to open sam in cldap netlogon reply\n"));
71 return NT_STATUS_INTERNAL_DB_CORRUPTION;
75 partitions_basedn = samdb_partitions_dn(cldapd->samctx, mem_ctx);
77 /* the domain has an optional trailing . */
78 if (domain && domain[strlen(domain)-1] == '.') {
79 domain = talloc_strndup(mem_ctx, domain, strlen(domain)-1);
82 if (domain) {
83 struct ldb_result *dom_ldb_result;
84 struct ldb_dn *dom_dn;
85 /* try and find the domain */
86 count = gendb_search(cldapd->samctx, mem_ctx, partitions_basedn, &ref_res, ref_attrs,
87 "(&(&(objectClass=crossRef)(dnsRoot=%s))(nETBIOSName=*))",
88 domain);
89 if (count == 1) {
90 dom_dn = samdb_result_dn(mem_ctx, ref_res[0], "ncName", NULL);
91 if (!dom_dn) {
92 return NT_STATUS_NO_SUCH_DOMAIN;
94 ret = ldb_search(cldapd->samctx, dom_dn,
95 LDB_SCOPE_BASE, "objectClass=domain",
96 dom_attrs, &dom_ldb_result);
97 if (ret != LDB_SUCCESS) {
98 DEBUG(2,("Error finding domain '%s'/'%s' in sam: %s\n", domain, ldb_dn_linearize(mem_ctx, dom_dn), ldb_errstring(cldapd->samctx)));
99 return NT_STATUS_NO_SUCH_DOMAIN;
101 talloc_steal(mem_ctx, dom_ldb_result);
102 if (dom_ldb_result->count != 1) {
103 DEBUG(2,("Error finding domain '%s'/'%s' in sam\n", domain, ldb_dn_linearize(mem_ctx, dom_dn)));
104 return NT_STATUS_NO_SUCH_DOMAIN;
106 dom_res = dom_ldb_result->msgs;
110 if (count == 0 && domain_guid) {
111 /* OK, so no dice with the name, try and find the domain with the GUID */
112 count = gendb_search(cldapd->samctx, mem_ctx, NULL, &dom_res, dom_attrs,
113 "(&(objectClass=domainDNS)(objectGUID=%s))",
114 domain_guid);
115 if (count == 1) {
116 /* try and find the domain */
117 ret = gendb_search(cldapd->samctx, mem_ctx, partitions_basedn, &ref_res, ref_attrs,
118 "(&(objectClass=crossRef)(ncName=%s))",
119 ldb_dn_linearize(mem_ctx, dom_res[0]->dn));
120 if (ret != 1) {
121 DEBUG(2,("Unable to find referece to '%s' in sam\n",
122 ldb_dn_linearize(mem_ctx, dom_res[0]->dn)));
123 return NT_STATUS_NO_SUCH_DOMAIN;
128 if (count == 0) {
129 DEBUG(2,("Unable to find domain with name %s or GUID {%s}\n", domain, domain_guid));
130 return NT_STATUS_NO_SUCH_DOMAIN;
133 server_type =
134 NBT_SERVER_PDC | NBT_SERVER_GC |
135 NBT_SERVER_DS | NBT_SERVER_TIMESERV |
136 NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE |
137 NBT_SERVER_GOOD_TIMESERV;
139 if (str_list_check(services, "ldap")) {
140 server_type |= NBT_SERVER_LDAP;
143 if (str_list_check(services, "kdc")) {
144 server_type |= NBT_SERVER_KDC;
147 pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
148 domain_uuid = samdb_result_guid(dom_res[0], "objectGUID");
149 realm = samdb_result_string(ref_res[0], "dnsRoot", lp_realm());
150 dns_domain = samdb_result_string(ref_res[0], "dnsRoot", lp_realm());
151 pdc_dns_name = talloc_asprintf(mem_ctx, "%s.%s",
152 strlower_talloc(mem_ctx, lp_netbios_name()),
153 dns_domain);
155 flatname = samdb_result_string(ref_res[0], "nETBIOSName", lp_workgroup());
156 server_site = "Default-First-Site-Name";
157 client_site = "Default-First-Site-Name";
158 pdc_ip = iface_best_ip(src_address);
160 ZERO_STRUCTP(netlogon);
162 switch (version & 0xF) {
163 case 0:
164 case 1:
165 netlogon->logon1.type = (user?19+2:19);
166 netlogon->logon1.pdc_name = pdc_name;
167 netlogon->logon1.user_name = user;
168 netlogon->logon1.domain_name = flatname;
169 netlogon->logon1.nt_version = 1;
170 netlogon->logon1.lmnt_token = 0xFFFF;
171 netlogon->logon1.lm20_token = 0xFFFF;
172 break;
173 case 2:
174 case 3:
175 netlogon->logon3.type = (user?19+2:19);
176 netlogon->logon3.pdc_name = pdc_name;
177 netlogon->logon3.user_name = user;
178 netlogon->logon3.domain_name = flatname;
179 netlogon->logon3.domain_uuid = domain_uuid;
180 netlogon->logon3.forest = realm;
181 netlogon->logon3.dns_domain = dns_domain;
182 netlogon->logon3.pdc_dns_name = pdc_dns_name;
183 netlogon->logon3.pdc_ip = pdc_ip;
184 netlogon->logon3.server_type = server_type;
185 netlogon->logon3.lmnt_token = 0xFFFF;
186 netlogon->logon3.lm20_token = 0xFFFF;
187 break;
188 case 4:
189 case 5:
190 case 6:
191 case 7:
192 netlogon->logon5.type = (user?23+2:23);
193 netlogon->logon5.server_type = server_type;
194 netlogon->logon5.domain_uuid = domain_uuid;
195 netlogon->logon5.forest = realm;
196 netlogon->logon5.dns_domain = dns_domain;
197 netlogon->logon5.pdc_dns_name = pdc_dns_name;
198 netlogon->logon5.domain = flatname;
199 netlogon->logon5.pdc_name = lp_netbios_name();
200 netlogon->logon5.user_name = user;
201 netlogon->logon5.server_site = server_site;
202 netlogon->logon5.client_site = client_site;
203 netlogon->logon5.lmnt_token = 0xFFFF;
204 netlogon->logon5.lm20_token = 0xFFFF;
205 break;
206 default:
207 netlogon->logon13.type = (user?23+2:23);
208 netlogon->logon13.server_type = server_type;
209 netlogon->logon13.domain_uuid = domain_uuid;
210 netlogon->logon13.forest = realm;
211 netlogon->logon13.dns_domain = dns_domain;
212 netlogon->logon13.pdc_dns_name = pdc_dns_name;
213 netlogon->logon13.domain = flatname;
214 netlogon->logon13.pdc_name = lp_netbios_name();
215 netlogon->logon13.user_name = user;
216 netlogon->logon13.server_site = server_site;
217 netlogon->logon13.client_site = client_site;
218 netlogon->logon13.unknown = 10;
219 netlogon->logon13.unknown2 = 2;
220 netlogon->logon13.pdc_ip = pdc_ip;
221 netlogon->logon13.lmnt_token = 0xFFFF;
222 netlogon->logon13.lm20_token = 0xFFFF;
223 break;
226 return NT_STATUS_OK;
231 handle incoming cldap requests
233 void cldapd_netlogon_request(struct cldap_socket *cldap,
234 uint32_t message_id,
235 struct ldb_parse_tree *tree,
236 struct socket_address *src)
238 struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private, struct cldapd_server);
239 int i;
240 const char *domain = NULL;
241 const char *host = NULL;
242 const char *user = NULL;
243 const char *domain_guid = NULL;
244 const char *domain_sid = NULL;
245 int acct_control = -1;
246 int version = -1;
247 union nbt_cldap_netlogon netlogon;
248 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
250 TALLOC_CTX *tmp_ctx = talloc_new(cldap);
252 if (tree->operation != LDB_OP_AND) goto failed;
254 /* extract the query elements */
255 for (i=0;i<tree->u.list.num_elements;i++) {
256 struct ldb_parse_tree *t = tree->u.list.elements[i];
257 if (t->operation != LDB_OP_EQUALITY) goto failed;
258 if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) {
259 domain = talloc_strndup(tmp_ctx,
260 (const char *)t->u.equality.value.data,
261 t->u.equality.value.length);
263 if (strcasecmp(t->u.equality.attr, "Host") == 0) {
264 host = talloc_strndup(tmp_ctx,
265 (const char *)t->u.equality.value.data,
266 t->u.equality.value.length);
268 if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) {
269 NTSTATUS enc_status;
270 struct GUID guid;
271 enc_status = ldap_decode_ndr_GUID(tmp_ctx,
272 t->u.equality.value, &guid);
273 if (NT_STATUS_IS_OK(enc_status)) {
274 domain_guid = GUID_string(tmp_ctx, &guid);
277 if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) {
278 domain_sid = talloc_strndup(tmp_ctx,
279 (const char *)t->u.equality.value.data,
280 t->u.equality.value.length);
282 if (strcasecmp(t->u.equality.attr, "User") == 0) {
283 user = talloc_strndup(tmp_ctx,
284 (const char *)t->u.equality.value.data,
285 t->u.equality.value.length);
287 if (strcasecmp(t->u.equality.attr, "NtVer") == 0 &&
288 t->u.equality.value.length == 4) {
289 version = IVAL(t->u.equality.value.data, 0);
291 if (strcasecmp(t->u.equality.attr, "AAC") == 0 &&
292 t->u.equality.value.length == 4) {
293 acct_control = IVAL(t->u.equality.value.data, 0);
297 if (domain_guid == NULL && domain == NULL) {
298 domain = lp_realm();
301 if (version == -1) {
302 goto failed;
305 DEBUG(5,("cldap netlogon query domain=%s host=%s user=%s version=%d guid=%s\n",
306 domain, host, user, version, domain_guid));
308 status = cldapd_netlogon_fill(cldapd, tmp_ctx, domain, domain_guid,
309 user, src->addr,
310 version, &netlogon);
311 if (!NT_STATUS_IS_OK(status)) {
312 goto failed;
315 status = cldap_netlogon_reply(cldap, message_id, src, version,
316 &netlogon);
317 if (!NT_STATUS_IS_OK(status)) {
318 goto failed;
321 talloc_free(tmp_ctx);
322 return;
324 failed:
325 DEBUG(2,("cldap netlogon query failed domain=%s host=%s version=%d - %s\n",
326 domain, host, version, nt_errstr(status)));
327 talloc_free(tmp_ctx);
328 cldap_empty_reply(cldap, message_id, src);