root/source4/auth/gensec/gensec_gssapi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gssapi_error_string
  2. gensec_gssapi_destructor
  3. gensec_gssapi_init_lucid
  4. gensec_gssapi_start
  5. gensec_gssapi_server_start
  6. gensec_gssapi_sasl_server_start
  7. gensec_gssapi_client_start
  8. gensec_gssapi_sasl_client_start
  9. gensec_gssapi_magic
  10. gensec_gssapi_update
  11. gensec_gssapi_wrap
  12. gensec_gssapi_unwrap
  13. gensec_gssapi_max_input_size
  14. gensec_gssapi_max_wrapped_size
  15. gensec_gssapi_seal_packet
  16. gensec_gssapi_unseal_packet
  17. gensec_gssapi_sign_packet
  18. gensec_gssapi_check_packet
  19. gensec_gssapi_have_feature
  20. gensec_gssapi_session_key
  21. gensec_gssapi_session_info
  22. gensec_gssapi_sig_size
  23. gensec_gssapi_init

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    Kerberos backend for GENSEC
   5    
   6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
   7    Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
   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    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "lib/events/events.h"
  26 #include "system/kerberos.h"
  27 #include "auth/kerberos/kerberos.h"
  28 #include "librpc/gen_ndr/krb5pac.h"
  29 #include "auth/auth.h"
  30 #include "lib/ldb/include/ldb.h"
  31 #include "auth/auth_sam.h"
  32 #include "librpc/rpc/dcerpc.h"
  33 #include "auth/credentials/credentials.h"
  34 #include "auth/credentials/credentials_krb5.h"
  35 #include "auth/gensec/gensec.h"
  36 #include "auth/gensec/gensec_proto.h"
  37 #include "param/param.h"
  38 #include "auth/session_proto.h"
  39 #include <gssapi/gssapi.h>
  40 #include <gssapi/gssapi_krb5.h>
  41 #include "auth/gensec/gensec_gssapi.h"
  42 
  43 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
  44 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security);
  45 
  46 static char *gssapi_error_string(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
  47                                  OM_uint32 maj_stat, OM_uint32 min_stat, 
  48                                  const gss_OID mech)
  49 {
  50         OM_uint32 disp_min_stat, disp_maj_stat;
  51         gss_buffer_desc maj_error_message;
  52         gss_buffer_desc min_error_message;
  53         char *maj_error_string, *min_error_string;
  54         OM_uint32 msg_ctx = 0;
  55 
  56         char *ret;
  57 
  58         maj_error_message.value = NULL;
  59         min_error_message.value = NULL;
  60         maj_error_message.length = 0;
  61         min_error_message.length = 0;
  62         
  63         disp_maj_stat = gss_display_status(&disp_min_stat, maj_stat, GSS_C_GSS_CODE,
  64                            mech, &msg_ctx, &maj_error_message);
  65         disp_maj_stat = gss_display_status(&disp_min_stat, min_stat, GSS_C_MECH_CODE,
  66                            mech, &msg_ctx, &min_error_message);
  67         
  68         maj_error_string = talloc_strndup(mem_ctx, (char *)maj_error_message.value, maj_error_message.length);
  69 
  70         min_error_string = talloc_strndup(mem_ctx, (char *)min_error_message.value, min_error_message.length);
  71 
  72         ret = talloc_asprintf(mem_ctx, "%s: %s", maj_error_string, min_error_string);
  73 
  74         talloc_free(maj_error_string);
  75         talloc_free(min_error_string);
  76 
  77         gss_release_buffer(&disp_min_stat, &maj_error_message);
  78         gss_release_buffer(&disp_min_stat, &min_error_message);
  79 
  80         return ret;
  81 }
  82 
  83 
  84 static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
     /* [<][>][^][v][top][bottom][index][help] */
  85 {
  86         OM_uint32 maj_stat, min_stat;
  87         
  88         if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
  89                 maj_stat = gss_release_cred(&min_stat, 
  90                                             &gensec_gssapi_state->delegated_cred_handle);
  91         }
  92 
  93         if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
  94                 maj_stat = gss_delete_sec_context (&min_stat,
  95                                                    &gensec_gssapi_state->gssapi_context,
  96                                                    GSS_C_NO_BUFFER);
  97         }
  98 
  99         if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
 100                 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->server_name);
 101         }
 102         if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
 103                 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->client_name);
 104         }
 105 
 106         if (gensec_gssapi_state->lucid) {
 107                 gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
 108         }
 109 
 110         return 0;
 111 }
 112 
 113 static NTSTATUS gensec_gssapi_init_lucid(struct gensec_gssapi_state *gensec_gssapi_state)
     /* [<][>][^][v][top][bottom][index][help] */
 114 {
 115         OM_uint32 maj_stat, min_stat;
 116 
 117         if (gensec_gssapi_state->lucid) {
 118                 return NT_STATUS_OK;
 119         }
 120 
 121         maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
 122                                                      &gensec_gssapi_state->gssapi_context,
 123                                                      1,
 124                                                      (void **)&gensec_gssapi_state->lucid);
 125         if (maj_stat != GSS_S_COMPLETE) {
 126                 DEBUG(0,("gensec_gssapi_init_lucid: %s\n",
 127                         gssapi_error_string(gensec_gssapi_state,
 128                                             maj_stat, min_stat,
 129                                             gensec_gssapi_state->gss_oid)));
 130                 return NT_STATUS_INTERNAL_ERROR;
 131         }
 132 
 133         if (gensec_gssapi_state->lucid->version != 1) {
 134                 DEBUG(0,("gensec_gssapi_init_lucid: lucid version[%d] != 1\n",
 135                         gensec_gssapi_state->lucid->version));
 136                 gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
 137                 gensec_gssapi_state->lucid = NULL;
 138                 return NT_STATUS_INTERNAL_ERROR;
 139         }
 140 
 141         return NT_STATUS_OK;
 142 }
 143 
 144 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
     /* [<][>][^][v][top][bottom][index][help] */
 145 {
 146         struct gensec_gssapi_state *gensec_gssapi_state;
 147         krb5_error_code ret;
 148         struct gsskrb5_send_to_kdc send_to_kdc;
 149 
 150         gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state);
 151         if (!gensec_gssapi_state) {
 152                 return NT_STATUS_NO_MEMORY;
 153         }
 154         
 155         gensec_gssapi_state->gss_exchange_count = 0;
 156         gensec_gssapi_state->max_wrap_buf_size
 157                 = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
 158                 
 159         gensec_gssapi_state->sasl = false;
 160         gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
 161 
 162         gensec_security->private_data = gensec_gssapi_state;
 163 
 164         gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
 165         gensec_gssapi_state->server_name = GSS_C_NO_NAME;
 166         gensec_gssapi_state->client_name = GSS_C_NO_NAME;
 167         gensec_gssapi_state->lucid = NULL;
 168 
 169         /* TODO: Fill in channel bindings */
 170         gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
 171         
 172         gensec_gssapi_state->want_flags = 0;
 173         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
 174                 gensec_gssapi_state->want_flags |= GSS_C_MUTUAL_FLAG;
 175         }
 176         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", true)) {
 177                 gensec_gssapi_state->want_flags |= GSS_C_DELEG_FLAG;
 178         }
 179         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
 180                 gensec_gssapi_state->want_flags |= GSS_C_REPLAY_FLAG;
 181         }
 182         if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
 183                 gensec_gssapi_state->want_flags |= GSS_C_SEQUENCE_FLAG;
 184         }
 185 
 186         gensec_gssapi_state->got_flags = 0;
 187 
 188         gensec_gssapi_state->session_key = data_blob(NULL, 0);
 189         gensec_gssapi_state->pac = data_blob(NULL, 0);
 190 
 191         gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
 192         gensec_gssapi_state->sig_size = 0;
 193 
 194         talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
 195 
 196         if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
 197                 gensec_gssapi_state->want_flags |= GSS_C_INTEG_FLAG;
 198         }
 199         if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
 200                 gensec_gssapi_state->want_flags |= GSS_C_CONF_FLAG;
 201         }
 202         if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
 203                 gensec_gssapi_state->want_flags |= GSS_C_DCE_STYLE;
 204         }
 205 
 206         gensec_gssapi_state->gss_oid = GSS_C_NULL_OID;
 207         
 208         send_to_kdc.func = smb_krb5_send_and_recv_func;
 209         send_to_kdc.ptr = gensec_security->event_ctx;
 210 
 211         ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
 212         if (ret) {
 213                 DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n"));
 214                 talloc_free(gensec_gssapi_state);
 215                 return NT_STATUS_INTERNAL_ERROR;
 216         }
 217         if (lp_realm(gensec_security->settings->lp_ctx) && *lp_realm(gensec_security->settings->lp_ctx)) {
 218                 char *upper_realm = strupper_talloc(gensec_gssapi_state, lp_realm(gensec_security->settings->lp_ctx));
 219                 if (!upper_realm) {
 220                         DEBUG(1,("gensec_krb5_start: could not uppercase realm: %s\n", lp_realm(gensec_security->settings->lp_ctx)));
 221                         talloc_free(gensec_gssapi_state);
 222                         return NT_STATUS_NO_MEMORY;
 223                 }
 224                 ret = gsskrb5_set_default_realm(upper_realm);
 225                 talloc_free(upper_realm);
 226                 if (ret) {
 227                         DEBUG(1,("gensec_krb5_start: gsskrb5_set_default_realm failed\n"));
 228                         talloc_free(gensec_gssapi_state);
 229                         return NT_STATUS_INTERNAL_ERROR;
 230                 }
 231         }
 232 
 233         /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
 234         ret = gsskrb5_set_dns_canonicalize(gensec_setting_bool(gensec_security->settings, "krb5", "set_dns_canonicalize", false));
 235         if (ret) {
 236                 DEBUG(1,("gensec_krb5_start: gsskrb5_set_dns_canonicalize failed\n"));
 237                 talloc_free(gensec_gssapi_state);
 238                 return NT_STATUS_INTERNAL_ERROR;
 239         }
 240 
 241         ret = smb_krb5_init_context(gensec_gssapi_state, 
 242                                     gensec_security->event_ctx,
 243                                     gensec_security->settings->lp_ctx,
 244                                     &gensec_gssapi_state->smb_krb5_context);
 245         if (ret) {
 246                 DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
 247                          error_message(ret)));
 248                 talloc_free(gensec_gssapi_state);
 249                 return NT_STATUS_INTERNAL_ERROR;
 250         }
 251         return NT_STATUS_OK;
 252 }
 253 
 254 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
     /* [<][>][^][v][top][bottom][index][help] */
 255 {
 256         NTSTATUS nt_status;
 257         int ret;
 258         struct gensec_gssapi_state *gensec_gssapi_state;
 259         struct cli_credentials *machine_account;
 260         struct gssapi_creds_container *gcc;
 261 
 262         nt_status = gensec_gssapi_start(gensec_security);
 263         if (!NT_STATUS_IS_OK(nt_status)) {
 264                 return nt_status;
 265         }
 266 
 267         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 268 
 269         machine_account = gensec_get_credentials(gensec_security);
 270         
 271         if (!machine_account) {
 272                 DEBUG(3, ("No machine account credentials specified\n"));
 273                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 274         } else {
 275                 ret = cli_credentials_get_server_gss_creds(machine_account, 
 276                                                            gensec_security->event_ctx, 
 277                                                            gensec_security->settings->lp_ctx, &gcc);
 278                 if (ret) {
 279                         DEBUG(1, ("Aquiring acceptor credentials failed: %s\n", 
 280                                   error_message(ret)));
 281                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 282                 }
 283         }
 284 
 285         gensec_gssapi_state->server_cred = gcc;
 286         return NT_STATUS_OK;
 287 
 288 }
 289 
 290 static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
     /* [<][>][^][v][top][bottom][index][help] */
 291 {
 292         NTSTATUS nt_status;
 293         struct gensec_gssapi_state *gensec_gssapi_state;
 294         nt_status = gensec_gssapi_server_start(gensec_security);
 295 
 296         if (NT_STATUS_IS_OK(nt_status)) {
 297                 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 298                 gensec_gssapi_state->sasl = true;
 299         }
 300         return nt_status;
 301 }
 302 
 303 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
     /* [<][>][^][v][top][bottom][index][help] */
 304 {
 305         struct gensec_gssapi_state *gensec_gssapi_state;
 306         struct cli_credentials *creds = gensec_get_credentials(gensec_security);
 307         krb5_error_code ret;
 308         NTSTATUS nt_status;
 309         gss_buffer_desc name_token;
 310         gss_OID name_type;
 311         OM_uint32 maj_stat, min_stat;
 312         const char *hostname = gensec_get_target_hostname(gensec_security);
 313         const char *principal;
 314         struct gssapi_creds_container *gcc;
 315 
 316         if (!hostname) {
 317                 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
 318                 return NT_STATUS_INVALID_PARAMETER;
 319         }
 320         if (is_ipaddress(hostname)) {
 321                 DEBUG(2, ("Cannot do GSSAPI to an IP address\n"));
 322                 return NT_STATUS_INVALID_PARAMETER;
 323         }
 324         if (strcmp(hostname, "localhost") == 0) {
 325                 DEBUG(2, ("GSSAPI to 'localhost' does not make sense\n"));
 326                 return NT_STATUS_INVALID_PARAMETER;
 327         }
 328 
 329         nt_status = gensec_gssapi_start(gensec_security);
 330         if (!NT_STATUS_IS_OK(nt_status)) {
 331                 return nt_status;
 332         }
 333 
 334         gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 335 
 336         gensec_gssapi_state->gss_oid = gss_mech_krb5;
 337 
 338         principal = gensec_get_target_principal(gensec_security);
 339         if (principal && lp_client_use_spnego_principal(gensec_security->settings->lp_ctx)) {
 340                 name_type = GSS_C_NULL_OID;
 341         } else {
 342                 principal = talloc_asprintf(gensec_gssapi_state, "%s@%s", 
 343                                             gensec_get_target_service(gensec_security), 
 344                                             hostname);
 345 
 346                 name_type = GSS_C_NT_HOSTBASED_SERVICE;
 347         }               
 348         name_token.value  = discard_const_p(uint8_t, principal);
 349         name_token.length = strlen(principal);
 350 
 351 
 352         maj_stat = gss_import_name (&min_stat,
 353                                     &name_token,
 354                                     name_type,
 355                                     &gensec_gssapi_state->server_name);
 356         if (maj_stat) {
 357                 DEBUG(2, ("GSS Import name of %s failed: %s\n",
 358                           (char *)name_token.value,
 359                           gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 360                 return NT_STATUS_INVALID_PARAMETER;
 361         }
 362 
 363         ret = cli_credentials_get_client_gss_creds(creds, 
 364                                                    gensec_security->event_ctx, 
 365                                                    gensec_security->settings->lp_ctx, &gcc);
 366         switch (ret) {
 367         case 0:
 368                 break;
 369         case KRB5KDC_ERR_PREAUTH_FAILED:
 370                 return NT_STATUS_LOGON_FAILURE;
 371         case KRB5_KDC_UNREACH:
 372                 DEBUG(3, ("Cannot reach a KDC we require to contact %s\n", principal));
 373                 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 374         default:
 375                 DEBUG(1, ("Aquiring initiator credentials failed\n"));
 376                 return NT_STATUS_UNSUCCESSFUL;
 377         }
 378 
 379         gensec_gssapi_state->client_cred = gcc;
 380         if (!talloc_reference(gensec_gssapi_state, gcc)) {
 381                 return NT_STATUS_NO_MEMORY;
 382         }
 383         
 384         return NT_STATUS_OK;
 385 }
 386 
 387 static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
     /* [<][>][^][v][top][bottom][index][help] */
 388 {
 389         NTSTATUS nt_status;
 390         struct gensec_gssapi_state *gensec_gssapi_state;
 391         nt_status = gensec_gssapi_client_start(gensec_security);
 392 
 393         if (NT_STATUS_IS_OK(nt_status)) {
 394                 gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 395                 gensec_gssapi_state->sasl = true;
 396         }
 397         return nt_status;
 398 }
 399 
 400 
 401 /**
 402  * Check if the packet is one for this mechansim
 403  * 
 404  * @param gensec_security GENSEC state
 405  * @param in The request, as a DATA_BLOB
 406  * @return Error, INVALID_PARAMETER if it's not a packet for us
 407  *                or NT_STATUS_OK if the packet is ok. 
 408  */
 409 
 410 static NTSTATUS gensec_gssapi_magic(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 411                                     const DATA_BLOB *in) 
 412 {
 413         if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
 414                 return NT_STATUS_OK;
 415         } else {
 416                 return NT_STATUS_INVALID_PARAMETER;
 417         }
 418 }
 419 
 420 
 421 /**
 422  * Next state function for the GSSAPI GENSEC mechanism
 423  * 
 424  * @param gensec_gssapi_state GSSAPI State
 425  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
 426  * @param in The request, as a DATA_BLOB
 427  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
 428  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
 429  *                or NT_STATUS_OK if the user is authenticated. 
 430  */
 431 
 432 static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 433                                    TALLOC_CTX *out_mem_ctx, 
 434                                    const DATA_BLOB in, DATA_BLOB *out) 
 435 {
 436         struct gensec_gssapi_state *gensec_gssapi_state
 437                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 438         NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
 439         OM_uint32 maj_stat, min_stat;
 440         OM_uint32 min_stat2;
 441         gss_buffer_desc input_token, output_token;
 442         gss_OID gss_oid_p = NULL;
 443         input_token.length = in.length;
 444         input_token.value = in.data;
 445 
 446         switch (gensec_gssapi_state->sasl_state) {
 447         case STAGE_GSS_NEG:
 448         {
 449                 switch (gensec_security->gensec_role) {
 450                 case GENSEC_CLIENT:
 451                 {
 452                         maj_stat = gss_init_sec_context(&min_stat, 
 453                                                         gensec_gssapi_state->client_cred->creds,
 454                                                         &gensec_gssapi_state->gssapi_context, 
 455                                                         gensec_gssapi_state->server_name, 
 456                                                         gensec_gssapi_state->gss_oid,
 457                                                         gensec_gssapi_state->want_flags, 
 458                                                         0, 
 459                                                         gensec_gssapi_state->input_chan_bindings,
 460                                                         &input_token, 
 461                                                         &gss_oid_p,
 462                                                         &output_token, 
 463                                                         &gensec_gssapi_state->got_flags, /* ret flags */
 464                                                         NULL);
 465                         if (gss_oid_p) {
 466                                 gensec_gssapi_state->gss_oid = gss_oid_p;
 467                         }
 468                         break;
 469                 }
 470                 case GENSEC_SERVER:
 471                 {
 472                         maj_stat = gss_accept_sec_context(&min_stat, 
 473                                                           &gensec_gssapi_state->gssapi_context, 
 474                                                           gensec_gssapi_state->server_cred->creds,
 475                                                           &input_token, 
 476                                                           gensec_gssapi_state->input_chan_bindings,
 477                                                           &gensec_gssapi_state->client_name, 
 478                                                           &gss_oid_p,
 479                                                           &output_token, 
 480                                                           &gensec_gssapi_state->got_flags, 
 481                                                           NULL, 
 482                                                           &gensec_gssapi_state->delegated_cred_handle);
 483                         if (gss_oid_p) {
 484                                 gensec_gssapi_state->gss_oid = gss_oid_p;
 485                         }
 486                         break;
 487                 }
 488                 default:
 489                         return NT_STATUS_INVALID_PARAMETER;
 490                         
 491                 }
 492 
 493                 gensec_gssapi_state->gss_exchange_count++;
 494 
 495                 if (maj_stat == GSS_S_COMPLETE) {
 496                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 497                         gss_release_buffer(&min_stat2, &output_token);
 498                         
 499                         if (gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG) {
 500                                 DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
 501                         } else {
 502                                 DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
 503                         }
 504 
 505                         /* We may have been invoked as SASL, so there
 506                          * is more work to do */
 507                         if (gensec_gssapi_state->sasl) {
 508                                 /* Due to a very subtle interaction
 509                                  * with SASL and the LDAP libs, we
 510                                  * must ensure the data pointer is 
 511                                  * != NULL, but the length is 0.  
 512                                  *
 513                                  * This ensures we send a 'zero
 514                                  * length' (rather than NULL) response 
 515                                  */
 516                                 
 517                                 if (!out->data) {
 518                                         out->data = (uint8_t *)talloc_strdup(out_mem_ctx, "\0");
 519                                 }
 520 
 521                                 gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
 522                                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
 523                         } else {
 524                                 gensec_gssapi_state->sasl_state = STAGE_DONE;
 525 
 526                                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 527                                         DEBUG(5, ("GSSAPI Connection will be cryptographicly sealed\n"));
 528                                 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 529                                         DEBUG(5, ("GSSAPI Connection will be cryptographicly signed\n"));
 530                                 } else {
 531                                         DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
 532                                 }
 533 
 534                                 return NT_STATUS_OK;
 535                         }
 536                 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
 537                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 538                         gss_release_buffer(&min_stat2, &output_token);
 539                         
 540                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
 541                 } else if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
 542                         switch (min_stat) {
 543                         case KRB5_KDC_UNREACH:
 544                                 DEBUG(3, ("Cannot reach a KDC we require: %s\n",
 545                                           gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 546                                 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 547                         case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
 548                                 DEBUG(3, ("Server is not registered with our KDC: %s\n", 
 549                                           gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 550                                 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 551                         case KRB5KRB_AP_ERR_MSG_TYPE:
 552                                 /* garbage input, possibly from the auto-mech detection */
 553                                 return NT_STATUS_INVALID_PARAMETER;
 554                         default:
 555                                 DEBUG(1, ("GSS Update(krb5)(%d) Update failed: %s\n", 
 556                                           gensec_gssapi_state->gss_exchange_count,
 557                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 558                                 return nt_status;
 559                         }
 560                 } else {
 561                         DEBUG(1, ("GSS Update(%d) failed: %s\n", 
 562                                   gensec_gssapi_state->gss_exchange_count,
 563                                   gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 564                         return nt_status;
 565                 }
 566                 break;
 567         }
 568 
 569         /* These last two stages are only done if we were invoked as SASL */
 570         case STAGE_SASL_SSF_NEG:
 571         {
 572                 switch (gensec_security->gensec_role) {
 573                 case GENSEC_CLIENT:
 574                 {
 575                         uint8_t maxlength_proposed[4]; 
 576                         uint8_t maxlength_accepted[4]; 
 577                         uint8_t security_supported;
 578                         int conf_state;
 579                         gss_qop_t qop_state;
 580                         input_token.length = in.length;
 581                         input_token.value = in.data;
 582 
 583                         /* As a client, we have just send a
 584                          * zero-length blob to the server (after the
 585                          * normal GSSAPI exchange), and it has replied
 586                          * with it's SASL negotiation */
 587                         
 588                         maj_stat = gss_unwrap(&min_stat, 
 589                                               gensec_gssapi_state->gssapi_context, 
 590                                               &input_token,
 591                                               &output_token, 
 592                                               &conf_state,
 593                                               &qop_state);
 594                         if (GSS_ERROR(maj_stat)) {
 595                                 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
 596                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 597                                 return NT_STATUS_ACCESS_DENIED;
 598                         }
 599                         
 600                         if (output_token.length < 4) {
 601                                 return NT_STATUS_INVALID_PARAMETER;
 602                         }
 603 
 604                         memcpy(maxlength_proposed, output_token.value, 4);
 605                         gss_release_buffer(&min_stat, &output_token);
 606 
 607                         /* first byte is the proposed security */
 608                         security_supported = maxlength_proposed[0];
 609                         maxlength_proposed[0] = '\0';
 610                         
 611                         /* Rest is the proposed max wrap length */
 612                         gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0), 
 613                                                                      gensec_gssapi_state->max_wrap_buf_size);
 614                         gensec_gssapi_state->sasl_protection = 0;
 615                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 616                                 if (security_supported & NEG_SEAL) {
 617                                         gensec_gssapi_state->sasl_protection |= NEG_SEAL;
 618                                 }
 619                         } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 620                                 if (security_supported & NEG_SIGN) {
 621                                         gensec_gssapi_state->sasl_protection |= NEG_SIGN;
 622                                 }
 623                         } else if (security_supported & NEG_NONE) {
 624                                 gensec_gssapi_state->sasl_protection |= NEG_NONE;
 625                         } else {
 626                                 DEBUG(1, ("Remote server does not support unprotected connections"));
 627                                 return NT_STATUS_ACCESS_DENIED;
 628                         }
 629 
 630                         /* Send back the negotiated max length */
 631 
 632                         RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
 633 
 634                         maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
 635                         
 636                         input_token.value = maxlength_accepted;
 637                         input_token.length = sizeof(maxlength_accepted);
 638 
 639                         maj_stat = gss_wrap(&min_stat, 
 640                                             gensec_gssapi_state->gssapi_context, 
 641                                             false,
 642                                             GSS_C_QOP_DEFAULT,
 643                                             &input_token,
 644                                             &conf_state,
 645                                             &output_token);
 646                         if (GSS_ERROR(maj_stat)) {
 647                                 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
 648                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 649                                 return NT_STATUS_ACCESS_DENIED;
 650                         }
 651                         
 652                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 653                         gss_release_buffer(&min_stat, &output_token);
 654 
 655                         /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
 656                         gensec_gssapi_state->sasl_state = STAGE_DONE;
 657 
 658                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 659                                 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly sealed\n"));
 660                         } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 661                                 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly signed\n"));
 662                         } else {
 663                                 DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographicly protection\n"));
 664                         }
 665 
 666                         return NT_STATUS_OK;
 667                 }
 668                 case GENSEC_SERVER:
 669                 {
 670                         uint8_t maxlength_proposed[4]; 
 671                         uint8_t security_supported = 0x0;
 672                         int conf_state;
 673 
 674                         /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
 675                         if (in.length != 0) {
 676                                 DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
 677                         }
 678                         
 679                         /* Give the client some idea what we will support */
 680                           
 681                         RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
 682                         /* first byte is the proposed security */
 683                         maxlength_proposed[0] = '\0';
 684                         
 685                         gensec_gssapi_state->sasl_protection = 0;
 686                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 687                                 security_supported |= NEG_SEAL;
 688                         } 
 689                         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 690                                 security_supported |= NEG_SIGN;
 691                         }
 692                         if (security_supported == 0) {
 693                                 /* If we don't support anything, this must be 0 */
 694                                 RSIVAL(maxlength_proposed, 0, 0x0);
 695                         }
 696 
 697                         /* TODO:  We may not wish to support this */
 698                         security_supported |= NEG_NONE;
 699                         maxlength_proposed[0] = security_supported;
 700                         
 701                         input_token.value = maxlength_proposed;
 702                         input_token.length = sizeof(maxlength_proposed);
 703 
 704                         maj_stat = gss_wrap(&min_stat, 
 705                                             gensec_gssapi_state->gssapi_context, 
 706                                             false,
 707                                             GSS_C_QOP_DEFAULT,
 708                                             &input_token,
 709                                             &conf_state,
 710                                             &output_token);
 711                         if (GSS_ERROR(maj_stat)) {
 712                                 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
 713                                           gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 714                                 return NT_STATUS_ACCESS_DENIED;
 715                         }
 716                         
 717                         *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 718                         gss_release_buffer(&min_stat, &output_token);
 719 
 720                         gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
 721                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
 722                 }
 723                 default:
 724                         return NT_STATUS_INVALID_PARAMETER;
 725                         
 726                 }
 727         }
 728         /* This is s server-only stage */
 729         case STAGE_SASL_SSF_ACCEPT:
 730         {
 731                 uint8_t maxlength_accepted[4]; 
 732                 uint8_t security_accepted;
 733                 int conf_state;
 734                 gss_qop_t qop_state;
 735                 input_token.length = in.length;
 736                 input_token.value = in.data;
 737                         
 738                 maj_stat = gss_unwrap(&min_stat, 
 739                                       gensec_gssapi_state->gssapi_context, 
 740                                       &input_token,
 741                                       &output_token, 
 742                                       &conf_state,
 743                                       &qop_state);
 744                 if (GSS_ERROR(maj_stat)) {
 745                         DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
 746                                   gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 747                         return NT_STATUS_ACCESS_DENIED;
 748                 }
 749                         
 750                 if (output_token.length < 4) {
 751                         return NT_STATUS_INVALID_PARAMETER;
 752                 }
 753 
 754                 memcpy(maxlength_accepted, output_token.value, 4);
 755                 gss_release_buffer(&min_stat, &output_token);
 756                 
 757                 /* first byte is the proposed security */
 758                 security_accepted = maxlength_accepted[0];
 759                 maxlength_accepted[0] = '\0';
 760                 
 761                 /* Rest is the proposed max wrap length */
 762                 gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0), 
 763                                                              gensec_gssapi_state->max_wrap_buf_size);
 764 
 765                 gensec_gssapi_state->sasl_protection = 0;
 766                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 767                         if (security_accepted & NEG_SEAL) {
 768                                 gensec_gssapi_state->sasl_protection |= NEG_SEAL;
 769                         }
 770                 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 771                         if (security_accepted & NEG_SIGN) {
 772                                 gensec_gssapi_state->sasl_protection |= NEG_SIGN;
 773                         }
 774                 } else if (security_accepted & NEG_NONE) {
 775                         gensec_gssapi_state->sasl_protection |= NEG_NONE;
 776                 } else {
 777                         DEBUG(1, ("Remote client does not support unprotected connections, but we failed to negotiate anything better"));
 778                         return NT_STATUS_ACCESS_DENIED;
 779                 }
 780 
 781                 /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
 782                 gensec_gssapi_state->sasl_state = STAGE_DONE;
 783                 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 784                         DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly sealed\n"));
 785                 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 786                         DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly signed\n"));
 787                 } else {
 788                         DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
 789                 }
 790 
 791                 *out = data_blob(NULL, 0);
 792                 return NT_STATUS_OK;    
 793         }
 794         default:
 795                 return NT_STATUS_INVALID_PARAMETER;
 796         }
 797 }
 798 
 799 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 800                                    TALLOC_CTX *mem_ctx, 
 801                                    const DATA_BLOB *in, 
 802                                    DATA_BLOB *out)
 803 {
 804         struct gensec_gssapi_state *gensec_gssapi_state
 805                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 806         OM_uint32 maj_stat, min_stat;
 807         gss_buffer_desc input_token, output_token;
 808         int conf_state;
 809         input_token.length = in->length;
 810         input_token.value = in->data;
 811 
 812         maj_stat = gss_wrap(&min_stat, 
 813                             gensec_gssapi_state->gssapi_context, 
 814                             gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
 815                             GSS_C_QOP_DEFAULT,
 816                             &input_token,
 817                             &conf_state,
 818                             &output_token);
 819         if (GSS_ERROR(maj_stat)) {
 820                 DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", 
 821                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 822                 return NT_STATUS_ACCESS_DENIED;
 823         }
 824 
 825         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
 826         gss_release_buffer(&min_stat, &output_token);
 827 
 828         if (gensec_gssapi_state->sasl) {
 829                 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
 830                 if (max_wrapped_size < out->length) {
 831                         DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
 832                                   (unsigned)in->length, 
 833                                   (unsigned)out->length, 
 834                                   (unsigned int)max_wrapped_size));
 835                         return NT_STATUS_INVALID_PARAMETER;
 836                 }
 837         }
 838         
 839         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
 840             && !conf_state) {
 841                 return NT_STATUS_ACCESS_DENIED;
 842         }
 843         return NT_STATUS_OK;
 844 }
 845 
 846 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 847                                      TALLOC_CTX *mem_ctx, 
 848                                      const DATA_BLOB *in, 
 849                                      DATA_BLOB *out)
 850 {
 851         struct gensec_gssapi_state *gensec_gssapi_state
 852                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 853         OM_uint32 maj_stat, min_stat;
 854         gss_buffer_desc input_token, output_token;
 855         int conf_state;
 856         gss_qop_t qop_state;
 857         input_token.length = in->length;
 858         input_token.value = in->data;
 859         
 860         if (gensec_gssapi_state->sasl) {
 861                 size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
 862                 if (max_wrapped_size < in->length) {
 863                         DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
 864                         return NT_STATUS_INVALID_PARAMETER;
 865                 }
 866         }
 867         
 868         maj_stat = gss_unwrap(&min_stat, 
 869                               gensec_gssapi_state->gssapi_context, 
 870                               &input_token,
 871                               &output_token, 
 872                               &conf_state,
 873                               &qop_state);
 874         if (GSS_ERROR(maj_stat)) {
 875                 DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n", 
 876                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 877                 return NT_STATUS_ACCESS_DENIED;
 878         }
 879 
 880         *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
 881         gss_release_buffer(&min_stat, &output_token);
 882         
 883         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
 884             && !conf_state) {
 885                 return NT_STATUS_ACCESS_DENIED;
 886         }
 887         return NT_STATUS_OK;
 888 }
 889 
 890 /* Find out the maximum input size negotiated on this connection */
 891 
 892 static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
 893 {
 894         struct gensec_gssapi_state *gensec_gssapi_state
 895                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 896         OM_uint32 maj_stat, min_stat;
 897         OM_uint32 max_input_size;
 898 
 899         maj_stat = gss_wrap_size_limit(&min_stat, 
 900                                        gensec_gssapi_state->gssapi_context,
 901                                        gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
 902                                        GSS_C_QOP_DEFAULT,
 903                                        gensec_gssapi_state->max_wrap_buf_size,
 904                                        &max_input_size);
 905         if (GSS_ERROR(maj_stat)) {
 906                 TALLOC_CTX *mem_ctx = talloc_new(NULL); 
 907                 DEBUG(1, ("gensec_gssapi_max_input_size: determinaing signature size with gss_wrap_size_limit failed: %s\n", 
 908                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 909                 talloc_free(mem_ctx);
 910                 return 0;
 911         }
 912 
 913         return max_input_size;
 914 }
 915 
 916 /* Find out the maximum output size negotiated on this connection */
 917 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
 918 {
 919         struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
 920         return gensec_gssapi_state->max_wrap_buf_size;
 921 }
 922 
 923 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 924                                           TALLOC_CTX *mem_ctx, 
 925                                           uint8_t *data, size_t length, 
 926                                           const uint8_t *whole_pdu, size_t pdu_length, 
 927                                           DATA_BLOB *sig)
 928 {
 929         struct gensec_gssapi_state *gensec_gssapi_state
 930                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 931         OM_uint32 maj_stat, min_stat;
 932         gss_buffer_desc input_token, output_token;
 933         int conf_state;
 934         ssize_t sig_length;
 935 
 936         input_token.length = length;
 937         input_token.value = data;
 938         
 939         maj_stat = gss_wrap(&min_stat, 
 940                             gensec_gssapi_state->gssapi_context,
 941                             gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
 942                             GSS_C_QOP_DEFAULT,
 943                             &input_token,
 944                             &conf_state,
 945                             &output_token);
 946         if (GSS_ERROR(maj_stat)) {
 947                 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap failed: %s\n", 
 948                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 949                 return NT_STATUS_ACCESS_DENIED;
 950         }
 951 
 952         if (output_token.length < input_token.length) {
 953                 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%ld] *less* than caller length [%ld]\n", 
 954                           (long)output_token.length, (long)length));
 955                 return NT_STATUS_INTERNAL_ERROR;
 956         }
 957         sig_length = output_token.length - input_token.length;
 958 
 959         memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
 960         *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
 961 
 962         dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
 963         dump_data_pw("gensec_gssapi_seal_packet: clear\n", data, length);
 964         dump_data_pw("gensec_gssapi_seal_packet: sealed\n", ((uint8_t *)output_token.value) + sig_length, output_token.length - sig_length);
 965 
 966         gss_release_buffer(&min_stat, &output_token);
 967 
 968         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
 969             && !conf_state) {
 970                 return NT_STATUS_ACCESS_DENIED;
 971         }
 972         return NT_STATUS_OK;
 973 }
 974 
 975 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 976                                             TALLOC_CTX *mem_ctx, 
 977                                             uint8_t *data, size_t length, 
 978                                             const uint8_t *whole_pdu, size_t pdu_length,
 979                                             const DATA_BLOB *sig)
 980 {
 981         struct gensec_gssapi_state *gensec_gssapi_state
 982                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 983         OM_uint32 maj_stat, min_stat;
 984         gss_buffer_desc input_token, output_token;
 985         int conf_state;
 986         gss_qop_t qop_state;
 987         DATA_BLOB in;
 988 
 989         dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig->data, sig->length);
 990 
 991         in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
 992 
 993         memcpy(in.data, sig->data, sig->length);
 994         memcpy(in.data + sig->length, data, length);
 995 
 996         input_token.length = in.length;
 997         input_token.value = in.data;
 998         
 999         maj_stat = gss_unwrap(&min_stat, 
1000                               gensec_gssapi_state->gssapi_context, 
1001                               &input_token,
1002                               &output_token, 
1003                               &conf_state,
1004                               &qop_state);
1005         if (GSS_ERROR(maj_stat)) {
1006                 DEBUG(1, ("gensec_gssapi_unseal_packet: GSS UnWrap failed: %s\n", 
1007                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1008                 return NT_STATUS_ACCESS_DENIED;
1009         }
1010 
1011         if (output_token.length != length) {
1012                 return NT_STATUS_INTERNAL_ERROR;
1013         }
1014 
1015         memcpy(data, output_token.value, length);
1016 
1017         gss_release_buffer(&min_stat, &output_token);
1018         
1019         if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1020             && !conf_state) {
1021                 return NT_STATUS_ACCESS_DENIED;
1022         }
1023         return NT_STATUS_OK;
1024 }
1025 
1026 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
1027                                           TALLOC_CTX *mem_ctx, 
1028                                           const uint8_t *data, size_t length, 
1029                                           const uint8_t *whole_pdu, size_t pdu_length, 
1030                                           DATA_BLOB *sig)
1031 {
1032         struct gensec_gssapi_state *gensec_gssapi_state
1033                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1034         OM_uint32 maj_stat, min_stat;
1035         gss_buffer_desc input_token, output_token;
1036 
1037         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1038                 input_token.length = pdu_length;
1039                 input_token.value = discard_const_p(uint8_t *, whole_pdu);
1040         } else {
1041                 input_token.length = length;
1042                 input_token.value = discard_const_p(uint8_t *, data);
1043         }
1044 
1045         maj_stat = gss_get_mic(&min_stat,
1046                             gensec_gssapi_state->gssapi_context,
1047                             GSS_C_QOP_DEFAULT,
1048                             &input_token,
1049                             &output_token);
1050         if (GSS_ERROR(maj_stat)) {
1051                 DEBUG(1, ("GSS GetMic failed: %s\n",
1052                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1053                 return NT_STATUS_ACCESS_DENIED;
1054         }
1055 
1056         *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, output_token.length);
1057 
1058         dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
1059 
1060         gss_release_buffer(&min_stat, &output_token);
1061 
1062         return NT_STATUS_OK;
1063 }
1064 
1065 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
1066                                            TALLOC_CTX *mem_ctx, 
1067                                            const uint8_t *data, size_t length, 
1068                                            const uint8_t *whole_pdu, size_t pdu_length, 
1069                                            const DATA_BLOB *sig)
1070 {
1071         struct gensec_gssapi_state *gensec_gssapi_state
1072                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1073         OM_uint32 maj_stat, min_stat;
1074         gss_buffer_desc input_token;
1075         gss_buffer_desc input_message;
1076         gss_qop_t qop_state;
1077 
1078         dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
1079 
1080         if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1081                 input_message.length = pdu_length;
1082                 input_message.value = discard_const(whole_pdu);
1083         } else {
1084                 input_message.length = length;
1085                 input_message.value = discard_const(data);
1086         }
1087 
1088         input_token.length = sig->length;
1089         input_token.value = sig->data;
1090 
1091         maj_stat = gss_verify_mic(&min_stat,
1092                               gensec_gssapi_state->gssapi_context, 
1093                               &input_message,
1094                               &input_token,
1095                               &qop_state);
1096         if (GSS_ERROR(maj_stat)) {
1097                 DEBUG(1, ("GSS VerifyMic failed: %s\n",
1098                           gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1099                 return NT_STATUS_ACCESS_DENIED;
1100         }
1101 
1102         return NT_STATUS_OK;
1103 }
1104 
1105 /* Try to figure out what features we actually got on the connection */
1106 static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
1107                                        uint32_t feature) 
1108 {
1109         struct gensec_gssapi_state *gensec_gssapi_state
1110                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1111         if (feature & GENSEC_FEATURE_SIGN) {
1112                 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1113                 if (gensec_gssapi_state->sasl 
1114                     && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1115                         return ((gensec_gssapi_state->sasl_protection & NEG_SIGN) 
1116                                 && (gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG));
1117                 }
1118                 return gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG;
1119         }
1120         if (feature & GENSEC_FEATURE_SEAL) {
1121                 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1122                 if (gensec_gssapi_state->sasl 
1123                     && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1124                         return ((gensec_gssapi_state->sasl_protection & NEG_SEAL) 
1125                                  && (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG));
1126                 }
1127                 return gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG;
1128         }
1129         if (feature & GENSEC_FEATURE_SESSION_KEY) {
1130                 /* Only for GSSAPI/Krb5 */
1131                 if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
1132                         return true;
1133                 }
1134         }
1135         if (feature & GENSEC_FEATURE_DCE_STYLE) {
1136                 return gensec_gssapi_state->got_flags & GSS_C_DCE_STYLE;
1137         }
1138         if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
1139                 NTSTATUS status;
1140 
1141                 if (!(gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG)) {
1142                         return false;
1143                 }
1144 
1145                 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
1146                         return true;
1147                 }
1148                 if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
1149                         return false;
1150                 }
1151 
1152                 status = gensec_gssapi_init_lucid(gensec_gssapi_state);
1153                 if (!NT_STATUS_IS_OK(status)) {
1154                         return false;
1155                 }
1156 
1157                 if (gensec_gssapi_state->lucid->protocol == 1) {
1158                         return true;
1159                 }
1160 
1161                 return false;
1162         }
1163         /* We can always do async (rather than strict request/reply) packets.  */
1164         if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1165                 return true;
1166         }
1167         return false;
1168 }
1169 
1170 /*
1171  * Extract the 'sesssion key' needed by SMB signing and ncacn_np 
1172  * (for encrypting some passwords).
1173  * 
1174  * This breaks all the abstractions, but what do you expect...
1175  */
1176 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
1177                                           DATA_BLOB *session_key) 
1178 {
1179         struct gensec_gssapi_state *gensec_gssapi_state
1180                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1181         OM_uint32 maj_stat, min_stat;
1182         krb5_keyblock *subkey;
1183 
1184         if (gensec_gssapi_state->sasl_state != STAGE_DONE) {
1185                 return NT_STATUS_NO_USER_SESSION_KEY;
1186         }
1187 
1188         if (gensec_gssapi_state->session_key.data) {
1189                 *session_key = gensec_gssapi_state->session_key;
1190                 return NT_STATUS_OK;
1191         }
1192 
1193         maj_stat = gsskrb5_get_subkey(&min_stat,
1194                                       gensec_gssapi_state->gssapi_context,
1195                                       &subkey);
1196         if (maj_stat != 0) {
1197                 DEBUG(1, ("NO session key for this mech\n"));
1198                 return NT_STATUS_NO_USER_SESSION_KEY;
1199         }
1200         
1201         DEBUG(10, ("Got KRB5 session key of length %d%s\n",
1202                    (int)KRB5_KEY_LENGTH(subkey),
1203                    (gensec_gssapi_state->sasl_state == STAGE_DONE)?" (done)":""));
1204         *session_key = data_blob_talloc(gensec_gssapi_state,
1205                                         KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
1206         krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey);
1207         gensec_gssapi_state->session_key = *session_key;
1208         dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
1209 
1210         return NT_STATUS_OK;
1211 }
1212 
1213 /* Get some basic (and authorization) information about the user on
1214  * this session.  This uses either the PAC (if present) or a local
1215  * database lookup */
1216 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
1217                                            struct auth_session_info **_session_info) 
1218 {
1219         NTSTATUS nt_status;
1220         TALLOC_CTX *mem_ctx;
1221         struct gensec_gssapi_state *gensec_gssapi_state
1222                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1223         struct auth_serversupplied_info *server_info = NULL;
1224         struct auth_session_info *session_info = NULL;
1225         OM_uint32 maj_stat, min_stat;
1226         gss_buffer_desc pac;
1227         DATA_BLOB pac_blob;
1228         
1229         if ((gensec_gssapi_state->gss_oid->length != gss_mech_krb5->length)
1230             || (memcmp(gensec_gssapi_state->gss_oid->elements, gss_mech_krb5->elements, 
1231                        gensec_gssapi_state->gss_oid->length) != 0)) {
1232                 DEBUG(1, ("NO session info available for this mech\n"));
1233                 return NT_STATUS_INVALID_PARAMETER;
1234         }
1235                 
1236         mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context"); 
1237         NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
1238 
1239         maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 
1240                                                                gensec_gssapi_state->gssapi_context, 
1241                                                                KRB5_AUTHDATA_WIN2K_PAC,
1242                                                                &pac);
1243         
1244         
1245         if (maj_stat == 0) {
1246                 pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length);
1247                 gss_release_buffer(&min_stat, &pac);
1248 
1249         } else {
1250                 pac_blob = data_blob(NULL, 0);
1251         }
1252         
1253         /* IF we have the PAC - otherwise we need to get this
1254          * data from elsewere - local ldb, or (TODO) lookup of some
1255          * kind... 
1256          */
1257         if (pac_blob.length) {
1258                 nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
1259                                                              gensec_security->settings->iconv_convenience,
1260                                                              pac_blob, 
1261                                                              gensec_gssapi_state->smb_krb5_context->krb5_context,
1262                                                              &server_info);
1263                 if (!NT_STATUS_IS_OK(nt_status)) {
1264                         talloc_free(mem_ctx);
1265                         return nt_status;
1266                 }
1267         } else {
1268                 gss_buffer_desc name_token;
1269                 char *principal_string;
1270 
1271                 maj_stat = gss_display_name (&min_stat,
1272                                              gensec_gssapi_state->client_name,
1273                                              &name_token,
1274                                              NULL);
1275                 if (GSS_ERROR(maj_stat)) {
1276                         DEBUG(1, ("GSS display_name failed: %s\n", 
1277                                   gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1278                         talloc_free(mem_ctx);
1279                         return NT_STATUS_FOOBAR;
1280                 }
1281                 
1282                 principal_string = talloc_strndup(mem_ctx, 
1283                                                   (const char *)name_token.value, 
1284                                                   name_token.length);
1285                 
1286                 gss_release_buffer(&min_stat, &name_token);
1287                 
1288                 if (!principal_string) {
1289                         talloc_free(mem_ctx);
1290                         return NT_STATUS_NO_MEMORY;
1291                 }
1292 
1293                 if (gensec_security->auth_context && 
1294                     !gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) {
1295                         DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",
1296                                   gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1297                         nt_status = gensec_security->auth_context->get_server_info_principal(mem_ctx, 
1298                                                                                              gensec_security->auth_context, 
1299                                                                                              principal_string,
1300                                                                                              &server_info);
1301                         
1302                         if (!NT_STATUS_IS_OK(nt_status)) {
1303                                 talloc_free(mem_ctx);
1304                                 return nt_status;
1305                         }
1306                 } else {
1307                         DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",
1308                                   principal_string,
1309                                   gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1310                         return NT_STATUS_ACCESS_DENIED;
1311                 }
1312         }
1313 
1314         /* references the server_info into the session_info */
1315         nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx, 
1316                                                gensec_security->settings->lp_ctx, server_info, &session_info);
1317         if (!NT_STATUS_IS_OK(nt_status)) {
1318                 talloc_free(mem_ctx);
1319                 return nt_status;
1320         }
1321 
1322         nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);
1323         if (!NT_STATUS_IS_OK(nt_status)) {
1324                 talloc_free(mem_ctx);
1325                 return nt_status;
1326         }
1327 
1328         if (!(gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG)) {
1329                 DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
1330         } else {
1331                 krb5_error_code ret;
1332                 DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
1333                 session_info->credentials = cli_credentials_init(session_info);
1334                 if (!session_info->credentials) {
1335                         talloc_free(mem_ctx);
1336                         return NT_STATUS_NO_MEMORY;
1337                 }
1338 
1339                 cli_credentials_set_conf(session_info->credentials, gensec_security->settings->lp_ctx);
1340                 /* Just so we don't segfault trying to get at a username */
1341                 cli_credentials_set_anonymous(session_info->credentials);
1342                 
1343                 ret = cli_credentials_set_client_gss_creds(session_info->credentials, 
1344                                                            gensec_security->event_ctx,
1345                                                            gensec_security->settings->lp_ctx, 
1346                                                            gensec_gssapi_state->delegated_cred_handle,
1347                                                            CRED_SPECIFIED);
1348                 if (ret) {
1349                         talloc_free(mem_ctx);
1350                         return NT_STATUS_NO_MEMORY;
1351                 }
1352                 
1353                 /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
1354                 cli_credentials_set_kerberos_state(session_info->credentials, CRED_MUST_USE_KERBEROS);
1355 
1356                 /* It has been taken from this place... */
1357                 gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1358         }
1359         talloc_steal(gensec_gssapi_state, session_info);
1360         talloc_free(mem_ctx);
1361         *_session_info = session_info;
1362 
1363         return NT_STATUS_OK;
1364 }
1365 
1366 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
     /* [<][>][^][v][top][bottom][index][help] */
1367 {
1368         struct gensec_gssapi_state *gensec_gssapi_state
1369                 = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1370         NTSTATUS status;
1371 
1372         if (gensec_gssapi_state->sig_size) {
1373                 return gensec_gssapi_state->sig_size;
1374         }
1375 
1376         if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1377                 gensec_gssapi_state->sig_size = 45;
1378         } else {
1379                 gensec_gssapi_state->sig_size = 37;
1380         }
1381 
1382         status = gensec_gssapi_init_lucid(gensec_gssapi_state);
1383         if (!NT_STATUS_IS_OK(status)) {
1384                 return gensec_gssapi_state->sig_size;
1385         }
1386 
1387         if (gensec_gssapi_state->lucid->protocol == 1) {
1388                 if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1389                         /*
1390                          * TODO: windows uses 76 here, but we don't know
1391                          *       gss_wrap works with aes keys yet
1392                          */
1393                         gensec_gssapi_state->sig_size = 76;
1394                 } else {
1395                         gensec_gssapi_state->sig_size = 28;
1396                 }
1397         } else if (gensec_gssapi_state->lucid->protocol == 0) {
1398                 switch (gensec_gssapi_state->lucid->rfc1964_kd.ctx_key.type) {
1399                 case KEYTYPE_DES:
1400                 case KEYTYPE_ARCFOUR:
1401                 case KEYTYPE_ARCFOUR_56:
1402                         if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1403                                 gensec_gssapi_state->sig_size = 45;
1404                         } else {
1405                                 gensec_gssapi_state->sig_size = 37;
1406                         }
1407                         break;
1408                 case KEYTYPE_DES3:
1409                         if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
1410                                 gensec_gssapi_state->sig_size = 57;
1411                         } else {
1412                                 gensec_gssapi_state->sig_size = 49;
1413                         }
1414                         break;
1415                 }
1416         }
1417 
1418         return gensec_gssapi_state->sig_size;
1419 }
1420 
1421 static const char *gensec_gssapi_krb5_oids[] = { 
1422         GENSEC_OID_KERBEROS5_OLD,
1423         GENSEC_OID_KERBEROS5,
1424         NULL 
1425 };
1426 
1427 static const char *gensec_gssapi_spnego_oids[] = { 
1428         GENSEC_OID_SPNEGO,
1429         NULL 
1430 };
1431 
1432 /* As a server, this could in theory accept any GSSAPI mech */
1433 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
1434         .name           = "gssapi_spnego",
1435         .sasl_name      = "GSS-SPNEGO",
1436         .auth_type      = DCERPC_AUTH_TYPE_SPNEGO,
1437         .oid            = gensec_gssapi_spnego_oids,
1438         .client_start   = gensec_gssapi_client_start,
1439         .server_start   = gensec_gssapi_server_start,
1440         .magic          = gensec_gssapi_magic,
1441         .update         = gensec_gssapi_update,
1442         .session_key    = gensec_gssapi_session_key,
1443         .session_info   = gensec_gssapi_session_info,
1444         .sign_packet    = gensec_gssapi_sign_packet,
1445         .check_packet   = gensec_gssapi_check_packet,
1446         .seal_packet    = gensec_gssapi_seal_packet,
1447         .unseal_packet  = gensec_gssapi_unseal_packet,
1448         .wrap           = gensec_gssapi_wrap,
1449         .unwrap         = gensec_gssapi_unwrap,
1450         .have_feature   = gensec_gssapi_have_feature,
1451         .enabled        = false,
1452         .kerberos       = true,
1453         .priority       = GENSEC_GSSAPI
1454 };
1455 
1456 /* As a server, this could in theory accept any GSSAPI mech */
1457 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
1458         .name           = "gssapi_krb5",
1459         .auth_type      = DCERPC_AUTH_TYPE_KRB5,
1460         .oid            = gensec_gssapi_krb5_oids,
1461         .client_start   = gensec_gssapi_client_start,
1462         .server_start   = gensec_gssapi_server_start,
1463         .magic          = gensec_gssapi_magic,
1464         .update         = gensec_gssapi_update,
1465         .session_key    = gensec_gssapi_session_key,
1466         .session_info   = gensec_gssapi_session_info,
1467         .sig_size       = gensec_gssapi_sig_size,
1468         .sign_packet    = gensec_gssapi_sign_packet,
1469         .check_packet   = gensec_gssapi_check_packet,
1470         .seal_packet    = gensec_gssapi_seal_packet,
1471         .unseal_packet  = gensec_gssapi_unseal_packet,
1472         .wrap           = gensec_gssapi_wrap,
1473         .unwrap         = gensec_gssapi_unwrap,
1474         .have_feature   = gensec_gssapi_have_feature,
1475         .enabled        = true,
1476         .kerberos       = true,
1477         .priority       = GENSEC_GSSAPI
1478 };
1479 
1480 /* As a server, this could in theory accept any GSSAPI mech */
1481 static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
1482         .name             = "gssapi_krb5_sasl",
1483         .sasl_name        = "GSSAPI",
1484         .client_start     = gensec_gssapi_sasl_client_start,
1485         .server_start     = gensec_gssapi_sasl_server_start,
1486         .update           = gensec_gssapi_update,
1487         .session_key      = gensec_gssapi_session_key,
1488         .session_info     = gensec_gssapi_session_info,
1489         .max_input_size   = gensec_gssapi_max_input_size,
1490         .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1491         .wrap             = gensec_gssapi_wrap,
1492         .unwrap           = gensec_gssapi_unwrap,
1493         .have_feature     = gensec_gssapi_have_feature,
1494         .enabled          = true,
1495         .kerberos         = true,
1496         .priority         = GENSEC_GSSAPI
1497 };
1498 
1499 _PUBLIC_ NTSTATUS gensec_gssapi_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
1500 {
1501         NTSTATUS ret;
1502 
1503         ret = gensec_register(&gensec_gssapi_spnego_security_ops);
1504         if (!NT_STATUS_IS_OK(ret)) {
1505                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1506                         gensec_gssapi_spnego_security_ops.name));
1507                 return ret;
1508         }
1509 
1510         ret = gensec_register(&gensec_gssapi_krb5_security_ops);
1511         if (!NT_STATUS_IS_OK(ret)) {
1512                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1513                         gensec_gssapi_krb5_security_ops.name));
1514                 return ret;
1515         }
1516 
1517         ret = gensec_register(&gensec_gssapi_sasl_krb5_security_ops);
1518         if (!NT_STATUS_IS_OK(ret)) {
1519                 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1520                         gensec_gssapi_sasl_krb5_security_ops.name));
1521                 return ret;
1522         }
1523 
1524         return ret;
1525 }

/* [<][>][^][v][top][bottom][index][help] */