2a8bba8bc0bd138d6679ff837a06b116850688c3
[sharpe/samba-autobuild/.git] / auth / gensec / gensec.c
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
230 static 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
375 struct 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
389 static void gensec_update_async_trigger(struct tevent_context *ctx,
390                                         struct tevent_immediate *im,
391                                         void *private_data);
392 static 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
448 static 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
467 static 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 }