2 Samba Unix/Linux SMB client library
3 net ads cldap functions
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "../utils/net.h"
26 struct cldap_netlogon_reply
{
32 char *domain_flatname
;
33 char *server_flatname
;
40 pull a length prefixed string from a packet
41 return number of bytes consumed
43 static unsigned pull_len_string(char **ret
, const char *p
)
47 if (len
== 0) return 1;
48 (*ret
) = smb_xstrndup(p
+1, len
);
53 pull a dotted string from a packet
54 return number of bytes consumed
56 static unsigned pull_dotted_string(char **ret
, const char *p
)
59 unsigned len
, total_len
=0;
63 while ((len
= pull_len_string(&s
, p
)) > 1) {
66 asprintf(&s2
, "%s.%s", *ret
, s
);
81 do a cldap netlogon query
83 static int send_cldap_netlogon(int sock
, const char *domain
,
84 const char *hostname
, unsigned ntversion
)
89 SIVAL(ntver
, 0, ntversion
);
91 memset(&data
, 0, sizeof(data
));
93 asn1_push_tag(&data
,ASN1_SEQUENCE(0));
94 asn1_write_Integer(&data
, 4);
95 asn1_push_tag(&data
, ASN1_APPLICATION(3));
96 asn1_write_OctetString(&data
, NULL
, 0);
97 asn1_write_enumerated(&data
, 0);
98 asn1_write_enumerated(&data
, 0);
99 asn1_write_Integer(&data
, 0);
100 asn1_write_Integer(&data
, 0);
101 asn1_write_BOOLEAN2(&data
, False
);
102 asn1_push_tag(&data
, ASN1_CONTEXT(0));
104 asn1_push_tag(&data
, ASN1_CONTEXT(3));
105 asn1_write_OctetString(&data
, "DnsDomain", 9);
106 asn1_write_OctetString(&data
, domain
, strlen(domain
));
109 asn1_push_tag(&data
, ASN1_CONTEXT(3));
110 asn1_write_OctetString(&data
, "Host", 4);
111 asn1_write_OctetString(&data
, hostname
, strlen(hostname
));
114 asn1_push_tag(&data
, ASN1_CONTEXT(3));
115 asn1_write_OctetString(&data
, "NtVer", 5);
116 asn1_write_OctetString(&data
, ntver
, 4);
121 asn1_push_tag(&data
,ASN1_SEQUENCE(0));
122 asn1_write_OctetString(&data
, "NetLogon", 8);
127 if (data
.has_error
) {
128 d_printf("Failed to build cldap netlogon at offset %d\n", (int)data
.ofs
);
133 if (write(sock
, data
.data
, data
.length
) != data
.length
) {
134 d_printf("failed to send cldap query (%s)\n", strerror(errno
));
137 file_save("cldap_query.dat", data
.data
, data
.length
);
145 receive a cldap netlogon reply
147 static int recv_cldap_netlogon(int sock
, struct cldap_netlogon_reply
*reply
)
152 DATA_BLOB os1
, os2
, os3
;
156 blob
= data_blob(NULL
, 8192);
158 ret
= read(sock
, blob
.data
, blob
.length
);
161 d_printf("no reply received to cldap netlogon\n");
166 file_save("cldap_reply.dat", blob
.data
, blob
.length
);
168 asn1_load(&data
, blob
);
169 asn1_start_tag(&data
, ASN1_SEQUENCE(0));
170 asn1_read_Integer(&data
, &i1
);
171 asn1_start_tag(&data
, ASN1_APPLICATION(4));
172 asn1_read_OctetString(&data
, &os1
);
173 asn1_start_tag(&data
, ASN1_SEQUENCE(0));
174 asn1_start_tag(&data
, ASN1_SEQUENCE(0));
175 asn1_read_OctetString(&data
, &os2
);
176 asn1_start_tag(&data
, ASN1_SET
);
177 asn1_read_OctetString(&data
, &os3
);
184 if (data
.has_error
) {
185 d_printf("Failed to parse cldap reply\n");
189 file_save("cldap_reply_core.dat", os3
.data
, os3
.length
);
193 reply
->version
= IVAL(p
, 0); p
+= 4;
194 reply
->flags
= IVAL(p
, 0); p
+= 4;
195 memcpy(&reply
->guid
.info
, p
, GUID_SIZE
);
197 p
+= pull_dotted_string(&reply
->domain
, p
);
198 p
+= 2; /* 0xc018 - whats this? */
199 p
+= pull_len_string(&reply
->server_name
, p
);
200 p
+= 2; /* 0xc018 - whats this? */
201 p
+= pull_len_string(&reply
->domain_flatname
, p
);
203 p
+= pull_len_string(&reply
->server_flatname
, p
);
205 p
+= pull_len_string(&reply
->dns_name
, p
);
207 data_blob_free(&os1
);
208 data_blob_free(&os2
);
209 data_blob_free(&os3
);
210 data_blob_free(&blob
);
217 free a cldap reply packet
219 static void cldap_reply_free(struct cldap_netlogon_reply
*reply
)
221 SAFE_FREE(reply
->domain
);
222 SAFE_FREE(reply
->server_name
);
223 SAFE_FREE(reply
->domain_flatname
);
224 SAFE_FREE(reply
->server_flatname
);
225 SAFE_FREE(reply
->dns_name
);
229 do a cldap netlogon query
231 int ads_cldap_netlogon(ADS_STRUCT
*ads
)
235 struct cldap_netlogon_reply reply
;
237 sock
= open_udp_socket(inet_ntoa(ads
->ldap_ip
), ads
->ldap_port
);
239 d_printf("Failed to open udp socket to %s:%u\n",
240 inet_ntoa(ads
->ldap_ip
),
245 ret
= send_cldap_netlogon(sock
, ads
->config
.realm
, global_myname(), 6);
250 ret
= recv_cldap_netlogon(sock
, &reply
);
257 d_printf("Version: 0x%x\n", reply
.version
);
259 print_guid(&reply
.guid
);
260 d_printf("Flags: 0x%x\n", reply
.flags
);
261 d_printf("Domain: %s\n", reply
.domain
);
262 d_printf("Server Name: %s\n", reply
.server_name
);
263 d_printf("Flatname: %s\n", reply
.domain_flatname
);
264 d_printf("Server Name2: %s\n", reply
.server_flatname
);
265 d_printf("DNS Name: %s\n", reply
.dns_name
);
267 cldap_reply_free(&reply
);