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