Store printer guid in the dsspooler registry key so we don't have to
[Samba/gebeck_regimport.git] / source / utils / net_ads_cldap.c
blobf81c763093f17ce63be118d653cab531136e46b2
1 /*
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.
21 #include "includes.h"
22 #include "../utils/net.h"
24 #ifdef HAVE_ADS
26 struct cldap_netlogon_reply {
27 uint32 version;
28 uint32 flags;
29 GUID guid;
30 char *domain;
31 char *server_name;
32 char *domain_flatname;
33 char *server_flatname;
34 char *dns_name;
35 uint32 unknown2[2];
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)
45 unsigned len = *p;
46 (*ret) = NULL;
47 if (len == 0) return 1;
48 (*ret) = smb_xstrndup(p+1, len);
49 return len+1;
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)
58 char *s;
59 unsigned len, total_len=0;
61 (*ret) = NULL;
63 while ((len = pull_len_string(&s, p)) > 1) {
64 if (total_len) {
65 char *s2;
66 asprintf(&s2, "%s.%s", *ret, s);
67 SAFE_FREE(*ret);
68 (*ret) = s2;
69 } else {
70 (*ret) = s;
72 total_len += len;
73 p += len;
76 return total_len + 1;
81 do a cldap netlogon query
83 static int send_cldap_netlogon(int sock, const char *domain,
84 const char *hostname, unsigned ntversion)
86 ASN1_DATA data;
87 char ntver[4];
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));
107 asn1_pop_tag(&data);
109 asn1_push_tag(&data, ASN1_CONTEXT(3));
110 asn1_write_OctetString(&data, "Host", 4);
111 asn1_write_OctetString(&data, hostname, strlen(hostname));
112 asn1_pop_tag(&data);
114 asn1_push_tag(&data, ASN1_CONTEXT(3));
115 asn1_write_OctetString(&data, "NtVer", 5);
116 asn1_write_OctetString(&data, ntver, 4);
117 asn1_pop_tag(&data);
119 asn1_pop_tag(&data);
121 asn1_push_tag(&data,ASN1_SEQUENCE(0));
122 asn1_write_OctetString(&data, "NetLogon", 8);
123 asn1_pop_tag(&data);
124 asn1_pop_tag(&data);
125 asn1_pop_tag(&data);
127 if (data.has_error) {
128 d_printf("Failed to build cldap netlogon at offset %d\n", (int)data.ofs);
129 asn1_free(&data);
130 return -1;
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);
138 asn1_free(&data);
140 return 0;
145 receive a cldap netlogon reply
147 static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
149 int ret;
150 ASN1_DATA data;
151 DATA_BLOB blob;
152 DATA_BLOB os1, os2, os3;
153 uint32 i1;
154 char *p;
156 blob = data_blob(NULL, 8192);
158 ret = read(sock, blob.data, blob.length);
160 if (ret <= 0) {
161 d_printf("no reply received to cldap netlogon\n");
162 return -1;
164 blob.length = ret;
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);
178 asn1_end_tag(&data);
179 asn1_end_tag(&data);
180 asn1_end_tag(&data);
181 asn1_end_tag(&data);
182 asn1_end_tag(&data);
184 if (data.has_error) {
185 d_printf("Failed to parse cldap reply\n");
186 return -1;
189 file_save("cldap_reply_core.dat", os3.data, os3.length);
191 p = os3.data;
193 reply->version = IVAL(p, 0); p += 4;
194 reply->flags = IVAL(p, 0); p += 4;
195 memcpy(&reply->guid.info, p, GUID_SIZE);
196 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);
202 p += 1;
203 p += pull_len_string(&reply->server_flatname, p);
204 p += 2;
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);
212 return 0;
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)
233 int sock;
234 int ret;
235 struct cldap_netlogon_reply reply;
237 sock = open_udp_socket(inet_ntoa(ads->ldap_ip), ads->ldap_port);
238 if (sock == -1) {
239 d_printf("Failed to open udp socket to %s:%u\n",
240 inet_ntoa(ads->ldap_ip),
241 ads->ldap_port);
242 return -1;
245 ret = send_cldap_netlogon(sock, ads->config.realm, global_myname(), 6);
246 if (ret != 0) {
247 return ret;
250 ret = recv_cldap_netlogon(sock, &reply);
251 close(sock);
253 if (ret == -1) {
254 return -1;
257 d_printf("Version: 0x%x\n", reply.version);
258 d_printf("GUID: ");
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);
269 return ret;
273 #endif