~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/libads/cldap.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
6
   Copyright (C) 2008 Guenther Deschner (gd@samba.org)
 
7
 
 
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.
 
12
 
 
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.
 
17
 
 
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/>.  
 
20
*/
 
21
 
 
22
#include "includes.h"
 
23
 
 
24
/*
 
25
  do a cldap netlogon query
 
26
*/
 
27
static int send_cldap_netlogon(TALLOC_CTX *mem_ctx, int sock, const char *domain,
 
28
                               const char *hostname, unsigned ntversion)
 
29
{
 
30
        ASN1_DATA *data;
 
31
        char ntver[4];
 
32
#ifdef CLDAP_USER_QUERY
 
33
        char aac[4];
 
34
 
 
35
        SIVAL(aac, 0, 0x00000180);
 
36
#endif
 
37
        SIVAL(ntver, 0, ntversion);
 
38
 
 
39
        data = asn1_init(mem_ctx);
 
40
        if (data == NULL) {
 
41
                return -1;
 
42
        }
 
43
 
 
44
        asn1_push_tag(data,ASN1_SEQUENCE(0));
 
45
        asn1_write_Integer(data, 4);
 
46
        asn1_push_tag(data, ASN1_APPLICATION(3));
 
47
        asn1_write_OctetString(data, NULL, 0);
 
48
        asn1_write_enumerated(data, 0);
 
49
        asn1_write_enumerated(data, 0);
 
50
        asn1_write_Integer(data, 0);
 
51
        asn1_write_Integer(data, 0);
 
52
        asn1_write_BOOLEAN(data, False);
 
53
        asn1_push_tag(data, ASN1_CONTEXT(0));
 
54
 
 
55
        if (domain) {
 
56
                asn1_push_tag(data, ASN1_CONTEXT(3));
 
57
                asn1_write_OctetString(data, "DnsDomain", 9);
 
58
                asn1_write_OctetString(data, domain, strlen(domain));
 
59
                asn1_pop_tag(data);
 
60
        }
 
61
 
 
62
        asn1_push_tag(data, ASN1_CONTEXT(3));
 
63
        asn1_write_OctetString(data, "Host", 4);
 
64
        asn1_write_OctetString(data, hostname, strlen(hostname));
 
65
        asn1_pop_tag(data);
 
66
 
 
67
#ifdef CLDAP_USER_QUERY
 
68
        asn1_push_tag(data, ASN1_CONTEXT(3));
 
69
        asn1_write_OctetString(data, "User", 4);
 
70
        asn1_write_OctetString(data, "SAMBA$", 6);
 
71
        asn1_pop_tag(data);
 
72
 
 
73
        asn1_push_tag(data, ASN1_CONTEXT(3));
 
74
        asn1_write_OctetString(data, "AAC", 4);
 
75
        asn1_write_OctetString(data, aac, 4);
 
76
        asn1_pop_tag(data);
 
77
#endif
 
78
 
 
79
        asn1_push_tag(data, ASN1_CONTEXT(3));
 
80
        asn1_write_OctetString(data, "NtVer", 5);
 
81
        asn1_write_OctetString(data, ntver, 4);
 
82
        asn1_pop_tag(data);
 
83
 
 
84
        asn1_pop_tag(data);
 
85
 
 
86
        asn1_push_tag(data,ASN1_SEQUENCE(0));
 
87
        asn1_write_OctetString(data, "NetLogon", 8);
 
88
        asn1_pop_tag(data);
 
89
        asn1_pop_tag(data);
 
90
        asn1_pop_tag(data);
 
91
 
 
92
        if (data->has_error) {
 
93
                DEBUG(2,("Failed to build cldap netlogon at offset %d\n", (int)data->ofs));
 
94
                asn1_free(data);
 
95
                return -1;
 
96
        }
 
97
 
 
98
        if (write(sock, data->data, data->length) != (ssize_t)data->length) {
 
99
                DEBUG(2,("failed to send cldap query (%s)\n", strerror(errno)));
 
100
                asn1_free(data);
 
101
                return -1;
 
102
        }
 
103
 
 
104
        asn1_free(data);
 
105
 
 
106
        return 0;
 
107
}
 
108
 
 
109
/*
 
110
  receive a cldap netlogon reply
 
111
*/
 
112
static int recv_cldap_netlogon(TALLOC_CTX *mem_ctx,
 
113
                               int sock,
 
114
                               uint32_t nt_version,
 
115
                               struct netlogon_samlogon_response **reply)
 
116
{
 
117
        int ret;
 
118
        ASN1_DATA *data;
 
119
        DATA_BLOB blob = data_blob_null;
 
120
        DATA_BLOB os1 = data_blob_null;
 
121
        DATA_BLOB os2 = data_blob_null;
 
122
        DATA_BLOB os3 = data_blob_null;
 
123
        int i1;
 
124
        struct netlogon_samlogon_response *r = NULL;
 
125
        NTSTATUS status;
 
126
 
 
127
        fd_set r_fds;
 
128
        struct timeval timeout;
 
129
 
 
130
        blob = data_blob(NULL, 8192);
 
131
        if (blob.data == NULL) {
 
132
                DEBUG(1, ("data_blob failed\n"));
 
133
                errno = ENOMEM;
 
134
                return -1;
 
135
        }
 
136
 
 
137
        FD_ZERO(&r_fds);
 
138
        FD_SET(sock, &r_fds);
 
139
 
 
140
        /*
 
141
         * half the time of a regular ldap timeout, not less than 3 seconds.
 
142
         */
 
143
        timeout.tv_sec = MAX(3,lp_ldap_timeout()/2);
 
144
        timeout.tv_usec = 0;
 
145
 
 
146
        ret = sys_select(sock+1, &r_fds, NULL, NULL, &timeout);
 
147
        if (ret == -1) {
 
148
                DEBUG(10, ("select failed: %s\n", strerror(errno)));
 
149
                data_blob_free(&blob);
 
150
                return -1;
 
151
        }
 
152
 
 
153
        if (ret == 0) {
 
154
                DEBUG(1,("no reply received to cldap netlogon "
 
155
                        "(select timeout %u sec)\n",
 
156
                        (unsigned int)timeout.tv_sec));
 
157
                data_blob_free(&blob);
 
158
                return -1;
 
159
        }
 
160
 
 
161
        ret = read(sock, blob.data, blob.length);
 
162
        if (ret <= 0) {
 
163
                DEBUG(1,("no reply received to cldap netlogon "
 
164
                        "(ret = %d: Error = %s)\n",
 
165
                        ret,
 
166
                        ret == -1 ? strerror(errno) : "" ));
 
167
                data_blob_free(&blob);
 
168
                return -1;
 
169
        }
 
170
        blob.length = ret;
 
171
 
 
172
        data = asn1_init(mem_ctx);
 
173
        if (data == NULL) {
 
174
                data_blob_free(&blob);
 
175
                return -1;
 
176
        }
 
177
 
 
178
        asn1_load(data, blob);
 
179
        asn1_start_tag(data, ASN1_SEQUENCE(0));
 
180
        asn1_read_Integer(data, &i1);
 
181
        asn1_start_tag(data, ASN1_APPLICATION(4));
 
182
        asn1_read_OctetString(data, NULL, &os1);
 
183
        asn1_start_tag(data, ASN1_SEQUENCE(0));
 
184
        asn1_start_tag(data, ASN1_SEQUENCE(0));
 
185
        asn1_read_OctetString(data, NULL, &os2);
 
186
        asn1_start_tag(data, ASN1_SET);
 
187
        asn1_read_OctetString(data, NULL, &os3);
 
188
        asn1_end_tag(data);
 
189
        asn1_end_tag(data);
 
190
        asn1_end_tag(data);
 
191
        asn1_end_tag(data);
 
192
        asn1_end_tag(data);
 
193
 
 
194
        if (data->has_error) {
 
195
                data_blob_free(&blob);
 
196
                data_blob_free(&os1);
 
197
                data_blob_free(&os2);
 
198
                data_blob_free(&os3);
 
199
                asn1_free(data);
 
200
                DEBUG(1,("Failed to parse cldap reply\n"));
 
201
                return -1;
 
202
        }
 
203
 
 
204
        r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response);
 
205
        if (!r) {
 
206
                errno = ENOMEM;
 
207
                data_blob_free(&os1);
 
208
                data_blob_free(&os2);
 
209
                data_blob_free(&os3);
 
210
                data_blob_free(&blob);
 
211
                asn1_free(data);
 
212
                return -1;
 
213
        }
 
214
 
 
215
        status = pull_netlogon_samlogon_response(&os3, mem_ctx, NULL, r);
 
216
        if (!NT_STATUS_IS_OK(status)) {
 
217
                data_blob_free(&os1);
 
218
                data_blob_free(&os2);
 
219
                data_blob_free(&os3);
 
220
                data_blob_free(&blob);
 
221
                asn1_free(data);
 
222
                TALLOC_FREE(r);
 
223
                return -1;
 
224
        }
 
225
 
 
226
        map_netlogon_samlogon_response(r);
 
227
 
 
228
        data_blob_free(&os1);
 
229
        data_blob_free(&os2);
 
230
        data_blob_free(&os3);
 
231
        data_blob_free(&blob);
 
232
 
 
233
        asn1_free(data);
 
234
 
 
235
        if (reply) {
 
236
                *reply = r;
 
237
        } else {
 
238
                TALLOC_FREE(r);
 
239
        }
 
240
 
 
241
        return 0;
 
242
}
 
243
 
 
244
/*******************************************************************
 
245
  do a cldap netlogon query.  Always 389/udp
 
246
*******************************************************************/
 
247
 
 
248
bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
 
249
                        const char *server,
 
250
                        const char *realm,
 
251
                        uint32_t nt_version,
 
252
                        struct netlogon_samlogon_response **reply)
 
253
{
 
254
        int sock;
 
255
        int ret;
 
256
 
 
257
        sock = open_udp_socket(server, LDAP_PORT );
 
258
        if (sock == -1) {
 
259
                DEBUG(2,("ads_cldap_netlogon: Failed to open udp socket to %s. "
 
260
                        "Error %s\n",
 
261
                        server,
 
262
                        strerror(errno) ));
 
263
                return False;
 
264
        }
 
265
 
 
266
        ret = send_cldap_netlogon(mem_ctx, sock, realm, global_myname(), nt_version);
 
267
        if (ret != 0) {
 
268
                close(sock);
 
269
                return False;
 
270
        }
 
271
        ret = recv_cldap_netlogon(mem_ctx, sock, nt_version, reply);
 
272
        close(sock);
 
273
 
 
274
        if (ret == -1) {
 
275
                return False;
 
276
        }
 
277
 
 
278
        return True;
 
279
}
 
280
 
 
281
/*******************************************************************
 
282
  do a cldap netlogon query.  Always 389/udp
 
283
*******************************************************************/
 
284
 
 
285
bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
 
286
                          const char *server,
 
287
                          const char *realm,
 
288
                          struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5)
 
289
{
 
290
        uint32_t nt_version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
 
291
        struct netlogon_samlogon_response *reply = NULL;
 
292
        bool ret;
 
293
 
 
294
        ret = ads_cldap_netlogon(mem_ctx, server, realm, nt_version, &reply);
 
295
        if (!ret) {
 
296
                return false;
 
297
        }
 
298
 
 
299
        if (reply->ntver != NETLOGON_NT_VERSION_5EX) {
 
300
                DEBUG(0,("ads_cldap_netlogon_5: nt_version mismatch: 0x%08x\n",
 
301
                        reply->ntver));
 
302
                return false;
 
303
        }
 
304
 
 
305
        *reply5 = reply->data.nt5_ex;
 
306
 
 
307
        return true;
 
308
}