Move the alarm setup/teardown out of another_ldap_try() and into separate
[Samba/gebeck_regimport.git] / auth / gensec / gensec.c
blob417b05cf063c4dd6dae3ab594058b620e34ea603
1 /*
2 Unix SMB/CIFS implementation.
4 Generic Authentication Interface
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "system/network.h"
25 #include <tevent.h>
26 #include "lib/tsocket/tsocket.h"
27 #include "lib/util/tevent_ntstatus.h"
28 #include "auth/gensec/gensec.h"
31 wrappers for the gensec function pointers
33 _PUBLIC_ NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
34 uint8_t *data, size_t length,
35 const uint8_t *whole_pdu, size_t pdu_length,
36 const DATA_BLOB *sig)
38 if (!gensec_security->ops->unseal_packet) {
39 return NT_STATUS_NOT_IMPLEMENTED;
41 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
42 return NT_STATUS_INVALID_PARAMETER;
45 return gensec_security->ops->unseal_packet(gensec_security,
46 data, length,
47 whole_pdu, pdu_length,
48 sig);
51 _PUBLIC_ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
52 const uint8_t *data, size_t length,
53 const uint8_t *whole_pdu, size_t pdu_length,
54 const DATA_BLOB *sig)
56 if (!gensec_security->ops->check_packet) {
57 return NT_STATUS_NOT_IMPLEMENTED;
59 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
60 return NT_STATUS_INVALID_PARAMETER;
63 return gensec_security->ops->check_packet(gensec_security, data, length, whole_pdu, pdu_length, sig);
66 _PUBLIC_ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
67 TALLOC_CTX *mem_ctx,
68 uint8_t *data, size_t length,
69 const uint8_t *whole_pdu, size_t pdu_length,
70 DATA_BLOB *sig)
72 if (!gensec_security->ops->seal_packet) {
73 return NT_STATUS_NOT_IMPLEMENTED;
75 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
76 return NT_STATUS_INVALID_PARAMETER;
79 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
82 _PUBLIC_ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
83 TALLOC_CTX *mem_ctx,
84 const uint8_t *data, size_t length,
85 const uint8_t *whole_pdu, size_t pdu_length,
86 DATA_BLOB *sig)
88 if (!gensec_security->ops->sign_packet) {
89 return NT_STATUS_NOT_IMPLEMENTED;
91 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
92 return NT_STATUS_INVALID_PARAMETER;
95 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
98 _PUBLIC_ size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
100 if (!gensec_security->ops->sig_size) {
101 return 0;
103 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
104 return 0;
107 return gensec_security->ops->sig_size(gensec_security, data_size);
110 size_t gensec_max_wrapped_size(struct gensec_security *gensec_security)
112 if (!gensec_security->ops->max_wrapped_size) {
113 return (1 << 17);
116 return gensec_security->ops->max_wrapped_size(gensec_security);
119 size_t gensec_max_input_size(struct gensec_security *gensec_security)
121 if (!gensec_security->ops->max_input_size) {
122 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
125 return gensec_security->ops->max_input_size(gensec_security);
128 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
129 TALLOC_CTX *mem_ctx,
130 const DATA_BLOB *in,
131 DATA_BLOB *out)
133 if (!gensec_security->ops->wrap) {
134 return NT_STATUS_NOT_IMPLEMENTED;
136 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
139 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
140 TALLOC_CTX *mem_ctx,
141 const DATA_BLOB *in,
142 DATA_BLOB *out)
144 if (!gensec_security->ops->unwrap) {
145 return NT_STATUS_NOT_IMPLEMENTED;
147 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
150 _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
151 TALLOC_CTX *mem_ctx,
152 DATA_BLOB *session_key)
154 if (!gensec_security->ops->session_key) {
155 return NT_STATUS_NOT_IMPLEMENTED;
157 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
158 return NT_STATUS_NO_USER_SESSION_KEY;
161 return gensec_security->ops->session_key(gensec_security, mem_ctx, session_key);
165 * Return the credentials of a logged on user, including session keys
166 * etc.
168 * Only valid after a successful authentication
170 * May only be called once per authentication.
174 _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
175 TALLOC_CTX *mem_ctx,
176 struct auth_session_info **session_info)
178 if (!gensec_security->ops->session_info) {
179 return NT_STATUS_NOT_IMPLEMENTED;
181 return gensec_security->ops->session_info(gensec_security, mem_ctx, session_info);
185 * Next state function for the GENSEC state machine
187 * @param gensec_security GENSEC State
188 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
189 * @param in The request, as a DATA_BLOB
190 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
191 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
192 * or NT_STATUS_OK if the user is authenticated.
195 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
196 const DATA_BLOB in, DATA_BLOB *out)
198 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
201 struct gensec_update_state {
202 struct tevent_immediate *im;
203 struct gensec_security *gensec_security;
204 DATA_BLOB in;
205 DATA_BLOB out;
208 static void gensec_update_async_trigger(struct tevent_context *ctx,
209 struct tevent_immediate *im,
210 void *private_data);
212 * Next state function for the GENSEC state machine async version
214 * @param mem_ctx The memory context for the request
215 * @param ev The event context for the request
216 * @param gensec_security GENSEC State
217 * @param in The request, as a DATA_BLOB
219 * @return The request handle or NULL on no memory failure
222 _PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx,
223 struct tevent_context *ev,
224 struct gensec_security *gensec_security,
225 const DATA_BLOB in)
227 struct tevent_req *req;
228 struct gensec_update_state *state = NULL;
230 req = tevent_req_create(mem_ctx, &state,
231 struct gensec_update_state);
232 if (req == NULL) {
233 return NULL;
236 state->gensec_security = gensec_security;
237 state->in = in;
238 state->out = data_blob(NULL, 0);
239 state->im = tevent_create_immediate(state);
240 if (tevent_req_nomem(state->im, req)) {
241 return tevent_req_post(req, ev);
244 tevent_schedule_immediate(state->im, ev,
245 gensec_update_async_trigger,
246 req);
248 return req;
251 static void gensec_update_async_trigger(struct tevent_context *ctx,
252 struct tevent_immediate *im,
253 void *private_data)
255 struct tevent_req *req =
256 talloc_get_type_abort(private_data, struct tevent_req);
257 struct gensec_update_state *state =
258 tevent_req_data(req, struct gensec_update_state);
259 NTSTATUS status;
261 status = gensec_update(state->gensec_security, state,
262 state->in, &state->out);
263 if (tevent_req_nterror(req, status)) {
264 return;
267 tevent_req_done(req);
271 * Next state function for the GENSEC state machine
273 * @param req request state
274 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
275 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
276 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
277 * or NT_STATUS_OK if the user is authenticated.
279 _PUBLIC_ NTSTATUS gensec_update_recv(struct tevent_req *req,
280 TALLOC_CTX *out_mem_ctx,
281 DATA_BLOB *out)
283 struct gensec_update_state *state =
284 tevent_req_data(req, struct gensec_update_state);
285 NTSTATUS status;
287 if (tevent_req_is_nterror(req, &status)) {
288 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
289 tevent_req_received(req);
290 return status;
292 } else {
293 status = NT_STATUS_OK;
296 *out = state->out;
297 talloc_steal(out_mem_ctx, out->data);
299 tevent_req_received(req);
300 return status;
304 * Set the requirement for a certain feature on the connection
308 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
309 uint32_t feature)
311 if (!gensec_security->ops || !gensec_security->ops->want_feature) {
312 gensec_security->want_features |= feature;
313 return;
315 gensec_security->ops->want_feature(gensec_security, feature);
319 * Check the requirement for a certain feature on the connection
323 _PUBLIC_ bool gensec_have_feature(struct gensec_security *gensec_security,
324 uint32_t feature)
326 if (!gensec_security->ops->have_feature) {
327 return false;
330 /* We might 'have' features that we don't 'want', because the
331 * other end demanded them, or we can't neotiate them off */
332 return gensec_security->ops->have_feature(gensec_security, feature);
336 * Return the credentials structure associated with a GENSEC context
340 _PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
342 if (!gensec_security) {
343 return NULL;
345 return gensec_security->credentials;
349 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
353 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
355 gensec_security->target.service = talloc_strdup(gensec_security, service);
356 if (!gensec_security->target.service) {
357 return NT_STATUS_NO_MEMORY;
359 return NT_STATUS_OK;
362 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security)
364 if (gensec_security->target.service) {
365 return gensec_security->target.service;
368 return "host";
372 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
376 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
378 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
379 if (hostname && !gensec_security->target.hostname) {
380 return NT_STATUS_NO_MEMORY;
382 return NT_STATUS_OK;
385 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
387 /* We allow the target hostname to be overriden for testing purposes */
388 if (gensec_security->settings->target_hostname) {
389 return gensec_security->settings->target_hostname;
392 if (gensec_security->target.hostname) {
393 return gensec_security->target.hostname;
396 /* We could add use the 'set sockaddr' call, and do a reverse
397 * lookup, but this would be both insecure (compromising the
398 * way kerberos works) and add DNS timeouts */
399 return NULL;
403 * Set (and talloc_reference) local and peer socket addresses onto a socket
404 * context on the GENSEC context.
406 * This is so that kerberos can include these addresses in
407 * cryptographic tokens, to avoid certain attacks.
411 * @brief Set the local gensec address.
413 * @param gensec_security The gensec security context to use.
415 * @param remote The local address to set.
417 * @return On success NT_STATUS_OK is returned or an NT_STATUS
418 * error.
420 _PUBLIC_ NTSTATUS gensec_set_local_address(struct gensec_security *gensec_security,
421 const struct tsocket_address *local)
423 TALLOC_FREE(gensec_security->local_addr);
425 if (local == NULL) {
426 return NT_STATUS_OK;
429 gensec_security->local_addr = tsocket_address_copy(local, gensec_security);
430 if (gensec_security->local_addr == NULL) {
431 return NT_STATUS_NO_MEMORY;
434 return NT_STATUS_OK;
438 * @brief Set the remote gensec address.
440 * @param gensec_security The gensec security context to use.
442 * @param remote The remote address to set.
444 * @return On success NT_STATUS_OK is returned or an NT_STATUS
445 * error.
447 _PUBLIC_ NTSTATUS gensec_set_remote_address(struct gensec_security *gensec_security,
448 const struct tsocket_address *remote)
450 TALLOC_FREE(gensec_security->remote_addr);
452 if (remote == NULL) {
453 return NT_STATUS_OK;
456 gensec_security->remote_addr = tsocket_address_copy(remote, gensec_security);
457 if (gensec_security->remote_addr == NULL) {
458 return NT_STATUS_NO_MEMORY;
461 return NT_STATUS_OK;
465 * @brief Get the local address from a gensec security context.
467 * @param gensec_security The security context to get the address from.
469 * @return The address as tsocket_address which could be NULL if
470 * no address is set.
472 _PUBLIC_ const struct tsocket_address *gensec_get_local_address(struct gensec_security *gensec_security)
474 if (gensec_security == NULL) {
475 return NULL;
477 return gensec_security->local_addr;
481 * @brief Get the remote address from a gensec security context.
483 * @param gensec_security The security context to get the address from.
485 * @return The address as tsocket_address which could be NULL if
486 * no address is set.
488 _PUBLIC_ const struct tsocket_address *gensec_get_remote_address(struct gensec_security *gensec_security)
490 if (gensec_security == NULL) {
491 return NULL;
493 return gensec_security->remote_addr;
497 * Set the target principal (assuming it it known, say from the SPNEGO reply)
498 * - ensures it is talloc()ed
502 _PUBLIC_ NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
504 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
505 if (!gensec_security->target.principal) {
506 return NT_STATUS_NO_MEMORY;
508 return NT_STATUS_OK;
511 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
513 if (gensec_security->target.principal) {
514 return gensec_security->target.principal;
517 return NULL;