source: vendor/current/auth/gensec/gensec.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 20.3 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 Generic Authentication Interface
5
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
8
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.
13
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.
18
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/>.
21*/
22
23#include "includes.h"
24#include "system/network.h"
25#define TEVENT_DEPRECATED 1
26#include <tevent.h>
27#include "lib/tsocket/tsocket.h"
28#include "lib/util/tevent_ntstatus.h"
29#include "auth/gensec/gensec.h"
30#include "auth/gensec/gensec_internal.h"
31#include "librpc/gen_ndr/dcerpc.h"
32
33_PRIVATE_ NTSTATUS gensec_may_reset_crypto(struct gensec_security *gensec_security,
34 bool full_reset)
35{
36 if (!gensec_security->ops->may_reset_crypto) {
37 return NT_STATUS_OK;
38 }
39
40 return gensec_security->ops->may_reset_crypto(gensec_security, full_reset);
41}
42
43/*
44 wrappers for the gensec function pointers
45*/
46_PUBLIC_ NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
47 uint8_t *data, size_t length,
48 const uint8_t *whole_pdu, size_t pdu_length,
49 const DATA_BLOB *sig)
50{
51 if (!gensec_security->ops->unseal_packet) {
52 return NT_STATUS_NOT_IMPLEMENTED;
53 }
54 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
55 return NT_STATUS_INVALID_PARAMETER;
56 }
57 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
58 return NT_STATUS_INVALID_PARAMETER;
59 }
60 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE)) {
61 return NT_STATUS_INVALID_PARAMETER;
62 }
63
64 return gensec_security->ops->unseal_packet(gensec_security,
65 data, length,
66 whole_pdu, pdu_length,
67 sig);
68}
69
70_PUBLIC_ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
71 const uint8_t *data, size_t length,
72 const uint8_t *whole_pdu, size_t pdu_length,
73 const DATA_BLOB *sig)
74{
75 if (!gensec_security->ops->check_packet) {
76 return NT_STATUS_NOT_IMPLEMENTED;
77 }
78 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
79 return NT_STATUS_INVALID_PARAMETER;
80 }
81
82 return gensec_security->ops->check_packet(gensec_security, data, length, whole_pdu, pdu_length, sig);
83}
84
85_PUBLIC_ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
86 TALLOC_CTX *mem_ctx,
87 uint8_t *data, size_t length,
88 const uint8_t *whole_pdu, size_t pdu_length,
89 DATA_BLOB *sig)
90{
91 if (!gensec_security->ops->seal_packet) {
92 return NT_STATUS_NOT_IMPLEMENTED;
93 }
94 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
95 return NT_STATUS_INVALID_PARAMETER;
96 }
97 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
98 return NT_STATUS_INVALID_PARAMETER;
99 }
100 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE)) {
101 return NT_STATUS_INVALID_PARAMETER;
102 }
103
104 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
105}
106
107_PUBLIC_ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
108 TALLOC_CTX *mem_ctx,
109 const uint8_t *data, size_t length,
110 const uint8_t *whole_pdu, size_t pdu_length,
111 DATA_BLOB *sig)
112{
113 if (!gensec_security->ops->sign_packet) {
114 return NT_STATUS_NOT_IMPLEMENTED;
115 }
116 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
117 return NT_STATUS_INVALID_PARAMETER;
118 }
119
120 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
121}
122
123_PUBLIC_ size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
124{
125 if (!gensec_security->ops->sig_size) {
126 return 0;
127 }
128 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
129 return 0;
130 }
131 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
132 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE)) {
133 return 0;
134 }
135 }
136
137 return gensec_security->ops->sig_size(gensec_security, data_size);
138}
139
140_PUBLIC_ size_t gensec_max_wrapped_size(struct gensec_security *gensec_security)
141{
142 if (!gensec_security->ops->max_wrapped_size) {
143 return (1 << 17);
144 }
145
146 return gensec_security->ops->max_wrapped_size(gensec_security);
147}
148
149_PUBLIC_ size_t gensec_max_input_size(struct gensec_security *gensec_security)
150{
151 if (!gensec_security->ops->max_input_size) {
152 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
153 }
154
155 return gensec_security->ops->max_input_size(gensec_security);
156}
157
158_PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
159 TALLOC_CTX *mem_ctx,
160 const DATA_BLOB *in,
161 DATA_BLOB *out)
162{
163 if (!gensec_security->ops->wrap) {
164 return NT_STATUS_NOT_IMPLEMENTED;
165 }
166 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
167}
168
169_PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
170 TALLOC_CTX *mem_ctx,
171 const DATA_BLOB *in,
172 DATA_BLOB *out)
173{
174 if (!gensec_security->ops->unwrap) {
175 return NT_STATUS_NOT_IMPLEMENTED;
176 }
177 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
178}
179
180_PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
181 TALLOC_CTX *mem_ctx,
182 DATA_BLOB *session_key)
183{
184 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
185 return NT_STATUS_NO_USER_SESSION_KEY;
186 }
187
188 if (!gensec_security->ops->session_key) {
189 return NT_STATUS_NOT_IMPLEMENTED;
190 }
191
192 return gensec_security->ops->session_key(gensec_security, mem_ctx, session_key);
193}
194
195/**
196 * Return the credentials of a logged on user, including session keys
197 * etc.
198 *
199 * Only valid after a successful authentication
200 *
201 * May only be called once per authentication.
202 *
203 */
204
205_PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
206 TALLOC_CTX *mem_ctx,
207 struct auth_session_info **session_info)
208{
209 if (!gensec_security->ops->session_info) {
210 return NT_STATUS_NOT_IMPLEMENTED;
211 }
212 return gensec_security->ops->session_info(gensec_security, mem_ctx, session_info);
213}
214
215_PUBLIC_ void gensec_set_max_update_size(struct gensec_security *gensec_security,
216 uint32_t max_update_size)
217{
218 gensec_security->max_update_size = max_update_size;
219}
220
221_PUBLIC_ size_t gensec_max_update_size(struct gensec_security *gensec_security)
222{
223 if (gensec_security->max_update_size == 0) {
224 return UINT32_MAX;
225 }
226
227 return gensec_security->max_update_size;
228}
229
230static NTSTATUS gensec_verify_dcerpc_auth_level(struct gensec_security *gensec_security)
231{
232 if (gensec_security->dcerpc_auth_level == 0) {
233 return NT_STATUS_OK;
234 }
235
236 /*
237 * Because callers using the
238 * gensec_start_mech_by_auth_type() never call
239 * gensec_want_feature(), it isn't sensible for them
240 * to have to call gensec_have_feature() manually, and
241 * these are not points of negotiation, but are
242 * asserted by the client
243 */
244 switch (gensec_security->dcerpc_auth_level) {
245 case DCERPC_AUTH_LEVEL_INTEGRITY:
246 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
247 DEBUG(0,("Did not manage to negotiate mandetory feature "
248 "SIGN for dcerpc auth_level %u\n",
249 gensec_security->dcerpc_auth_level));
250 return NT_STATUS_ACCESS_DENIED;
251 }
252 break;
253 case DCERPC_AUTH_LEVEL_PRIVACY:
254 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
255 DEBUG(0,("Did not manage to negotiate mandetory feature "
256 "SIGN for dcerpc auth_level %u\n",
257 gensec_security->dcerpc_auth_level));
258 return NT_STATUS_ACCESS_DENIED;
259 }
260 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
261 DEBUG(0,("Did not manage to negotiate mandetory feature "
262 "SEAL for dcerpc auth_level %u\n",
263 gensec_security->dcerpc_auth_level));
264 return NT_STATUS_ACCESS_DENIED;
265 }
266 break;
267 default:
268 break;
269 }
270
271 return NT_STATUS_OK;
272}
273
274_PUBLIC_ NTSTATUS gensec_update_ev(struct gensec_security *gensec_security,
275 TALLOC_CTX *out_mem_ctx,
276 struct tevent_context *ev,
277 const DATA_BLOB in, DATA_BLOB *out)
278{
279 NTSTATUS status;
280 const struct gensec_security_ops *ops = gensec_security->ops;
281 TALLOC_CTX *frame = NULL;
282 struct tevent_req *subreq = NULL;
283 bool ok;
284
285 if (ops->update_send == NULL) {
286
287 if (ev == NULL) {
288 frame = talloc_stackframe();
289
290 ev = samba_tevent_context_init(frame);
291 if (ev == NULL) {
292 status = NT_STATUS_NO_MEMORY;
293 goto fail;
294 }
295
296 /*
297 * TODO: remove this hack once the backends
298 * are fixed.
299 */
300 tevent_loop_allow_nesting(ev);
301 }
302
303 status = ops->update(gensec_security, out_mem_ctx,
304 ev, in, out);
305 TALLOC_FREE(frame);
306 if (!NT_STATUS_IS_OK(status)) {
307 return status;
308 }
309
310 /*
311 * Because callers using the
312 * gensec_start_mech_by_auth_type() never call
313 * gensec_want_feature(), it isn't sensible for them
314 * to have to call gensec_have_feature() manually, and
315 * these are not points of negotiation, but are
316 * asserted by the client
317 */
318 status = gensec_verify_dcerpc_auth_level(gensec_security);
319 if (!NT_STATUS_IS_OK(status)) {
320 return status;
321 }
322
323 return NT_STATUS_OK;
324 }
325
326 frame = talloc_stackframe();
327
328 if (ev == NULL) {
329 ev = samba_tevent_context_init(frame);
330 if (ev == NULL) {
331 status = NT_STATUS_NO_MEMORY;
332 goto fail;
333 }
334
335 /*
336 * TODO: remove this hack once the backends
337 * are fixed.
338 */
339 tevent_loop_allow_nesting(ev);
340 }
341
342 subreq = ops->update_send(frame, ev, gensec_security, in);
343 if (subreq == NULL) {
344 status = NT_STATUS_NO_MEMORY;
345 goto fail;
346 }
347 ok = tevent_req_poll_ntstatus(subreq, ev, &status);
348 if (!ok) {
349 goto fail;
350 }
351 status = ops->update_recv(subreq, out_mem_ctx, out);
352 fail:
353 TALLOC_FREE(frame);
354 return status;
355}
356
357/**
358 * Next state function for the GENSEC state machine
359 *
360 * @param gensec_security GENSEC State
361 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
362 * @param in The request, as a DATA_BLOB
363 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
364 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
365 * or NT_STATUS_OK if the user is authenticated.
366 */
367
368_PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security,
369 TALLOC_CTX *out_mem_ctx,
370 const DATA_BLOB in, DATA_BLOB *out)
371{
372 return gensec_update_ev(gensec_security, out_mem_ctx, NULL, in, out);
373}
374
375struct gensec_update_state {
376 const struct gensec_security_ops *ops;
377 struct tevent_req *subreq;
378 struct gensec_security *gensec_security;
379 DATA_BLOB out;
380
381 /*
382 * only for sync backends, we should remove this
383 * once all backends are async.
384 */
385 struct tevent_immediate *im;
386 DATA_BLOB in;
387};
388
389static void gensec_update_async_trigger(struct tevent_context *ctx,
390 struct tevent_immediate *im,
391 void *private_data);
392static void gensec_update_subreq_done(struct tevent_req *subreq);
393
394/**
395 * Next state function for the GENSEC state machine async version
396 *
397 * @param mem_ctx The memory context for the request
398 * @param ev The event context for the request
399 * @param gensec_security GENSEC State
400 * @param in The request, as a DATA_BLOB
401 *
402 * @return The request handle or NULL on no memory failure
403 */
404
405_PUBLIC_ struct tevent_req *gensec_update_send(TALLOC_CTX *mem_ctx,
406 struct tevent_context *ev,
407 struct gensec_security *gensec_security,
408 const DATA_BLOB in)
409{
410 struct tevent_req *req;
411 struct gensec_update_state *state = NULL;
412
413 req = tevent_req_create(mem_ctx, &state,
414 struct gensec_update_state);
415 if (req == NULL) {
416 return NULL;
417 }
418
419 state->ops = gensec_security->ops;
420 state->gensec_security = gensec_security;
421
422 if (state->ops->update_send == NULL) {
423 state->in = in;
424 state->im = tevent_create_immediate(state);
425 if (tevent_req_nomem(state->im, req)) {
426 return tevent_req_post(req, ev);
427 }
428
429 tevent_schedule_immediate(state->im, ev,
430 gensec_update_async_trigger,
431 req);
432
433 return req;
434 }
435
436 state->subreq = state->ops->update_send(state, ev, gensec_security, in);
437 if (tevent_req_nomem(state->subreq, req)) {
438 return tevent_req_post(req, ev);
439 }
440
441 tevent_req_set_callback(state->subreq,
442 gensec_update_subreq_done,
443 req);
444
445 return req;
446}
447
448static void gensec_update_async_trigger(struct tevent_context *ctx,
449 struct tevent_immediate *im,
450 void *private_data)
451{
452 struct tevent_req *req =
453 talloc_get_type_abort(private_data, struct tevent_req);
454 struct gensec_update_state *state =
455 tevent_req_data(req, struct gensec_update_state);
456 NTSTATUS status;
457
458 status = state->ops->update(state->gensec_security, state, ctx,
459 state->in, &state->out);
460 if (tevent_req_nterror(req, status)) {
461 return;
462 }
463
464 tevent_req_done(req);
465}
466
467static void gensec_update_subreq_done(struct tevent_req *subreq)
468{
469 struct tevent_req *req =
470 tevent_req_callback_data(subreq,
471 struct tevent_req);
472 struct gensec_update_state *state =
473 tevent_req_data(req,
474 struct gensec_update_state);
475 NTSTATUS status;
476
477 state->subreq = NULL;
478
479 status = state->ops->update_recv(subreq, state, &state->out);
480 TALLOC_FREE(subreq);
481 if (tevent_req_nterror(req, status)) {
482 return;
483 }
484
485 /*
486 * Because callers using the
487 * gensec_start_mech_by_authtype() never call
488 * gensec_want_feature(), it isn't sensible for them
489 * to have to call gensec_have_feature() manually, and
490 * these are not points of negotiation, but are
491 * asserted by the client
492 */
493 status = gensec_verify_dcerpc_auth_level(state->gensec_security);
494 if (tevent_req_nterror(req, status)) {
495 return;
496 }
497
498 tevent_req_done(req);
499}
500
501/**
502 * Next state function for the GENSEC state machine
503 *
504 * @param req request state
505 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
506 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
507 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
508 * or NT_STATUS_OK if the user is authenticated.
509 */
510_PUBLIC_ NTSTATUS gensec_update_recv(struct tevent_req *req,
511 TALLOC_CTX *out_mem_ctx,
512 DATA_BLOB *out)
513{
514 struct gensec_update_state *state =
515 tevent_req_data(req, struct gensec_update_state);
516 NTSTATUS status;
517
518 if (tevent_req_is_nterror(req, &status)) {
519 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
520 tevent_req_received(req);
521 return status;
522 }
523 } else {
524 status = NT_STATUS_OK;
525 }
526
527 *out = state->out;
528 talloc_steal(out_mem_ctx, out->data);
529
530 tevent_req_received(req);
531 return status;
532}
533
534/**
535 * Set the requirement for a certain feature on the connection
536 *
537 */
538
539_PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
540 uint32_t feature)
541{
542 if (!gensec_security->ops || !gensec_security->ops->want_feature) {
543 gensec_security->want_features |= feature;
544 return;
545 }
546 gensec_security->ops->want_feature(gensec_security, feature);
547}
548
549/**
550 * Check the requirement for a certain feature on the connection
551 *
552 */
553
554_PUBLIC_ bool gensec_have_feature(struct gensec_security *gensec_security,
555 uint32_t feature)
556{
557 if (!gensec_security->ops || !gensec_security->ops->have_feature) {
558 return false;
559 }
560
561 /* We might 'have' features that we don't 'want', because the
562 * other end demanded them, or we can't neotiate them off */
563 return gensec_security->ops->have_feature(gensec_security, feature);
564}
565
566_PUBLIC_ NTTIME gensec_expire_time(struct gensec_security *gensec_security)
567{
568 if (!gensec_security->ops->expire_time) {
569 return GENSEC_EXPIRE_TIME_INFINITY;
570 }
571
572 return gensec_security->ops->expire_time(gensec_security);
573}
574/**
575 * Return the credentials structure associated with a GENSEC context
576 *
577 */
578
579_PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
580{
581 if (!gensec_security) {
582 return NULL;
583 }
584 return gensec_security->credentials;
585}
586
587/**
588 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
589 *
590 */
591
592_PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
593{
594 gensec_security->target.service = talloc_strdup(gensec_security, service);
595 if (!gensec_security->target.service) {
596 return NT_STATUS_NO_MEMORY;
597 }
598 return NT_STATUS_OK;
599}
600
601_PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security)
602{
603 if (gensec_security->target.service) {
604 return gensec_security->target.service;
605 }
606
607 return "host";
608}
609
610/**
611 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
612 *
613 */
614
615_PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
616{
617 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
618 if (hostname && !gensec_security->target.hostname) {
619 return NT_STATUS_NO_MEMORY;
620 }
621 return NT_STATUS_OK;
622}
623
624_PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
625{
626 /* We allow the target hostname to be overriden for testing purposes */
627 if (gensec_security->settings->target_hostname) {
628 return gensec_security->settings->target_hostname;
629 }
630
631 if (gensec_security->target.hostname) {
632 return gensec_security->target.hostname;
633 }
634
635 /* We could add use the 'set sockaddr' call, and do a reverse
636 * lookup, but this would be both insecure (compromising the
637 * way kerberos works) and add DNS timeouts */
638 return NULL;
639}
640
641/**
642 * Set (and copy) local and peer socket addresses onto a socket
643 * context on the GENSEC context.
644 *
645 * This is so that kerberos can include these addresses in
646 * cryptographic tokens, to avoid certain attacks.
647 */
648
649/**
650 * @brief Set the local gensec address.
651 *
652 * @param gensec_security The gensec security context to use.
653 *
654 * @param remote The local address to set.
655 *
656 * @return On success NT_STATUS_OK is returned or an NT_STATUS
657 * error.
658 */
659_PUBLIC_ NTSTATUS gensec_set_local_address(struct gensec_security *gensec_security,
660 const struct tsocket_address *local)
661{
662 TALLOC_FREE(gensec_security->local_addr);
663
664 if (local == NULL) {
665 return NT_STATUS_OK;
666 }
667
668 gensec_security->local_addr = tsocket_address_copy(local, gensec_security);
669 if (gensec_security->local_addr == NULL) {
670 return NT_STATUS_NO_MEMORY;
671 }
672
673 return NT_STATUS_OK;
674}
675
676/**
677 * @brief Set the remote gensec address.
678 *
679 * @param gensec_security The gensec security context to use.
680 *
681 * @param remote The remote address to set.
682 *
683 * @return On success NT_STATUS_OK is returned or an NT_STATUS
684 * error.
685 */
686_PUBLIC_ NTSTATUS gensec_set_remote_address(struct gensec_security *gensec_security,
687 const struct tsocket_address *remote)
688{
689 TALLOC_FREE(gensec_security->remote_addr);
690
691 if (remote == NULL) {
692 return NT_STATUS_OK;
693 }
694
695 gensec_security->remote_addr = tsocket_address_copy(remote, gensec_security);
696 if (gensec_security->remote_addr == NULL) {
697 return NT_STATUS_NO_MEMORY;
698 }
699
700 return NT_STATUS_OK;
701}
702
703/**
704 * @brief Get the local address from a gensec security context.
705 *
706 * @param gensec_security The security context to get the address from.
707 *
708 * @return The address as tsocket_address which could be NULL if
709 * no address is set.
710 */
711_PUBLIC_ const struct tsocket_address *gensec_get_local_address(struct gensec_security *gensec_security)
712{
713 if (gensec_security == NULL) {
714 return NULL;
715 }
716 return gensec_security->local_addr;
717}
718
719/**
720 * @brief Get the remote address from a gensec security context.
721 *
722 * @param gensec_security The security context to get the address from.
723 *
724 * @return The address as tsocket_address which could be NULL if
725 * no address is set.
726 */
727_PUBLIC_ const struct tsocket_address *gensec_get_remote_address(struct gensec_security *gensec_security)
728{
729 if (gensec_security == NULL) {
730 return NULL;
731 }
732 return gensec_security->remote_addr;
733}
734
735/**
736 * Set the target principal (assuming it it known, say from the SPNEGO reply)
737 * - ensures it is talloc()ed
738 *
739 */
740
741_PUBLIC_ NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
742{
743 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
744 if (!gensec_security->target.principal) {
745 return NT_STATUS_NO_MEMORY;
746 }
747 return NT_STATUS_OK;
748}
749
750_PUBLIC_ const char *gensec_get_target_principal(struct gensec_security *gensec_security)
751{
752 if (gensec_security->target.principal) {
753 return gensec_security->target.principal;
754 }
755
756 return NULL;
757}
Note: See TracBrowser for help on using the repository browser.