2 Public Interface file for Linux DNS client library implementation
4 Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
5 Copyright (C) 2006 Gerald Carter <jerry@samba.org>
7 ** NOTE! The following LGPL license applies to the libaddns
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "lib/util/talloc_stack.h"
28 #include "lib/util/data_blob.h"
29 #include "lib/util/time.h"
30 #include "lib/util/charset/charset.h"
31 #include "libcli/util/ntstatus.h"
32 #include "auth/gensec/gensec.h"
36 static DNS_ERROR
dns_negotiate_gss_ctx_int(struct dns_connection
*conn
,
38 struct gensec_security
*gensec
,
39 enum dns_ServerType srv_type
)
41 TALLOC_CTX
*frame
= talloc_stackframe();
42 struct dns_request
*req
= NULL
;
43 struct dns_buffer
*buf
= NULL
;
44 DATA_BLOB in
= { .length
= 0, };
45 DATA_BLOB out
= { .length
= 0, };
50 status
= gensec_update(gensec
, frame
, in
, &out
);
52 if (GENSEC_UPDATE_IS_NTERROR(status
)) {
53 err
= ERROR_DNS_GSS_ERROR
;
57 if (out
.length
!= 0) {
60 time_t t
= time(NULL
);
62 err
= dns_create_query(frame
, keyname
, QTYPE_TKEY
,
64 if (!ERR_DNS_IS_OK(err
)) goto error
;
66 err
= dns_create_tkey_record(
67 req
, keyname
, "gss.microsoft.com", t
,
68 t
+ 86400, DNS_TKEY_MODE_GSSAPI
, 0,
71 if (!ERR_DNS_IS_OK(err
)) goto error
;
73 /* Windows 2000 DNS is broken and requires the
74 TKEY payload in the Answer section instead
75 of the Additional section like Windows 2003 */
77 if ( srv_type
== DNS_SRV_WIN2000
) {
78 err
= dns_add_rrec(req
, rec
, &req
->num_answers
,
81 err
= dns_add_rrec(req
, rec
, &req
->num_additionals
,
85 if (!ERR_DNS_IS_OK(err
)) goto error
;
87 err
= dns_marshall_request(frame
, req
, &buf
);
88 if (!ERR_DNS_IS_OK(err
)) goto error
;
90 err
= dns_send(conn
, buf
);
91 if (!ERR_DNS_IS_OK(err
)) goto error
;
96 err
= dns_receive(frame
, conn
, &buf
);
97 if (!ERR_DNS_IS_OK(err
)) goto error
;
100 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
101 struct dns_request
*resp
;
102 struct dns_tkey_record
*tkey
;
103 struct dns_rrec
*tkey_answer
= NULL
;
107 err
= ERROR_DNS_BAD_RESPONSE
;
111 err
= dns_unmarshall_request(buf
, buf
, &resp
);
112 if (!ERR_DNS_IS_OK(err
)) goto error
;
115 * TODO: Compare id and keyname
118 for (i
=0; i
< resp
->num_answers
; i
++) {
119 if (resp
->answers
[i
]->type
!= QTYPE_TKEY
) {
123 tkey_answer
= resp
->answers
[i
];
126 if (tkey_answer
== NULL
) {
127 err
= ERROR_DNS_INVALID_MESSAGE
;
131 err
= dns_unmarshall_tkey_record(
132 frame
, resp
->answers
[0], &tkey
);
133 if (!ERR_DNS_IS_OK(err
)) goto error
;
135 in
= data_blob_const(tkey
->key
, tkey
->key_length
);
140 } while (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
));
142 /* If we arrive here, we have a valid security context */
144 err
= ERROR_DNS_SUCCESS
;
152 DNS_ERROR
dns_negotiate_sec_ctx(const char *servername
,
154 struct gensec_security
*gensec
,
155 enum dns_ServerType srv_type
)
157 TALLOC_CTX
*frame
= talloc_stackframe();
159 struct dns_connection
*conn
= NULL
;
161 err
= dns_open_connection( servername
, DNS_TCP
, frame
, &conn
);
162 if (!ERR_DNS_IS_OK(err
)) goto error
;
164 err
= dns_negotiate_gss_ctx_int(conn
, keyname
,
167 if (!ERR_DNS_IS_OK(err
)) goto error
;
175 DNS_ERROR
dns_sign_update(struct dns_update_request
*req
,
176 struct gensec_security
*gensec
,
178 const char *algorithmname
,
179 time_t time_signed
, uint16_t fudge
)
181 TALLOC_CTX
*frame
= talloc_stackframe();
182 struct dns_buffer
*buf
;
184 struct dns_domain_name
*key
, *algorithm
;
185 struct dns_rrec
*rec
;
186 DATA_BLOB mic
= { .length
= 0, };
189 err
= dns_marshall_update_request(frame
, req
, &buf
);
190 if (!ERR_DNS_IS_OK(err
)) return err
;
192 err
= dns_domain_name_from_string(frame
, keyname
, &key
);
193 if (!ERR_DNS_IS_OK(err
)) goto error
;
195 err
= dns_domain_name_from_string(frame
, algorithmname
, &algorithm
);
196 if (!ERR_DNS_IS_OK(err
)) goto error
;
198 dns_marshall_domain_name(buf
, key
);
199 dns_marshall_uint16(buf
, DNS_CLASS_ANY
);
200 dns_marshall_uint32(buf
, 0); /* TTL */
201 dns_marshall_domain_name(buf
, algorithm
);
202 dns_marshall_uint16(buf
, 0); /* Time prefix for 48-bit time_t */
203 dns_marshall_uint32(buf
, time_signed
);
204 dns_marshall_uint16(buf
, fudge
);
205 dns_marshall_uint16(buf
, 0); /* error */
206 dns_marshall_uint16(buf
, 0); /* other len */
209 if (!ERR_DNS_IS_OK(buf
->error
)) goto error
;
211 status
= gensec_sign_packet(gensec
,
218 if (!NT_STATUS_IS_OK(status
)) {
219 err
= ERROR_DNS_GSS_ERROR
;
223 if (mic
.length
> 0xffff) {
224 err
= ERROR_DNS_GSS_ERROR
;
228 err
= dns_create_tsig_record(frame
, keyname
, algorithmname
, time_signed
,
229 fudge
, mic
.length
, mic
.data
,
231 if (!ERR_DNS_IS_OK(err
)) goto error
;
233 err
= dns_add_rrec(req
, rec
, &req
->num_additionals
, &req
->additional
);