Changeset 988 for vendor/current/source3/librpc/crypto
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- Location:
- vendor/current/source3/librpc/crypto
- Files:
-
- 2 deleted
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/librpc/crypto/gse.c
r746 r988 3 3 * RPC Pipe client and server routines 4 4 * Copyright (C) Simo Sorce 2010. 5 * Copyright (C) Andrew Bartlett 2004-2011. 6 * Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005 5 7 * 6 8 * This program is free software; you can redistribute it and/or modify … … 22 24 #include "includes.h" 23 25 #include "gse.h" 24 25 #if defined(HAVE_KRB5) \ 26 && defined(HAVE_GSSAPI_GSSAPI_EXT_H) \ 27 && defined(HAVE_GSS_WRAP_IOV) \ 28 && defined(HAVE_GSS_GET_NAME_ATTRIBUTE) 29 30 #include "smb_krb5.h" 26 #include "libads/kerberos_proto.h" 27 #include "auth/common_auth.h" 28 #include "auth/gensec/gensec.h" 29 #include "auth/gensec/gensec_internal.h" 30 #include "auth/credentials/credentials.h" 31 #include "../librpc/gen_ndr/dcerpc.h" 32 33 #if defined(HAVE_KRB5) 34 35 #include "auth/kerberos/pac_utils.h" 36 #include "auth/kerberos/gssapi_helper.h" 31 37 #include "gse_krb5.h" 32 38 33 #include <gssapi/gssapi.h>34 #include <gssapi/gssapi_krb5.h>35 #include <gssapi/gssapi_ext.h>36 37 #ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID38 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 1139 #define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"40 #endif41 42 gss_OID_desc gse_sesskey_inq_oid = {43 GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH,44 (void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID45 };46 47 #ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID48 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 1049 #define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"50 #endif51 52 gss_OID_desc gse_sesskeytype_oid = {53 GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,54 (void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID55 };56 57 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH 1258 /* EXTRACTION OID AUTHZ ID */59 #define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" "\x01"60 61 gss_OID_desc gse_authz_data_oid = {62 GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH,63 (void *)GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID64 };65 66 #ifndef GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID67 #define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH 1168 #define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0c"69 #endif70 71 gss_OID_desc gse_authtime_oid = {72 GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH,73 (void *)GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID74 };75 76 39 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min); 40 static size_t gensec_gse_sig_size(struct gensec_security *gensec_security, 41 size_t data_size); 77 42 78 43 struct gse_context { 44 gss_ctx_id_t gssapi_context; 45 gss_name_t server_name; 46 gss_name_t client_name; 47 OM_uint32 gss_want_flags, gss_got_flags; 48 size_t max_wrap_buf_size; 49 size_t sig_size; 50 51 gss_cred_id_t delegated_cred_handle; 52 53 NTTIME expire_time; 54 55 /* gensec_gse only */ 79 56 krb5_context k5ctx; 80 57 krb5_ccache ccache; 81 58 krb5_keytab keytab; 82 59 83 gss_ctx_id_t gss_ctx;84 85 60 gss_OID_desc gss_mech; 86 OM_uint32 gss_c_flags;87 61 gss_cred_id_t creds; 88 gss_name_t server_name;89 62 90 63 gss_OID ret_mech; 91 OM_uint32 ret_flags;92 gss_cred_id_t delegated_creds;93 gss_name_t client_name;94 95 bool more_processing;96 bool authenticated;97 64 }; 98 65 … … 101 68 { 102 69 struct gse_context *gse_ctx; 103 OM_uint32 gss_min , gss_maj;70 OM_uint32 gss_min; 104 71 105 72 gse_ctx = talloc_get_type_abort(ptr, struct gse_context); … … 116 83 gse_ctx->k5ctx = NULL; 117 84 } 118 if (gse_ctx->gss _ctx!= GSS_C_NO_CONTEXT) {119 gss_maj =gss_delete_sec_context(&gss_min,120 &gse_ctx->gss _ctx,85 if (gse_ctx->gssapi_context != GSS_C_NO_CONTEXT) { 86 (void)gss_delete_sec_context(&gss_min, 87 &gse_ctx->gssapi_context, 121 88 GSS_C_NO_BUFFER); 122 89 } 123 90 if (gse_ctx->server_name) { 124 gss_maj =gss_release_name(&gss_min,91 (void)gss_release_name(&gss_min, 125 92 &gse_ctx->server_name); 126 93 } 127 94 if (gse_ctx->client_name) { 128 gss_maj =gss_release_name(&gss_min,95 (void)gss_release_name(&gss_min, 129 96 &gse_ctx->client_name); 130 97 } 131 98 if (gse_ctx->creds) { 132 gss_maj =gss_release_cred(&gss_min,99 (void)gss_release_cred(&gss_min, 133 100 &gse_ctx->creds); 134 101 } 135 if (gse_ctx->delegated_creds) { 136 gss_maj = gss_release_cred(&gss_min, 137 &gse_ctx->delegated_creds); 138 } 139 if (gse_ctx->ret_mech) { 140 gss_maj = gss_release_oid(&gss_min, 141 &gse_ctx->ret_mech); 142 } 102 if (gse_ctx->delegated_cred_handle) { 103 (void)gss_release_cred(&gss_min, 104 &gse_ctx->delegated_cred_handle); 105 } 106 107 /* MIT and Heimdal differ as to if you can call 108 * gss_release_oid() on this OID, generated by 109 * gss_{accept,init}_sec_context(). However, as long as the 110 * oid is gss_mech_krb5 (which it always is at the moment), 111 * then this is a moot point, as both declare this particular 112 * OID static, and so no memory is lost. This assert is in 113 * place to ensure that the programmer who wishes to extend 114 * this code to EAP or other GSS mechanisms determines an 115 * implementation-dependent way of releasing any dynamically 116 * allocated OID */ 117 SMB_ASSERT(smb_gss_oid_equal(&gse_ctx->gss_mech, GSS_C_NO_OID) || 118 smb_gss_oid_equal(&gse_ctx->gss_mech, gss_mech_krb5)); 119 143 120 return 0; 144 121 } … … 160 137 talloc_set_destructor((TALLOC_CTX *)gse_ctx, gse_context_destructor); 161 138 139 gse_ctx->expire_time = GENSEC_EXPIRE_TIME_INFINITY; 140 gse_ctx->max_wrap_buf_size = UINT16_MAX; 141 162 142 memcpy(&gse_ctx->gss_mech, gss_mech_krb5, sizeof(gss_OID_desc)); 163 143 164 gse_ctx->gss_ c_flags = GSS_C_MUTUAL_FLAG |144 gse_ctx->gss_want_flags = GSS_C_MUTUAL_FLAG | 165 145 GSS_C_DELEG_FLAG | 166 146 GSS_C_DELEG_POLICY_FLAG | … … 168 148 GSS_C_SEQUENCE_FLAG; 169 149 if (do_sign) { 170 gse_ctx->gss_ c_flags |= GSS_C_INTEG_FLAG;150 gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG; 171 151 } 172 152 if (do_seal) { 173 gse_ctx->gss_c_flags |= GSS_C_CONF_FLAG; 174 } 175 176 gse_ctx->gss_c_flags |= add_gss_c_flags; 153 gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG; 154 gse_ctx->gss_want_flags |= GSS_C_CONF_FLAG; 155 } 156 157 gse_ctx->gss_want_flags |= add_gss_c_flags; 177 158 178 159 /* Initialize Kerberos Context */ … … 211 192 } 212 193 213 NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,214 215 216 217 218 219 220 221 194 static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, 195 bool do_sign, bool do_seal, 196 const char *ccache_name, 197 const char *server, 198 const char *service, 199 const char *username, 200 const char *password, 201 uint32_t add_gss_c_flags, 202 struct gse_context **_gse_ctx) 222 203 { 223 204 struct gse_context *gse_ctx; 224 205 OM_uint32 gss_maj, gss_min; 225 gss_buffer_desc name_buffer = {0, NULL};206 gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER; 226 207 gss_OID_set_desc mech_set; 208 #ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X 209 gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; 210 #endif 227 211 NTSTATUS status; 228 212 … … 238 222 } 239 223 240 name_buffer.value = talloc_asprintf(gse_ctx, 241 "%s@%s", service, server); 224 /* Guess the realm based on the supplied service, and avoid the GSS libs 225 doing DNS lookups which may fail. 226 227 TODO: Loop with the KDC on some more combinations (local 228 realm in particular), possibly falling back to 229 GSS_C_NT_HOSTBASED_SERVICE 230 */ 231 name_buffer.value = kerberos_get_principal_from_service_hostname( 232 gse_ctx, service, server, lp_realm()); 242 233 if (!name_buffer.value) { 243 234 status = NT_STATUS_NO_MEMORY; … … 246 237 name_buffer.length = strlen((char *)name_buffer.value); 247 238 gss_maj = gss_import_name(&gss_min, &name_buffer, 248 GSS_C_NT_ HOSTBASED_SERVICE,239 GSS_C_NT_USER_NAME, 249 240 &gse_ctx->server_name); 250 241 if (gss_maj) { 251 DEBUG( 0, ("gss_import_name failed for %s, with [%s]\n",242 DEBUG(5, ("gss_import_name failed for %s, with [%s]\n", 252 243 (char *)name_buffer.value, 253 244 gse_errstr(gse_ctx, gss_maj, gss_min))); … … 270 261 NULL, NULL); 271 262 if (gss_maj) { 272 DEBUG( 0, ("gss_acquire_creds failed for %s, with [%s]\n",273 (char *)name_buffer.value,263 DEBUG(5, ("gss_acquire_creds failed for GSS_C_NO_NAME with [%s] -" 264 "the caller may retry after a kinit.\n", 274 265 gse_errstr(gse_ctx, gss_maj, gss_min))); 275 266 status = NT_STATUS_INTERNAL_ERROR; 276 267 goto err_out; 277 268 } 269 270 #ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X 271 /* 272 * Don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG. 273 * 274 * This allows us to disable SIGN and SEAL for 275 * AUTH_LEVEL_CONNECT and AUTH_LEVEL_INTEGRITY. 276 * 277 * https://groups.yahoo.com/neo/groups/cat-ietf/conversations/topics/575 278 * http://krbdev.mit.edu/rt/Ticket/Display.html?id=6938 279 */ 280 gss_maj = gss_set_cred_option(&gss_min, &gse_ctx->creds, 281 GSS_KRB5_CRED_NO_CI_FLAGS_X, 282 &empty_buffer); 283 if (gss_maj) { 284 DEBUG(0, ("gss_set_cred_option(GSS_KRB5_CRED_NO_CI_FLAGS_X), " 285 "failed with [%s]\n", 286 gse_errstr(gse_ctx, gss_maj, gss_min))); 287 status = NT_STATUS_INTERNAL_ERROR; 288 goto err_out; 289 } 290 #endif 278 291 279 292 *_gse_ctx = gse_ctx; … … 287 300 } 288 301 289 NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,290 291 292 302 static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, 303 struct gse_context *gse_ctx, 304 const DATA_BLOB *token_in, 305 DATA_BLOB *token_out) 293 306 { 294 307 OM_uint32 gss_maj, gss_min; … … 297 310 DATA_BLOB blob = data_blob_null; 298 311 NTSTATUS status; 312 OM_uint32 time_rec = 0; 313 struct timeval tv; 299 314 300 315 in_data.value = token_in->data; … … 303 318 gss_maj = gss_init_sec_context(&gss_min, 304 319 gse_ctx->creds, 305 &gse_ctx->gss _ctx,320 &gse_ctx->gssapi_context, 306 321 gse_ctx->server_name, 307 322 &gse_ctx->gss_mech, 308 gse_ctx->gss_ c_flags,323 gse_ctx->gss_want_flags, 309 324 0, GSS_C_NO_CHANNEL_BINDINGS, 310 325 &in_data, NULL, &out_data, 311 NULL, NULL);326 &gse_ctx->gss_got_flags, &time_rec); 312 327 switch (gss_maj) { 313 328 case GSS_S_COMPLETE: 314 329 /* we are done with it */ 315 gse_ctx->more_processing = false; 330 tv = timeval_current_ofs(time_rec, 0); 331 gse_ctx->expire_time = timeval_to_nttime(&tv); 332 316 333 status = NT_STATUS_OK; 317 334 break; 318 335 case GSS_S_CONTINUE_NEEDED: 319 336 /* we will need a third leg */ 320 gse_ctx->more_processing = true; 321 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */ 322 status = NT_STATUS_OK; 337 status = NT_STATUS_MORE_PROCESSING_REQUIRED; 323 338 break; 324 339 default: … … 329 344 } 330 345 331 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length); 332 if (!blob.data) { 333 status = NT_STATUS_NO_MEMORY; 334 } 335 336 gss_maj = gss_release_buffer(&gss_min, &out_data); 346 /* we may be told to return nothing */ 347 if (out_data.length) { 348 blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length); 349 if (!blob.data) { 350 status = NT_STATUS_NO_MEMORY; 351 } 352 353 gss_maj = gss_release_buffer(&gss_min, &out_data); 354 } 337 355 338 356 done: … … 341 359 } 342 360 343 NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx, 344 bool do_sign, bool do_seal, 345 uint32_t add_gss_c_flags, 346 const char *keytab_name, 347 struct gse_context **_gse_ctx) 361 static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx, 362 bool do_sign, bool do_seal, 363 uint32_t add_gss_c_flags, 364 struct gse_context **_gse_ctx) 348 365 { 349 366 struct gse_context *gse_ctx; 350 367 OM_uint32 gss_maj, gss_min; 351 gss_OID_set_desc mech_set;352 368 krb5_error_code ret; 353 const char *ktname;354 369 NTSTATUS status; 355 370 … … 360 375 } 361 376 362 if (!keytab_name) { 363 ret = gse_krb5_get_server_keytab(gse_ctx->k5ctx, 364 &gse_ctx->keytab); 365 if (ret) { 366 status = NT_STATUS_INTERNAL_ERROR; 367 goto done; 368 } 369 ret = smb_krb5_keytab_name(gse_ctx, gse_ctx->k5ctx, 370 gse_ctx->keytab, &ktname); 371 if (ret) { 372 status = NT_STATUS_INTERNAL_ERROR; 373 goto done; 374 } 375 } else { 376 ktname = keytab_name; 377 } 378 377 ret = gse_krb5_get_server_keytab(gse_ctx->k5ctx, 378 &gse_ctx->keytab); 379 if (ret) { 380 status = NT_STATUS_INTERNAL_ERROR; 381 goto done; 382 } 383 384 #ifdef HAVE_GSS_KRB5_IMPORT_CRED 385 386 /* This creates a GSSAPI cred_id_t with the keytab set */ 387 gss_maj = gss_krb5_import_cred(&gss_min, NULL, NULL, gse_ctx->keytab, 388 &gse_ctx->creds); 389 390 if (gss_maj != 0 391 && gss_maj != (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) { 392 DEBUG(0, ("gss_krb5_import_cred failed with [%s]\n", 393 gse_errstr(gse_ctx, gss_maj, gss_min))); 394 status = NT_STATUS_INTERNAL_ERROR; 395 goto done; 396 397 /* This is the error the MIT krb5 1.9 gives when it 398 * implements the function, but we do not specify the 399 * principal. However, when we specify the principal 400 * as host$@REALM the GSS acceptor fails with 'wrong 401 * principal in request'. Work around the issue by 402 * falling back to the alternate approach below. */ 403 } else if (gss_maj == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) 404 #endif 379 405 /* FIXME!!! 380 406 * This call sets the default keytab for the whole server, not 381 407 * just for this context. Need to find a way that does not alter 382 408 * the state of the whole server ... */ 383 ret = gsskrb5_register_acceptor_identity(ktname); 384 if (ret) { 385 status = NT_STATUS_INTERNAL_ERROR; 386 goto done; 387 } 388 389 mech_set.count = 1; 390 mech_set.elements = &gse_ctx->gss_mech; 391 392 gss_maj = gss_acquire_cred(&gss_min, 409 { 410 const char *ktname; 411 gss_OID_set_desc mech_set; 412 413 ret = smb_krb5_keytab_name(gse_ctx, gse_ctx->k5ctx, 414 gse_ctx->keytab, &ktname); 415 if (ret) { 416 status = NT_STATUS_INTERNAL_ERROR; 417 goto done; 418 } 419 420 ret = gsskrb5_register_acceptor_identity(ktname); 421 if (ret) { 422 status = NT_STATUS_INTERNAL_ERROR; 423 goto done; 424 } 425 426 mech_set.count = 1; 427 mech_set.elements = &gse_ctx->gss_mech; 428 429 gss_maj = gss_acquire_cred(&gss_min, 393 430 GSS_C_NO_NAME, 394 431 GSS_C_INDEFINITE, … … 397 434 &gse_ctx->creds, 398 435 NULL, NULL); 399 if (gss_maj) { 400 DEBUG(0, ("gss_acquire_creds failed with [%s]\n", 401 gse_errstr(gse_ctx, gss_maj, gss_min))); 402 status = NT_STATUS_INTERNAL_ERROR; 403 goto done; 436 437 if (gss_maj) { 438 DEBUG(0, ("gss_acquire_creds failed with [%s]\n", 439 gse_errstr(gse_ctx, gss_maj, gss_min))); 440 status = NT_STATUS_INTERNAL_ERROR; 441 goto done; 442 } 404 443 } 405 444 … … 415 454 } 416 455 417 NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,418 419 420 456 static NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx, 457 struct gse_context *gse_ctx, 458 const DATA_BLOB *token_in, 459 DATA_BLOB *token_out) 421 460 { 422 461 OM_uint32 gss_maj, gss_min; … … 425 464 DATA_BLOB blob = data_blob_null; 426 465 NTSTATUS status; 466 OM_uint32 time_rec = 0; 467 struct timeval tv; 427 468 428 469 in_data.value = token_in->data; … … 430 471 431 472 gss_maj = gss_accept_sec_context(&gss_min, 432 &gse_ctx->gss _ctx,473 &gse_ctx->gssapi_context, 433 474 gse_ctx->creds, 434 475 &in_data, … … 437 478 &gse_ctx->ret_mech, 438 479 &out_data, 439 &gse_ctx->ret_flags, NULL, 440 &gse_ctx->delegated_creds); 480 &gse_ctx->gss_got_flags, 481 &time_rec, 482 &gse_ctx->delegated_cred_handle); 441 483 switch (gss_maj) { 442 484 case GSS_S_COMPLETE: 443 485 /* we are done with it */ 444 gse_ctx->more_processing = false; 445 gse_ctx->authenticated = true; 486 tv = timeval_current_ofs(time_rec, 0); 487 gse_ctx->expire_time = timeval_to_nttime(&tv); 488 446 489 status = NT_STATUS_OK; 447 490 break; 448 491 case GSS_S_CONTINUE_NEEDED: 449 492 /* we will need a third leg */ 450 gse_ctx->more_processing = true; 451 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */ 452 status = NT_STATUS_OK; 493 status = NT_STATUS_MORE_PROCESSING_REQUIRED; 453 494 break; 454 495 default: 455 DEBUG( 0, ("gss_init_sec_context failed with [%s]\n",496 DEBUG(1, ("gss_accept_sec_context failed with [%s]\n", 456 497 gse_errstr(talloc_tos(), gss_maj, gss_min))); 457 498 458 if (gse_ctx->gss _ctx) {499 if (gse_ctx->gssapi_context) { 459 500 gss_delete_sec_context(&gss_min, 460 &gse_ctx->gss _ctx,501 &gse_ctx->gssapi_context, 461 502 GSS_C_NO_BUFFER); 462 503 } 463 504 464 status = NT_STATUS_INTERNAL_ERROR; 465 goto done; 505 /* 506 * If we got an output token, make Windows aware of it 507 * by telling it that more processing is needed 508 */ 509 if (out_data.length > 0) { 510 status = NT_STATUS_MORE_PROCESSING_REQUIRED; 511 /* Fall through to handle the out token */ 512 } else { 513 status = NT_STATUS_LOGON_FAILURE; 514 goto done; 515 } 466 516 } 467 517 … … 481 531 } 482 532 483 NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx)484 {485 if (!gse_ctx->authenticated) {486 return NT_STATUS_INVALID_HANDLE;487 }488 489 if (memcmp(gse_ctx->ret_mech,490 gss_mech_krb5, sizeof(gss_OID_desc)) != 0) {491 return NT_STATUS_ACCESS_DENIED;492 }493 494 /* GSS_C_MUTUAL_FLAG */495 if (gse_ctx->gss_c_flags & GSS_C_MUTUAL_FLAG) {496 if (!(gse_ctx->ret_flags & GSS_C_MUTUAL_FLAG)) {497 return NT_STATUS_ACCESS_DENIED;498 }499 }500 501 /* GSS_C_DELEG_FLAG */502 /* GSS_C_DELEG_POLICY_FLAG */503 /* GSS_C_REPLAY_FLAG */504 /* GSS_C_SEQUENCE_FLAG */505 506 /* GSS_C_INTEG_FLAG */507 if (gse_ctx->gss_c_flags & GSS_C_INTEG_FLAG) {508 if (!(gse_ctx->ret_flags & GSS_C_INTEG_FLAG)) {509 return NT_STATUS_ACCESS_DENIED;510 }511 }512 513 /* GSS_C_CONF_FLAG */514 if (gse_ctx->gss_c_flags & GSS_C_CONF_FLAG) {515 if (!(gse_ctx->ret_flags & GSS_C_CONF_FLAG)) {516 return NT_STATUS_ACCESS_DENIED;517 }518 }519 520 return NT_STATUS_OK;521 }522 523 533 static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min) 524 534 { … … 536 546 GSS_C_NO_OID, &msg_ctx, &msg_maj); 537 547 if (gss_maj) { 548 goto done; 549 } 550 errstr = talloc_strndup(mem_ctx, 551 (char *)msg_maj.value, 552 msg_maj.length); 553 if (!errstr) { 538 554 goto done; 539 555 } … … 545 561 } 546 562 547 errstr = talloc_strndup(mem_ctx,548 (char *)msg_maj.value,549 msg_maj.length);550 if (!errstr) {551 goto done;552 }553 563 errstr = talloc_strdup_append_buffer(errstr, ": "); 554 564 if (!errstr) { … … 572 582 } 573 583 574 bool gse_require_more_processing(struct gse_context *gse_ctx) 575 { 576 return gse_ctx->more_processing; 577 } 578 579 DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx, 580 struct gse_context *gse_ctx) 581 { 582 OM_uint32 gss_min, gss_maj; 583 gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; 584 DATA_BLOB ret; 585 586 gss_maj = gss_inquire_sec_context_by_oid( 587 &gss_min, gse_ctx->gss_ctx, 588 &gse_sesskey_inq_oid, &set); 589 if (gss_maj) { 590 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n", 591 gse_errstr(talloc_tos(), gss_maj, gss_min))); 592 return data_blob_null; 593 } 594 595 if ((set == GSS_C_NO_BUFFER_SET) || 596 (set->count != 2) || 597 (memcmp(set->elements[1].value, 598 gse_sesskeytype_oid.elements, 599 gse_sesskeytype_oid.length) != 0)) { 600 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown " 601 "OID for data in results:\n")); 602 dump_data(1, (uint8_t *)set->elements[1].value, 603 set->elements[1].length); 604 return data_blob_null; 605 } 606 607 ret = data_blob_talloc(mem_ctx, set->elements[0].value, 608 set->elements[0].length); 609 610 gss_maj = gss_release_buffer_set(&gss_min, &set); 611 return ret; 612 } 613 614 NTSTATUS gse_get_client_name(struct gse_context *gse_ctx, 615 TALLOC_CTX *mem_ctx, char **cli_name) 616 { 617 OM_uint32 gss_min, gss_maj; 618 gss_buffer_desc name_buffer; 619 620 if (!gse_ctx->authenticated) { 584 static NTSTATUS gensec_gse_client_start(struct gensec_security *gensec_security) 585 { 586 struct gse_context *gse_ctx; 587 struct cli_credentials *creds = gensec_get_credentials(gensec_security); 588 NTSTATUS nt_status; 589 OM_uint32 want_flags = 0; 590 bool do_sign = false, do_seal = false; 591 const char *hostname = gensec_get_target_hostname(gensec_security); 592 const char *service = gensec_get_target_service(gensec_security); 593 const char *username = cli_credentials_get_username(creds); 594 const char *password = cli_credentials_get_password(creds); 595 596 if (!hostname) { 597 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n")); 598 return NT_STATUS_INVALID_PARAMETER; 599 } 600 if (is_ipaddress(hostname)) { 601 DEBUG(2, ("Cannot do GSE to an IP address\n")); 602 return NT_STATUS_INVALID_PARAMETER; 603 } 604 if (strcmp(hostname, "localhost") == 0) { 605 DEBUG(2, ("GSE to 'localhost' does not make sense\n")); 606 return NT_STATUS_INVALID_PARAMETER; 607 } 608 609 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) { 610 do_sign = true; 611 } 612 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { 613 do_sign = true; 614 } 615 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { 616 do_seal = true; 617 } 618 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) { 619 want_flags |= GSS_C_DCE_STYLE; 620 } 621 622 nt_status = gse_init_client(gensec_security, do_sign, do_seal, NULL, 623 hostname, service, 624 username, password, want_flags, 625 &gse_ctx); 626 if (!NT_STATUS_IS_OK(nt_status)) { 627 return nt_status; 628 } 629 gensec_security->private_data = gse_ctx; 630 return NT_STATUS_OK; 631 } 632 633 static NTSTATUS gensec_gse_server_start(struct gensec_security *gensec_security) 634 { 635 struct gse_context *gse_ctx; 636 NTSTATUS nt_status; 637 OM_uint32 want_flags = 0; 638 bool do_sign = false, do_seal = false; 639 640 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { 641 do_sign = true; 642 } 643 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { 644 do_seal = true; 645 } 646 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) { 647 want_flags |= GSS_C_DCE_STYLE; 648 } 649 650 nt_status = gse_init_server(gensec_security, do_sign, do_seal, want_flags, 651 &gse_ctx); 652 if (!NT_STATUS_IS_OK(nt_status)) { 653 return nt_status; 654 } 655 gensec_security->private_data = gse_ctx; 656 return NT_STATUS_OK; 657 } 658 659 /** 660 * Next state function for the GSE GENSEC mechanism 661 * 662 * @param gensec_gse_state GSE State 663 * @param mem_ctx The TALLOC_CTX for *out to be allocated on 664 * @param in The request, as a DATA_BLOB 665 * @param out The reply, as an talloc()ed DATA_BLOB, on *mem_ctx 666 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 667 * or NT_STATUS_OK if the user is authenticated. 668 */ 669 670 static NTSTATUS gensec_gse_update(struct gensec_security *gensec_security, 671 TALLOC_CTX *mem_ctx, 672 struct tevent_context *ev, 673 const DATA_BLOB in, DATA_BLOB *out) 674 { 675 NTSTATUS status; 676 struct gse_context *gse_ctx = 677 talloc_get_type_abort(gensec_security->private_data, 678 struct gse_context); 679 680 switch (gensec_security->gensec_role) { 681 case GENSEC_CLIENT: 682 status = gse_get_client_auth_token(mem_ctx, gse_ctx, 683 &in, out); 684 break; 685 case GENSEC_SERVER: 686 status = gse_get_server_auth_token(mem_ctx, gse_ctx, 687 &in, out); 688 break; 689 } 690 if (!NT_STATUS_IS_OK(status)) { 691 return status; 692 } 693 694 return NT_STATUS_OK; 695 } 696 697 static NTSTATUS gensec_gse_wrap(struct gensec_security *gensec_security, 698 TALLOC_CTX *mem_ctx, 699 const DATA_BLOB *in, 700 DATA_BLOB *out) 701 { 702 struct gse_context *gse_ctx = 703 talloc_get_type_abort(gensec_security->private_data, 704 struct gse_context); 705 OM_uint32 maj_stat, min_stat; 706 gss_buffer_desc input_token, output_token; 707 int conf_state; 708 input_token.length = in->length; 709 input_token.value = in->data; 710 711 maj_stat = gss_wrap(&min_stat, 712 gse_ctx->gssapi_context, 713 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL), 714 GSS_C_QOP_DEFAULT, 715 &input_token, 716 &conf_state, 717 &output_token); 718 if (GSS_ERROR(maj_stat)) { 719 DEBUG(0, ("gensec_gse_wrap: GSS Wrap failed: %s\n", 720 gse_errstr(talloc_tos(), maj_stat, min_stat))); 621 721 return NT_STATUS_ACCESS_DENIED; 622 722 } 623 723 624 if (!gse_ctx->client_name) { 625 return NT_STATUS_NOT_FOUND; 626 } 627 628 /* TODO: check OID matches KRB5 Principal Name OID ? */ 629 630 gss_maj = gss_display_name(&gss_min, 631 gse_ctx->client_name, 632 &name_buffer, NULL); 633 if (gss_maj) { 634 DEBUG(0, ("gss_display_name failed [%s]\n", 635 gse_errstr(talloc_tos(), gss_maj, gss_min))); 636 return NT_STATUS_INTERNAL_ERROR; 637 } 638 639 *cli_name = talloc_strndup(talloc_tos(), 640 (char *)name_buffer.value, 641 name_buffer.length); 642 643 gss_maj = gss_release_buffer(&gss_min, &name_buffer); 644 645 if (!*cli_name) { 724 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length); 725 gss_release_buffer(&min_stat, &output_token); 726 727 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) 728 && !conf_state) { 729 return NT_STATUS_ACCESS_DENIED; 730 } 731 return NT_STATUS_OK; 732 } 733 734 static NTSTATUS gensec_gse_unwrap(struct gensec_security *gensec_security, 735 TALLOC_CTX *mem_ctx, 736 const DATA_BLOB *in, 737 DATA_BLOB *out) 738 { 739 struct gse_context *gse_ctx = 740 talloc_get_type_abort(gensec_security->private_data, 741 struct gse_context); 742 OM_uint32 maj_stat, min_stat; 743 gss_buffer_desc input_token, output_token; 744 int conf_state; 745 gss_qop_t qop_state; 746 input_token.length = in->length; 747 input_token.value = in->data; 748 749 maj_stat = gss_unwrap(&min_stat, 750 gse_ctx->gssapi_context, 751 &input_token, 752 &output_token, 753 &conf_state, 754 &qop_state); 755 if (GSS_ERROR(maj_stat)) { 756 DEBUG(0, ("gensec_gse_unwrap: GSS UnWrap failed: %s\n", 757 gse_errstr(talloc_tos(), maj_stat, min_stat))); 758 return NT_STATUS_ACCESS_DENIED; 759 } 760 761 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length); 762 gss_release_buffer(&min_stat, &output_token); 763 764 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL) 765 && !conf_state) { 766 return NT_STATUS_ACCESS_DENIED; 767 } 768 return NT_STATUS_OK; 769 } 770 771 static NTSTATUS gensec_gse_seal_packet(struct gensec_security *gensec_security, 772 TALLOC_CTX *mem_ctx, 773 uint8_t *data, size_t length, 774 const uint8_t *whole_pdu, size_t pdu_length, 775 DATA_BLOB *sig) 776 { 777 struct gse_context *gse_ctx = 778 talloc_get_type_abort(gensec_security->private_data, 779 struct gse_context); 780 bool hdr_signing = false; 781 size_t sig_size = 0; 782 NTSTATUS status; 783 784 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { 785 hdr_signing = true; 786 } 787 788 sig_size = gensec_gse_sig_size(gensec_security, length); 789 790 status = gssapi_seal_packet(gse_ctx->gssapi_context, 791 &gse_ctx->gss_mech, 792 hdr_signing, sig_size, 793 data, length, 794 whole_pdu, pdu_length, 795 mem_ctx, sig); 796 if (!NT_STATUS_IS_OK(status)) { 797 DEBUG(0, ("gssapi_seal_packet(hdr_signing=%u,sig_size=%zu," 798 "data=%zu,pdu=%zu) failed: %s\n", 799 hdr_signing, sig_size, length, pdu_length, 800 nt_errstr(status))); 801 return status; 802 } 803 804 return NT_STATUS_OK; 805 } 806 807 static NTSTATUS gensec_gse_unseal_packet(struct gensec_security *gensec_security, 808 uint8_t *data, size_t length, 809 const uint8_t *whole_pdu, size_t pdu_length, 810 const DATA_BLOB *sig) 811 { 812 struct gse_context *gse_ctx = 813 talloc_get_type_abort(gensec_security->private_data, 814 struct gse_context); 815 bool hdr_signing = false; 816 NTSTATUS status; 817 818 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { 819 hdr_signing = true; 820 } 821 822 status = gssapi_unseal_packet(gse_ctx->gssapi_context, 823 &gse_ctx->gss_mech, 824 hdr_signing, 825 data, length, 826 whole_pdu, pdu_length, 827 sig); 828 if (!NT_STATUS_IS_OK(status)) { 829 DEBUG(0, ("gssapi_unseal_packet(hdr_signing=%u,sig_size=%zu," 830 "data=%zu,pdu=%zu) failed: %s\n", 831 hdr_signing, sig->length, length, pdu_length, 832 nt_errstr(status))); 833 return status; 834 } 835 836 return NT_STATUS_OK; 837 } 838 839 static NTSTATUS gensec_gse_sign_packet(struct gensec_security *gensec_security, 840 TALLOC_CTX *mem_ctx, 841 const uint8_t *data, size_t length, 842 const uint8_t *whole_pdu, size_t pdu_length, 843 DATA_BLOB *sig) 844 { 845 struct gse_context *gse_ctx = 846 talloc_get_type_abort(gensec_security->private_data, 847 struct gse_context); 848 bool hdr_signing = false; 849 NTSTATUS status; 850 851 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { 852 hdr_signing = true; 853 } 854 855 status = gssapi_sign_packet(gse_ctx->gssapi_context, 856 &gse_ctx->gss_mech, 857 hdr_signing, 858 data, length, 859 whole_pdu, pdu_length, 860 mem_ctx, sig); 861 if (!NT_STATUS_IS_OK(status)) { 862 DEBUG(0, ("gssapi_sign_packet(hdr_signing=%u," 863 "data=%zu,pdu=%zu) failed: %s\n", 864 hdr_signing, length, pdu_length, 865 nt_errstr(status))); 866 return status; 867 } 868 869 return NT_STATUS_OK; 870 } 871 872 static NTSTATUS gensec_gse_check_packet(struct gensec_security *gensec_security, 873 const uint8_t *data, size_t length, 874 const uint8_t *whole_pdu, size_t pdu_length, 875 const DATA_BLOB *sig) 876 { 877 struct gse_context *gse_ctx = 878 talloc_get_type_abort(gensec_security->private_data, 879 struct gse_context); 880 bool hdr_signing = false; 881 NTSTATUS status; 882 883 if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) { 884 hdr_signing = true; 885 } 886 887 status = gssapi_check_packet(gse_ctx->gssapi_context, 888 &gse_ctx->gss_mech, 889 hdr_signing, 890 data, length, 891 whole_pdu, pdu_length, 892 sig); 893 if (!NT_STATUS_IS_OK(status)) { 894 DEBUG(0, ("gssapi_check_packet(hdr_signing=%u,sig_size=%zu" 895 "data=%zu,pdu=%zu) failed: %s\n", 896 hdr_signing, sig->length, length, pdu_length, 897 nt_errstr(status))); 898 return status; 899 } 900 901 return NT_STATUS_OK; 902 } 903 904 /* Try to figure out what features we actually got on the connection */ 905 static bool gensec_gse_have_feature(struct gensec_security *gensec_security, 906 uint32_t feature) 907 { 908 struct gse_context *gse_ctx = 909 talloc_get_type_abort(gensec_security->private_data, 910 struct gse_context); 911 912 if (feature & GENSEC_FEATURE_SESSION_KEY) { 913 return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG; 914 } 915 if (feature & GENSEC_FEATURE_SIGN) { 916 return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG; 917 } 918 if (feature & GENSEC_FEATURE_SEAL) { 919 return gse_ctx->gss_got_flags & GSS_C_CONF_FLAG; 920 } 921 if (feature & GENSEC_FEATURE_DCE_STYLE) { 922 return gse_ctx->gss_got_flags & GSS_C_DCE_STYLE; 923 } 924 if (feature & GENSEC_FEATURE_NEW_SPNEGO) { 925 NTSTATUS status; 926 uint32_t keytype; 927 928 if (!(gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG)) { 929 return false; 930 } 931 932 status = gssapi_get_session_key(talloc_tos(), 933 gse_ctx->gssapi_context, NULL, &keytype); 934 /* 935 * We should do a proper sig on the mechListMic unless 936 * we know we have to be backwards compatible with 937 * earlier windows versions. 938 * 939 * Negotiating a non-krb5 940 * mech for example should be regarded as having 941 * NEW_SPNEGO 942 */ 943 if (NT_STATUS_IS_OK(status)) { 944 switch (keytype) { 945 case ENCTYPE_DES_CBC_CRC: 946 case ENCTYPE_DES_CBC_MD5: 947 case ENCTYPE_ARCFOUR_HMAC: 948 case ENCTYPE_DES3_CBC_SHA1: 949 return false; 950 } 951 } 952 return true; 953 } 954 /* We can always do async (rather than strict request/reply) packets. */ 955 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) { 956 return true; 957 } 958 if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) { 959 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { 960 return true; 961 } 962 963 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { 964 return true; 965 } 966 967 return false; 968 } 969 return false; 970 } 971 972 static NTTIME gensec_gse_expire_time(struct gensec_security *gensec_security) 973 { 974 struct gse_context *gse_ctx = 975 talloc_get_type_abort(gensec_security->private_data, 976 struct gse_context); 977 978 return gse_ctx->expire_time; 979 } 980 981 /* 982 * Extract the 'sesssion key' needed by SMB signing and ncacn_np 983 * (for encrypting some passwords). 984 * 985 * This breaks all the abstractions, but what do you expect... 986 */ 987 static NTSTATUS gensec_gse_session_key(struct gensec_security *gensec_security, 988 TALLOC_CTX *mem_ctx, 989 DATA_BLOB *session_key) 990 { 991 struct gse_context *gse_ctx = 992 talloc_get_type_abort(gensec_security->private_data, 993 struct gse_context); 994 995 return gssapi_get_session_key(mem_ctx, gse_ctx->gssapi_context, session_key, NULL); 996 } 997 998 /* Get some basic (and authorization) information about the user on 999 * this session. This uses either the PAC (if present) or a local 1000 * database lookup */ 1001 static NTSTATUS gensec_gse_session_info(struct gensec_security *gensec_security, 1002 TALLOC_CTX *mem_ctx, 1003 struct auth_session_info **_session_info) 1004 { 1005 struct gse_context *gse_ctx = 1006 talloc_get_type_abort(gensec_security->private_data, 1007 struct gse_context); 1008 NTSTATUS nt_status; 1009 TALLOC_CTX *tmp_ctx; 1010 struct auth_session_info *session_info = NULL; 1011 OM_uint32 maj_stat, min_stat; 1012 DATA_BLOB pac_blob, *pac_blob_ptr = NULL; 1013 1014 gss_buffer_desc name_token; 1015 char *principal_string; 1016 1017 tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gse_session_info context"); 1018 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); 1019 1020 maj_stat = gss_display_name(&min_stat, 1021 gse_ctx->client_name, 1022 &name_token, 1023 NULL); 1024 if (GSS_ERROR(maj_stat)) { 1025 DEBUG(1, ("GSS display_name failed: %s\n", 1026 gse_errstr(talloc_tos(), maj_stat, min_stat))); 1027 talloc_free(tmp_ctx); 1028 return NT_STATUS_FOOBAR; 1029 } 1030 1031 principal_string = talloc_strndup(tmp_ctx, 1032 (const char *)name_token.value, 1033 name_token.length); 1034 1035 gss_release_buffer(&min_stat, &name_token); 1036 1037 if (!principal_string) { 1038 talloc_free(tmp_ctx); 646 1039 return NT_STATUS_NO_MEMORY; 647 1040 } 648 1041 1042 nt_status = gssapi_obtain_pac_blob(tmp_ctx, gse_ctx->gssapi_context, 1043 gse_ctx->client_name, 1044 &pac_blob); 1045 1046 /* IF we have the PAC - otherwise we need to get this 1047 * data from elsewere 1048 */ 1049 if (NT_STATUS_IS_OK(nt_status)) { 1050 pac_blob_ptr = &pac_blob; 1051 } 1052 nt_status = gensec_generate_session_info_pac(tmp_ctx, 1053 gensec_security, 1054 NULL, 1055 pac_blob_ptr, principal_string, 1056 gensec_get_remote_address(gensec_security), 1057 &session_info); 1058 if (!NT_STATUS_IS_OK(nt_status)) { 1059 talloc_free(tmp_ctx); 1060 return nt_status; 1061 } 1062 1063 nt_status = gensec_gse_session_key(gensec_security, session_info, 1064 &session_info->session_key); 1065 if (!NT_STATUS_IS_OK(nt_status)) { 1066 talloc_free(tmp_ctx); 1067 return nt_status; 1068 } 1069 1070 *_session_info = talloc_move(mem_ctx, &session_info); 1071 talloc_free(tmp_ctx); 1072 649 1073 return NT_STATUS_OK; 650 1074 } 651 1075 652 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx, 653 TALLOC_CTX *mem_ctx, DATA_BLOB *pac) 654 { 655 OM_uint32 gss_min, gss_maj; 656 gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; 657 658 if (!gse_ctx->authenticated) { 659 return NT_STATUS_ACCESS_DENIED; 660 } 661 662 gss_maj = gss_inquire_sec_context_by_oid( 663 &gss_min, gse_ctx->gss_ctx, 664 &gse_authz_data_oid, &set); 665 if (gss_maj) { 666 DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n", 667 gse_errstr(talloc_tos(), gss_maj, gss_min))); 668 return NT_STATUS_NOT_FOUND; 669 } 670 671 if (set == GSS_C_NO_BUFFER_SET) { 672 DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown " 673 "data in results.\n")); 674 return NT_STATUS_INTERNAL_ERROR; 675 } 676 677 /* for now we just hope it is the first value */ 678 *pac = data_blob_talloc(mem_ctx, 679 set->elements[0].value, 680 set->elements[0].length); 681 682 gss_maj = gss_release_buffer_set(&gss_min, &set); 683 684 return NT_STATUS_OK; 685 } 686 687 NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx, 688 TALLOC_CTX *mem_ctx, DATA_BLOB *pac_blob) 689 { 690 OM_uint32 gss_min, gss_maj; 691 /* 692 * gss_get_name_attribute() in MIT krb5 1.10.0 can return unintialized pac_display_buffer 693 * and later gss_release_buffer() will crash on attempting to release it. 694 * 695 * So always initialize the buffer descriptors. 696 * 697 * See following links for more details: 698 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=658514 699 * http://krbdev.mit.edu/rt/Ticket/Display.html?user=guest&pass=guest&id=7087 700 */ 701 gss_buffer_desc pac_buffer = { 702 .value = NULL, 703 .length = 0 704 }; 705 gss_buffer_desc pac_display_buffer = { 706 .value = NULL, 707 .length = 0 708 }; 709 gss_buffer_desc pac_name = { 710 .value = discard_const_p(char, "urn:mspac:"), 711 .length = sizeof("urn:mspac:") - 1 712 }; 713 int more = -1; 714 int authenticated = false; 715 int complete = false; 716 NTSTATUS status; 717 718 if (!gse_ctx->authenticated) { 719 return NT_STATUS_ACCESS_DENIED; 720 } 721 722 gss_maj = gss_get_name_attribute(&gss_min, 723 gse_ctx->client_name, &pac_name, 724 &authenticated, &complete, 725 &pac_buffer, &pac_display_buffer, 726 &more); 727 728 if (gss_maj != 0) { 729 DEBUG(0, ("obtaining PAC via GSSAPI gss_get_name_attribute " 730 "failed: %s\n", 731 gse_errstr(mem_ctx, gss_maj, gss_min))); 732 return NT_STATUS_ACCESS_DENIED; 733 } 734 735 if (authenticated && complete) { 736 /* The PAC blob is returned directly */ 737 *pac_blob = data_blob_talloc(mem_ctx, 738 pac_buffer.value, 739 pac_buffer.length); 740 if (!pac_blob->data) { 741 status = NT_STATUS_NO_MEMORY; 742 } else { 743 status = NT_STATUS_OK; 744 } 745 746 gss_maj = gss_release_buffer(&gss_min, &pac_buffer); 747 gss_maj = gss_release_buffer(&gss_min, &pac_display_buffer); 748 749 return status; 750 } 751 752 DEBUG(0, ("obtaining PAC via GSSAPI failed: authenticated: %s, " 753 "complete: %s, more: %s\n", 754 authenticated ? "true" : "false", 755 complete ? "true" : "false", 756 more ? "true" : "false")); 757 758 return NT_STATUS_ACCESS_DENIED; 759 } 760 761 size_t gse_get_signature_length(struct gse_context *gse_ctx, 762 int seal, size_t payload_size) 763 { 764 OM_uint32 gss_min, gss_maj; 765 gss_iov_buffer_desc iov[2]; 766 uint8_t fakebuf[payload_size]; 767 int sealed; 768 769 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; 770 iov[0].buffer.value = NULL; 771 iov[0].buffer.length = 0; 772 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; 773 iov[1].buffer.value = fakebuf; 774 iov[1].buffer.length = payload_size; 775 776 gss_maj = gss_wrap_iov_length(&gss_min, gse_ctx->gss_ctx, 777 seal, GSS_C_QOP_DEFAULT, 778 &sealed, iov, 2); 779 if (gss_maj) { 780 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n", 781 gse_errstr(talloc_tos(), gss_maj, gss_min))); 1076 static size_t gensec_gse_max_input_size(struct gensec_security *gensec_security) 1077 { 1078 struct gse_context *gse_ctx = 1079 talloc_get_type_abort(gensec_security->private_data, 1080 struct gse_context); 1081 OM_uint32 maj_stat, min_stat; 1082 OM_uint32 max_input_size; 1083 1084 maj_stat = gss_wrap_size_limit(&min_stat, 1085 gse_ctx->gssapi_context, 1086 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL), 1087 GSS_C_QOP_DEFAULT, 1088 gse_ctx->max_wrap_buf_size, 1089 &max_input_size); 1090 if (GSS_ERROR(maj_stat)) { 1091 TALLOC_CTX *mem_ctx = talloc_new(NULL); 1092 DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n", 1093 gse_errstr(mem_ctx, maj_stat, min_stat))); 1094 talloc_free(mem_ctx); 782 1095 return 0; 783 1096 } 784 1097 785 return iov[0].buffer.length; 786 } 787 788 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 789 DATA_BLOB *data, DATA_BLOB *signature) 790 { 791 OM_uint32 gss_min, gss_maj; 792 gss_iov_buffer_desc iov[2]; 793 int req_seal = 1; /* setting to 1 means we request sign+seal */ 794 int sealed; 795 NTSTATUS status; 796 797 /* allocate the memory ourselves so we do not need to talloc_memdup */ 798 signature->length = gse_get_signature_length(gse_ctx, 1, data->length); 799 if (!signature->length) { 800 return NT_STATUS_INTERNAL_ERROR; 801 } 802 signature->data = (uint8_t *)talloc_size(mem_ctx, signature->length); 803 if (!signature->data) { 804 return NT_STATUS_NO_MEMORY; 805 } 806 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; 807 iov[0].buffer.value = signature->data; 808 iov[0].buffer.length = signature->length; 809 810 /* data is encrypted in place, which is ok */ 811 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; 812 iov[1].buffer.value = data->data; 813 iov[1].buffer.length = data->length; 814 815 gss_maj = gss_wrap_iov(&gss_min, gse_ctx->gss_ctx, 816 req_seal, GSS_C_QOP_DEFAULT, 817 &sealed, iov, 2); 818 if (gss_maj) { 819 DEBUG(0, ("gss_wrap_iov failed with [%s]\n", 820 gse_errstr(talloc_tos(), gss_maj, gss_min))); 821 status = NT_STATUS_ACCESS_DENIED; 822 goto done; 823 } 824 825 if (!sealed) { 826 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n")); 827 status = NT_STATUS_ACCESS_DENIED; 828 goto done; 829 } 830 831 status = NT_STATUS_OK; 832 833 DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n", 834 (int)iov[1].buffer.length, (int)iov[0].buffer.length)); 835 836 done: 837 return status; 838 } 839 840 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 841 DATA_BLOB *data, DATA_BLOB *signature) 842 { 843 OM_uint32 gss_min, gss_maj; 844 gss_iov_buffer_desc iov[2]; 845 int sealed; 846 NTSTATUS status; 847 848 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; 849 iov[0].buffer.value = signature->data; 850 iov[0].buffer.length = signature->length; 851 852 /* data is decrypted in place, which is ok */ 853 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; 854 iov[1].buffer.value = data->data; 855 iov[1].buffer.length = data->length; 856 857 gss_maj = gss_unwrap_iov(&gss_min, gse_ctx->gss_ctx, 858 &sealed, NULL, iov, 2); 859 if (gss_maj) { 860 DEBUG(0, ("gss_unwrap_iov failed with [%s]\n", 861 gse_errstr(talloc_tos(), gss_maj, gss_min))); 862 status = NT_STATUS_ACCESS_DENIED; 863 goto done; 864 } 865 866 if (!sealed) { 867 DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n")); 868 status = NT_STATUS_ACCESS_DENIED; 869 goto done; 870 } 871 872 status = NT_STATUS_OK; 873 874 DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n", 875 (int)iov[1].buffer.length, (int)iov[0].buffer.length)); 876 877 done: 878 return status; 879 } 880 881 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 882 DATA_BLOB *data, DATA_BLOB *signature) 883 { 884 OM_uint32 gss_min, gss_maj; 885 gss_buffer_desc in_data = { 0, NULL }; 886 gss_buffer_desc out_data = { 0, NULL}; 887 NTSTATUS status; 888 889 in_data.value = data->data; 890 in_data.length = data->length; 891 892 gss_maj = gss_get_mic(&gss_min, gse_ctx->gss_ctx, 893 GSS_C_QOP_DEFAULT, 894 &in_data, &out_data); 895 if (gss_maj) { 896 DEBUG(0, ("gss_get_mic failed with [%s]\n", 897 gse_errstr(talloc_tos(), gss_maj, gss_min))); 898 status = NT_STATUS_ACCESS_DENIED; 899 goto done; 900 } 901 902 *signature = data_blob_talloc(mem_ctx, 903 out_data.value, out_data.length); 904 if (!signature->data) { 905 status = NT_STATUS_NO_MEMORY; 906 goto done; 907 } 908 909 status = NT_STATUS_OK; 910 911 done: 912 if (out_data.value) { 913 gss_maj = gss_release_buffer(&gss_min, &out_data); 914 } 915 return status; 916 } 917 918 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 919 DATA_BLOB *data, DATA_BLOB *signature) 920 { 921 OM_uint32 gss_min, gss_maj; 922 gss_buffer_desc in_data = { 0, NULL }; 923 gss_buffer_desc in_token = { 0, NULL}; 924 NTSTATUS status; 925 926 in_data.value = data->data; 927 in_data.length = data->length; 928 in_token.value = signature->data; 929 in_token.length = signature->length; 930 931 gss_maj = gss_verify_mic(&gss_min, gse_ctx->gss_ctx, 932 &in_data, &in_token, NULL); 933 if (gss_maj) { 934 DEBUG(0, ("gss_verify_mic failed with [%s]\n", 935 gse_errstr(talloc_tos(), gss_maj, gss_min))); 936 status = NT_STATUS_ACCESS_DENIED; 937 goto done; 938 } 939 940 status = NT_STATUS_OK; 941 942 done: 943 return status; 944 } 945 946 #else 947 948 NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, 949 bool do_sign, bool do_seal, 950 const char *ccache_name, 951 const char *server, 952 const char *service, 953 const char *username, 954 const char *password, 955 uint32_t add_gss_c_flags, 956 struct gse_context **_gse_ctx) 957 { 958 return NT_STATUS_NOT_IMPLEMENTED; 959 } 960 961 NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, 962 struct gse_context *gse_ctx, 963 DATA_BLOB *token_in, 964 DATA_BLOB *token_out) 965 { 966 return NT_STATUS_NOT_IMPLEMENTED; 967 } 968 969 NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx, 970 bool do_sign, bool do_seal, 971 uint32_t add_gss_c_flags, 972 const char *keytab, 973 struct gse_context **_gse_ctx) 974 { 975 return NT_STATUS_NOT_IMPLEMENTED; 976 } 977 978 NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx, 979 struct gse_context *gse_ctx, 980 DATA_BLOB *token_in, 981 DATA_BLOB *token_out) 982 { 983 return NT_STATUS_NOT_IMPLEMENTED; 984 } 985 986 NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx) 987 { 988 return NT_STATUS_NOT_IMPLEMENTED; 989 } 990 991 bool gse_require_more_processing(struct gse_context *gse_ctx) 992 { 993 return false; 994 } 995 996 DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx, 997 struct gse_context *gse_ctx) 998 { 999 return data_blob_null; 1000 } 1001 1002 NTSTATUS gse_get_client_name(struct gse_context *gse_ctx, 1003 TALLOC_CTX *mem_ctx, char **cli_name) 1004 { 1005 return NT_STATUS_NOT_IMPLEMENTED; 1006 } 1007 1008 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx, 1009 TALLOC_CTX *mem_ctx, DATA_BLOB *pac) 1010 { 1011 return NT_STATUS_NOT_IMPLEMENTED; 1012 } 1013 1014 NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx, 1015 TALLOC_CTX *mem_ctx, DATA_BLOB *pac) 1016 { 1017 return NT_STATUS_NOT_IMPLEMENTED; 1018 } 1019 1020 size_t gse_get_signature_length(struct gse_context *gse_ctx, 1021 int seal, size_t payload_size) 1022 { 1023 return 0; 1024 } 1025 1026 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 1027 DATA_BLOB *data, DATA_BLOB *signature) 1028 { 1029 return NT_STATUS_NOT_IMPLEMENTED; 1030 } 1031 1032 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 1033 DATA_BLOB *data, DATA_BLOB *signature) 1034 { 1035 return NT_STATUS_NOT_IMPLEMENTED; 1036 } 1037 1038 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 1039 DATA_BLOB *data, DATA_BLOB *signature) 1040 { 1041 return NT_STATUS_NOT_IMPLEMENTED; 1042 } 1043 1044 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 1045 DATA_BLOB *data, DATA_BLOB *signature) 1046 { 1047 return NT_STATUS_NOT_IMPLEMENTED; 1048 } 1049 1050 #endif /* HAVE_KRB5 && HAVE_GSSAPI_EXT_H && HAVE_GSS_WRAP_IOV */ 1098 return max_input_size; 1099 } 1100 1101 /* Find out the maximum output size negotiated on this connection */ 1102 static size_t gensec_gse_max_wrapped_size(struct gensec_security *gensec_security) 1103 { 1104 struct gse_context *gse_ctx = 1105 talloc_get_type_abort(gensec_security->private_data, 1106 struct gse_context); 1107 return gse_ctx->max_wrap_buf_size; 1108 } 1109 1110 static size_t gensec_gse_sig_size(struct gensec_security *gensec_security, 1111 size_t data_size) 1112 { 1113 struct gse_context *gse_ctx = 1114 talloc_get_type_abort(gensec_security->private_data, 1115 struct gse_context); 1116 1117 if (gse_ctx->sig_size > 0) { 1118 return gse_ctx->sig_size; 1119 } 1120 1121 gse_ctx->sig_size = gssapi_get_sig_size(gse_ctx->gssapi_context, 1122 &gse_ctx->gss_mech, 1123 gse_ctx->gss_want_flags, 1124 data_size); 1125 return gse_ctx->sig_size; 1126 } 1127 1128 static const char *gensec_gse_krb5_oids[] = { 1129 GENSEC_OID_KERBEROS5_OLD, 1130 GENSEC_OID_KERBEROS5, 1131 NULL 1132 }; 1133 1134 const struct gensec_security_ops gensec_gse_krb5_security_ops = { 1135 .name = "gse_krb5", 1136 .auth_type = DCERPC_AUTH_TYPE_KRB5, 1137 .oid = gensec_gse_krb5_oids, 1138 .client_start = gensec_gse_client_start, 1139 .server_start = gensec_gse_server_start, 1140 .magic = gensec_magic_check_krb5_oid, 1141 .update = gensec_gse_update, 1142 .session_key = gensec_gse_session_key, 1143 .session_info = gensec_gse_session_info, 1144 .sig_size = gensec_gse_sig_size, 1145 .sign_packet = gensec_gse_sign_packet, 1146 .check_packet = gensec_gse_check_packet, 1147 .seal_packet = gensec_gse_seal_packet, 1148 .unseal_packet = gensec_gse_unseal_packet, 1149 .max_input_size = gensec_gse_max_input_size, 1150 .max_wrapped_size = gensec_gse_max_wrapped_size, 1151 .wrap = gensec_gse_wrap, 1152 .unwrap = gensec_gse_unwrap, 1153 .have_feature = gensec_gse_have_feature, 1154 .expire_time = gensec_gse_expire_time, 1155 .enabled = true, 1156 .kerberos = true, 1157 .priority = GENSEC_GSSAPI 1158 }; 1159 1160 #endif /* HAVE_KRB5 */ -
vendor/current/source3/librpc/crypto/gse.h
r740 r988 22 22 struct gse_context; 23 23 24 #ifndef GSS_C_DCE_STYLE 25 #define GSS_C_DCE_STYLE 0x1000 26 #endif 27 28 NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, 29 bool do_sign, bool do_seal, 30 const char *ccache_name, 31 const char *server, 32 const char *service, 33 const char *username, 34 const char *password, 35 uint32_t add_gss_c_flags, 36 struct gse_context **_gse_ctx); 37 NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, 38 struct gse_context *gse_ctx, 39 DATA_BLOB *token_in, 40 DATA_BLOB *token_out); 41 42 NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx, 43 bool do_sign, bool do_seal, 44 uint32_t add_gss_c_flags, 45 const char *keytab, 46 struct gse_context **_gse_ctx); 47 NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx, 48 struct gse_context *gse_ctx, 49 DATA_BLOB *token_in, 50 DATA_BLOB *token_out); 51 NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx); 52 53 bool gse_require_more_processing(struct gse_context *gse_ctx); 54 DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx, 55 struct gse_context *gse_ctx); 56 NTSTATUS gse_get_client_name(struct gse_context *gse_ctx, 57 TALLOC_CTX *mem_ctx, char **client_name); 58 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx, 59 TALLOC_CTX *mem_ctx, DATA_BLOB *pac); 60 NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx, 61 TALLOC_CTX *mem_ctx, DATA_BLOB *pac); 62 63 size_t gse_get_signature_length(struct gse_context *gse_ctx, 64 int seal, size_t payload_size); 65 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 66 DATA_BLOB *data, DATA_BLOB *signature); 67 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 68 DATA_BLOB *data, DATA_BLOB *signature); 69 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 70 DATA_BLOB *data, DATA_BLOB *signature); 71 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx, 72 DATA_BLOB *data, DATA_BLOB *signature); 24 extern const struct gensec_security_ops gensec_gse_krb5_security_ops; 73 25 74 26 #endif /* _GSE_H_ */ -
vendor/current/source3/librpc/crypto/gse_krb5.c
r740 r988 22 22 #include "secrets.h" 23 23 #include "gse_krb5.h" 24 #include "lib/param/loadparm.h" 24 25 25 26 #ifdef HAVE_KRB5 … … 91 92 int err; 92 93 93 err = asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());94 err = asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm()); 94 95 if (err == -1) { 95 96 return -1; 96 97 } 97 98 98 strlower_m(host_princ_s); 99 if (!strlower_m(host_princ_s)) { 100 SAFE_FREE(host_princ_s); 101 return -1; 102 } 99 103 ret = smb_krb5_parse_name(krbctx, host_princ_s, host_princ); 100 104 if (ret) { … … 170 174 #define CLEARTEXT_PRIV_ENCTYPE -99 171 175 172 static krb5_error_code get_mem_keytab_from_secrets(krb5_context krbctx,173 krb5_keytab *keytab)176 static krb5_error_code fill_mem_keytab_from_secrets(krb5_context krbctx, 177 krb5_keytab *keytab) 174 178 { 175 179 krb5_error_code ret; … … 194 198 } 195 199 pwd_len = strlen(pwd); 196 197 if (*keytab == NULL) {198 /* create memory keytab */199 ret = krb5_kt_resolve(krbctx, SRV_MEM_KEYTAB_NAME, keytab);200 if (ret) {201 DEBUG(1, (__location__ ": Failed to get memory "202 "keytab!\n"));203 return ret;204 }205 }206 200 207 201 ZERO_STRUCT(kt_entry); … … 281 275 } 282 276 283 pwd_old = secrets_fetch_ machine_password(lp_workgroup(), NULL, NULL);277 pwd_old = secrets_fetch_prev_machine_password(lp_workgroup()); 284 278 if (!pwd_old) { 285 279 DEBUG(10, (__location__ ": no prev machine password\n")); … … 332 326 } 333 327 334 if (ret) {335 if (*keytab) {336 krb5_kt_close(krbctx, *keytab);337 *keytab = NULL;338 }339 }340 341 328 return ret; 342 329 } 343 330 344 static krb5_error_code get_mem_keytab_from_system_keytab(krb5_context krbctx, 345 krb5_keytab *keytab, 346 bool verify) 331 static krb5_error_code fill_mem_keytab_from_system_keytab(krb5_context krbctx, 332 krb5_keytab *mkeytab) 347 333 { 348 return KRB5_KT_NOTFOUND; 334 krb5_error_code ret = 0; 335 krb5_keytab keytab = NULL; 336 krb5_kt_cursor kt_cursor; 337 krb5_keytab_entry kt_entry; 338 char *valid_princ_formats[7] = { NULL, NULL, NULL, 339 NULL, NULL, NULL, NULL }; 340 char *entry_princ_s = NULL; 341 fstring my_name, my_fqdn; 342 int i; 343 int err; 344 345 /* Generate the list of principal names which we expect 346 * clients might want to use for authenticating to the file 347 * service. We allow name$,{host,cifs}/{name,fqdn,name.REALM}. */ 348 349 fstrcpy(my_name, lp_netbios_name()); 350 351 my_fqdn[0] = '\0'; 352 name_to_fqdn(my_fqdn, lp_netbios_name()); 353 354 err = asprintf(&valid_princ_formats[0], 355 "%s$@%s", my_name, lp_realm()); 356 if (err == -1) { 357 ret = ENOMEM; 358 goto out; 359 } 360 err = asprintf(&valid_princ_formats[1], 361 "host/%s@%s", my_name, lp_realm()); 362 if (err == -1) { 363 ret = ENOMEM; 364 goto out; 365 } 366 err = asprintf(&valid_princ_formats[2], 367 "host/%s@%s", my_fqdn, lp_realm()); 368 if (err == -1) { 369 ret = ENOMEM; 370 goto out; 371 } 372 err = asprintf(&valid_princ_formats[3], 373 "host/%s.%s@%s", my_name, lp_realm(), lp_realm()); 374 if (err == -1) { 375 ret = ENOMEM; 376 goto out; 377 } 378 err = asprintf(&valid_princ_formats[4], 379 "cifs/%s@%s", my_name, lp_realm()); 380 if (err == -1) { 381 ret = ENOMEM; 382 goto out; 383 } 384 err = asprintf(&valid_princ_formats[5], 385 "cifs/%s@%s", my_fqdn, lp_realm()); 386 if (err == -1) { 387 ret = ENOMEM; 388 goto out; 389 } 390 err = asprintf(&valid_princ_formats[6], 391 "cifs/%s.%s@%s", my_name, lp_realm(), lp_realm()); 392 if (err == -1) { 393 ret = ENOMEM; 394 goto out; 395 } 396 397 ZERO_STRUCT(kt_entry); 398 ZERO_STRUCT(kt_cursor); 399 400 ret = smb_krb5_open_keytab(krbctx, NULL, false, &keytab); 401 if (ret) { 402 DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n", 403 error_message(ret))); 404 goto out; 405 } 406 407 /* 408 * Iterate through the keytab. For each key, if the principal 409 * name case-insensitively matches one of the allowed formats, 410 * copy it to the memory keytab. 411 */ 412 413 ret = krb5_kt_start_seq_get(krbctx, keytab, &kt_cursor); 414 if (ret) { 415 DEBUG(1, (__location__ ": krb5_kt_start_seq_get failed (%s)\n", 416 error_message(ret))); 417 goto out; 418 } 419 420 while ((krb5_kt_next_entry(krbctx, keytab, 421 &kt_entry, &kt_cursor) == 0)) { 422 ret = smb_krb5_unparse_name(talloc_tos(), krbctx, 423 kt_entry.principal, 424 &entry_princ_s); 425 if (ret) { 426 DEBUG(1, (__location__ ": smb_krb5_unparse_name " 427 "failed (%s)\n", error_message(ret))); 428 goto out; 429 } 430 431 for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) { 432 433 if (!strequal(entry_princ_s, valid_princ_formats[i])) { 434 continue; 435 } 436 437 ret = krb5_kt_add_entry(krbctx, *mkeytab, &kt_entry); 438 if (ret) { 439 DEBUG(1, (__location__ ": smb_krb5_unparse_name " 440 "failed (%s)\n", error_message(ret))); 441 goto out; 442 } 443 } 444 445 /* Free the name we parsed. */ 446 TALLOC_FREE(entry_princ_s); 447 448 /* Free the entry we just read. */ 449 smb_krb5_kt_free_entry(krbctx, &kt_entry); 450 ZERO_STRUCT(kt_entry); 451 } 452 krb5_kt_end_seq_get(krbctx, keytab, &kt_cursor); 453 454 ZERO_STRUCT(kt_cursor); 455 456 out: 457 458 for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) { 459 SAFE_FREE(valid_princ_formats[i]); 460 } 461 462 TALLOC_FREE(entry_princ_s); 463 464 { 465 krb5_keytab_entry zero_kt_entry; 466 ZERO_STRUCT(zero_kt_entry); 467 if (memcmp(&zero_kt_entry, &kt_entry, 468 sizeof(krb5_keytab_entry))) { 469 smb_krb5_kt_free_entry(krbctx, &kt_entry); 470 } 471 } 472 473 { 474 krb5_kt_cursor zero_csr; 475 ZERO_STRUCT(zero_csr); 476 if ((memcmp(&kt_cursor, &zero_csr, 477 sizeof(krb5_kt_cursor)) != 0) && keytab) { 478 krb5_kt_end_seq_get(krbctx, keytab, &kt_cursor); 479 } 480 } 481 482 if (keytab) { 483 krb5_kt_close(krbctx, keytab); 484 } 485 486 return ret; 487 } 488 489 static krb5_error_code fill_mem_keytab_from_dedicated_keytab(krb5_context krbctx, 490 krb5_keytab *mkeytab) 491 { 492 krb5_error_code ret = 0; 493 krb5_keytab keytab = NULL; 494 krb5_kt_cursor kt_cursor; 495 krb5_keytab_entry kt_entry; 496 497 ret = smb_krb5_open_keytab(krbctx, lp_dedicated_keytab_file(), 498 false, &keytab); 499 if (ret) { 500 DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n", 501 error_message(ret))); 502 return ret; 503 } 504 505 /* 506 * Iterate through the keytab. For each key, if the principal 507 * name case-insensitively matches one of the allowed formats, 508 * copy it to the memory keytab. 509 */ 510 511 ret = krb5_kt_start_seq_get(krbctx, keytab, &kt_cursor); 512 if (ret) { 513 DEBUG(1, (__location__ ": krb5_kt_start_seq_get failed (%s)\n", 514 error_message(ret))); 515 goto out; 516 } 517 518 while ((krb5_kt_next_entry(krbctx, keytab, 519 &kt_entry, &kt_cursor) == 0)) { 520 521 ret = krb5_kt_add_entry(krbctx, *mkeytab, &kt_entry); 522 523 /* Free the entry we just read. */ 524 smb_krb5_kt_free_entry(krbctx, &kt_entry); 525 526 if (ret) { 527 DEBUG(1, (__location__ ": smb_krb5_unparse_name " 528 "failed (%s)\n", error_message(ret))); 529 break; 530 } 531 } 532 krb5_kt_end_seq_get(krbctx, keytab, &kt_cursor); 533 534 out: 535 536 krb5_kt_close(krbctx, keytab); 537 538 return ret; 349 539 } 350 540 … … 352 542 krb5_keytab *keytab) 353 543 { 354 krb5_error_code ret; 544 krb5_error_code ret = 0; 545 krb5_error_code ret1 = 0; 546 krb5_error_code ret2 = 0; 355 547 356 548 *keytab = NULL; 549 550 /* create memory keytab */ 551 ret = krb5_kt_resolve(krbctx, SRV_MEM_KEYTAB_NAME, keytab); 552 if (ret) { 553 DEBUG(1, (__location__ ": Failed to get memory " 554 "keytab!\n")); 555 return ret; 556 } 357 557 358 558 switch (lp_kerberos_method()) { 359 559 default: 360 560 case KERBEROS_VERIFY_SECRETS: 361 ret = get_mem_keytab_from_secrets(krbctx, keytab);561 ret = fill_mem_keytab_from_secrets(krbctx, keytab); 362 562 break; 363 563 case KERBEROS_VERIFY_SYSTEM_KEYTAB: 364 ret = get_mem_keytab_from_system_keytab(krbctx, keytab, true);564 ret = fill_mem_keytab_from_system_keytab(krbctx, keytab); 365 565 break; 366 566 case KERBEROS_VERIFY_DEDICATED_KEYTAB: 367 567 /* just use whatever keytab is configured */ 368 ret = get_mem_keytab_from_system_keytab(krbctx, keytab, false);568 ret = fill_mem_keytab_from_dedicated_keytab(krbctx, keytab); 369 569 break; 370 570 case KERBEROS_VERIFY_SECRETS_AND_KEYTAB: 371 ret = get_mem_keytab_from_secrets(krbctx, keytab);372 if (ret ) {571 ret1 = fill_mem_keytab_from_secrets(krbctx, keytab); 572 if (ret1) { 373 573 DEBUG(3, (__location__ ": Warning! Unable to set mem " 374 574 "keytab from secrets!\n")); 375 575 } 376 576 /* Now append system keytab keys too */ 377 ret = get_mem_keytab_from_system_keytab(krbctx, keytab, true);378 if (ret ) {577 ret2 = fill_mem_keytab_from_system_keytab(krbctx, keytab); 578 if (ret2) { 379 579 DEBUG(3, (__location__ ": Warning! Unable to set mem " 380 "keytab from secrets!\n")); 580 "keytab from system keytab!\n")); 581 } 582 if (ret1 == 0 || ret2 == 0) { 583 ret = 0; 584 } else { 585 ret = ret1; 381 586 } 382 587 break; 588 } 589 590 if (ret) { 591 krb5_kt_close(krbctx, *keytab); 592 *keytab = NULL; 593 DEBUG(1,("%s: Error! Unable to set mem keytab - %d\n", 594 __location__, ret)); 383 595 } 384 596
Note:
See TracChangeset
for help on using the changeset viewer.