cldap: add talloc context to ads_cldap_netlogon().
[Samba/gebeck_regimport.git] / source3 / libads / cldap.c
blobbe084c9df6031d506ddf4161d53efbda6b3bd81b
1 /*
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)
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
24 do a cldap netlogon query
26 static int send_cldap_netlogon(int sock, const char *domain,
27 const char *hostname, unsigned ntversion)
29 ASN1_DATA data;
30 char ntver[4];
31 #ifdef CLDAP_USER_QUERY
32 char aac[4];
34 SIVAL(aac, 0, 0x00000180);
35 #endif
36 SIVAL(ntver, 0, ntversion);
38 memset(&data, 0, sizeof(data));
40 asn1_push_tag(&data,ASN1_SEQUENCE(0));
41 asn1_write_Integer(&data, 4);
42 asn1_push_tag(&data, ASN1_APPLICATION(3));
43 asn1_write_OctetString(&data, NULL, 0);
44 asn1_write_enumerated(&data, 0);
45 asn1_write_enumerated(&data, 0);
46 asn1_write_Integer(&data, 0);
47 asn1_write_Integer(&data, 0);
48 asn1_write_BOOLEAN2(&data, False);
49 asn1_push_tag(&data, ASN1_CONTEXT(0));
51 if (domain) {
52 asn1_push_tag(&data, ASN1_CONTEXT(3));
53 asn1_write_OctetString(&data, "DnsDomain", 9);
54 asn1_write_OctetString(&data, domain, strlen(domain));
55 asn1_pop_tag(&data);
58 asn1_push_tag(&data, ASN1_CONTEXT(3));
59 asn1_write_OctetString(&data, "Host", 4);
60 asn1_write_OctetString(&data, hostname, strlen(hostname));
61 asn1_pop_tag(&data);
63 #ifdef CLDAP_USER_QUERY
64 asn1_push_tag(&data, ASN1_CONTEXT(3));
65 asn1_write_OctetString(&data, "User", 4);
66 asn1_write_OctetString(&data, "SAMBA$", 6);
67 asn1_pop_tag(&data);
69 asn1_push_tag(&data, ASN1_CONTEXT(3));
70 asn1_write_OctetString(&data, "AAC", 4);
71 asn1_write_OctetString(&data, aac, 4);
72 asn1_pop_tag(&data);
73 #endif
75 asn1_push_tag(&data, ASN1_CONTEXT(3));
76 asn1_write_OctetString(&data, "NtVer", 5);
77 asn1_write_OctetString(&data, ntver, 4);
78 asn1_pop_tag(&data);
80 asn1_pop_tag(&data);
82 asn1_push_tag(&data,ASN1_SEQUENCE(0));
83 asn1_write_OctetString(&data, "NetLogon", 8);
84 asn1_pop_tag(&data);
85 asn1_pop_tag(&data);
86 asn1_pop_tag(&data);
88 if (data.has_error) {
89 DEBUG(2,("Failed to build cldap netlogon at offset %d\n", (int)data.ofs));
90 asn1_free(&data);
91 return -1;
94 if (write(sock, data.data, data.length) != (ssize_t)data.length) {
95 DEBUG(2,("failed to send cldap query (%s)\n", strerror(errno)));
96 asn1_free(&data);
97 return -1;
100 asn1_free(&data);
102 return 0;
105 static SIG_ATOMIC_T gotalarm;
107 /***************************************************************
108 Signal function to tell us we timed out.
109 ****************************************************************/
111 static void gotalarm_sig(void)
113 gotalarm = 1;
117 receive a cldap netlogon reply
119 static int recv_cldap_netlogon(TALLOC_CTX *mem_ctx,
120 int sock,
121 struct nbt_cldap_netlogon_5 *reply)
123 int ret;
124 ASN1_DATA data;
125 DATA_BLOB blob = data_blob_null;
126 DATA_BLOB os1 = data_blob_null;
127 DATA_BLOB os2 = data_blob_null;
128 DATA_BLOB os3 = data_blob_null;
129 int i1;
130 /* half the time of a regular ldap timeout, not less than 3 seconds. */
131 unsigned int al_secs = MAX(3,lp_ldap_timeout()/2);
132 union nbt_cldap_netlogon p;
133 enum ndr_err_code ndr_err;
135 blob = data_blob(NULL, 8192);
136 if (blob.data == NULL) {
137 DEBUG(1, ("data_blob failed\n"));
138 errno = ENOMEM;
139 return -1;
142 /* Setup timeout */
143 gotalarm = 0;
144 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
145 alarm(al_secs);
146 /* End setup timeout. */
148 ret = read(sock, blob.data, blob.length);
150 /* Teardown timeout. */
151 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
152 alarm(0);
154 if (ret <= 0) {
155 DEBUG(1,("no reply received to cldap netlogon\n"));
156 data_blob_free(&blob);
157 return -1;
159 blob.length = ret;
161 asn1_load(&data, blob);
162 asn1_start_tag(&data, ASN1_SEQUENCE(0));
163 asn1_read_Integer(&data, &i1);
164 asn1_start_tag(&data, ASN1_APPLICATION(4));
165 asn1_read_OctetString(&data, &os1);
166 asn1_start_tag(&data, ASN1_SEQUENCE(0));
167 asn1_start_tag(&data, ASN1_SEQUENCE(0));
168 asn1_read_OctetString(&data, &os2);
169 asn1_start_tag(&data, ASN1_SET);
170 asn1_read_OctetString(&data, &os3);
171 asn1_end_tag(&data);
172 asn1_end_tag(&data);
173 asn1_end_tag(&data);
174 asn1_end_tag(&data);
175 asn1_end_tag(&data);
177 if (data.has_error) {
178 data_blob_free(&blob);
179 data_blob_free(&os1);
180 data_blob_free(&os2);
181 data_blob_free(&os3);
182 asn1_free(&data);
183 DEBUG(1,("Failed to parse cldap reply\n"));
184 return -1;
187 ndr_err = ndr_pull_union_blob_all(&os3, mem_ctx, &p, 5,
188 (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon);
189 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
190 return -1;
193 *reply = p.logon5;
195 if (DEBUGLEVEL >= 10) {
196 NDR_PRINT_UNION_DEBUG(nbt_cldap_netlogon, 5, &p);
199 data_blob_free(&os1);
200 data_blob_free(&os2);
201 data_blob_free(&os3);
202 data_blob_free(&blob);
204 asn1_free(&data);
206 return 0;
209 /*******************************************************************
210 do a cldap netlogon query. Always 389/udp
211 *******************************************************************/
213 bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
214 const char *server,
215 const char *realm,
216 struct nbt_cldap_netlogon_5 *reply)
218 int sock;
219 int ret;
221 sock = open_udp_socket(server, LDAP_PORT );
222 if (sock == -1) {
223 DEBUG(2,("ads_cldap_netlogon: Failed to open udp socket to %s\n",
224 server));
225 return False;
228 ret = send_cldap_netlogon(sock, realm, global_myname(), 6);
229 if (ret != 0) {
230 close(sock);
231 return False;
233 ret = recv_cldap_netlogon(mem_ctx, sock, reply);
234 close(sock);
236 if (ret == -1) {
237 return False;
240 return True;