2 Samba Unix/Linux SMB client library
3 net ads cldap functions
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 Copyright (C) 2003 Jim McDonough (jmcd@us.ibm.com)
6 Copyright (C) 2008 Guenther Deschner (gd@samba.org)
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 3 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, see <http://www.gnu.org/licenses/>.
25 do a cldap netlogon query
27 static int send_cldap_netlogon(int sock, const char *domain,
28 const char *hostname, unsigned ntversion)
32 #ifdef CLDAP_USER_QUERY
35 SIVAL(aac, 0, 0x00000180);
37 SIVAL(ntver, 0, ntversion);
39 memset(&data, 0, sizeof(data));
41 asn1_push_tag(&data,ASN1_SEQUENCE(0));
42 asn1_write_Integer(&data, 4);
43 asn1_push_tag(&data, ASN1_APPLICATION(3));
44 asn1_write_OctetString(&data, NULL, 0);
45 asn1_write_enumerated(&data, 0);
46 asn1_write_enumerated(&data, 0);
47 asn1_write_Integer(&data, 0);
48 asn1_write_Integer(&data, 0);
49 asn1_write_BOOLEAN2(&data, False);
50 asn1_push_tag(&data, ASN1_CONTEXT(0));
53 asn1_push_tag(&data, ASN1_CONTEXT(3));
54 asn1_write_OctetString(&data, "DnsDomain", 9);
55 asn1_write_OctetString(&data, domain, strlen(domain));
59 asn1_push_tag(&data, ASN1_CONTEXT(3));
60 asn1_write_OctetString(&data, "Host", 4);
61 asn1_write_OctetString(&data, hostname, strlen(hostname));
64 #ifdef CLDAP_USER_QUERY
65 asn1_push_tag(&data, ASN1_CONTEXT(3));
66 asn1_write_OctetString(&data, "User", 4);
67 asn1_write_OctetString(&data, "SAMBA$", 6);
70 asn1_push_tag(&data, ASN1_CONTEXT(3));
71 asn1_write_OctetString(&data, "AAC", 4);
72 asn1_write_OctetString(&data, aac, 4);
76 asn1_push_tag(&data, ASN1_CONTEXT(3));
77 asn1_write_OctetString(&data, "NtVer", 5);
78 asn1_write_OctetString(&data, ntver, 4);
83 asn1_push_tag(&data,ASN1_SEQUENCE(0));
84 asn1_write_OctetString(&data, "NetLogon", 8);
90 DEBUG(2,("Failed to build cldap netlogon at offset %d\n", (int)data.ofs));
95 if (write(sock, data.data, data.length) != (ssize_t)data.length) {
96 DEBUG(2,("failed to send cldap query (%s)\n", strerror(errno)));
106 static SIG_ATOMIC_T gotalarm;
108 /***************************************************************
109 Signal function to tell us we timed out.
110 ****************************************************************/
112 static void gotalarm_sig(void)
118 receive a cldap netlogon reply
120 static int recv_cldap_netlogon(TALLOC_CTX *mem_ctx,
123 struct netlogon_samlogon_response **reply)
127 DATA_BLOB blob = data_blob_null;
128 DATA_BLOB os1 = data_blob_null;
129 DATA_BLOB os2 = data_blob_null;
130 DATA_BLOB os3 = data_blob_null;
132 /* half the time of a regular ldap timeout, not less than 3 seconds. */
133 unsigned int al_secs = MAX(3,lp_ldap_timeout()/2);
134 struct netlogon_samlogon_response *r = NULL;
137 blob = data_blob(NULL, 8192);
138 if (blob.data == NULL) {
139 DEBUG(1, ("data_blob failed\n"));
146 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
148 /* End setup timeout. */
150 ret = read(sock, blob.data, blob.length);
152 /* Teardown timeout. */
153 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
157 DEBUG(1,("no reply received to cldap netlogon\n"));
158 data_blob_free(&blob);
163 asn1_load(&data, blob);
164 asn1_start_tag(&data, ASN1_SEQUENCE(0));
165 asn1_read_Integer(&data, &i1);
166 asn1_start_tag(&data, ASN1_APPLICATION(4));
167 asn1_read_OctetString(&data, &os1);
168 asn1_start_tag(&data, ASN1_SEQUENCE(0));
169 asn1_start_tag(&data, ASN1_SEQUENCE(0));
170 asn1_read_OctetString(&data, &os2);
171 asn1_start_tag(&data, ASN1_SET);
172 asn1_read_OctetString(&data, &os3);
179 if (data.has_error) {
180 data_blob_free(&blob);
181 data_blob_free(&os1);
182 data_blob_free(&os2);
183 data_blob_free(&os3);
185 DEBUG(1,("Failed to parse cldap reply\n"));
189 r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response);
192 data_blob_free(&os1);
193 data_blob_free(&os2);
194 data_blob_free(&os3);
195 data_blob_free(&blob);
199 status = pull_netlogon_samlogon_response(&os3, mem_ctx, r);
200 if (!NT_STATUS_IS_OK(status)) {
201 data_blob_free(&os1);
202 data_blob_free(&os2);
203 data_blob_free(&os3);
204 data_blob_free(&blob);
209 map_netlogon_samlogon_response(r);
211 data_blob_free(&os1);
212 data_blob_free(&os2);
213 data_blob_free(&os3);
214 data_blob_free(&blob);
227 /*******************************************************************
228 do a cldap netlogon query. Always 389/udp
229 *******************************************************************/
231 bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
235 struct netlogon_samlogon_response **reply)
240 sock = open_udp_socket(server, LDAP_PORT );
242 DEBUG(2,("ads_cldap_netlogon: Failed to open udp socket to %s\n",
247 ret = send_cldap_netlogon(sock, realm, global_myname(), nt_version);
252 ret = recv_cldap_netlogon(mem_ctx, sock, nt_version, reply);
262 /*******************************************************************
263 do a cldap netlogon query. Always 389/udp
264 *******************************************************************/
266 bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
269 struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5)
271 uint32_t nt_version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
272 struct netlogon_samlogon_response *reply = NULL;
275 ret = ads_cldap_netlogon(mem_ctx, server, realm, nt_version, &reply);
280 if (reply->ntver != NETLOGON_NT_VERSION_5EX) {
281 DEBUG(0,("ads_cldap_netlogon_5: nt_version mismatch: 0x%08x\n",
286 *reply5 = reply->nt5_ex;