⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gensec_gssapi.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* If we are going GSSAPI SASL, then we honour the second negotiation */		if (gensec_gssapi_state->sasl 		    && gensec_gssapi_state->sasl_state == STAGE_DONE) {			return ((gensec_gssapi_state->sasl_protection & NEG_SIGN) 				&& (gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG));		}		return gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG;	}	if (feature & GENSEC_FEATURE_SEAL) {		/* If we are going GSSAPI SASL, then we honour the second negotiation */		if (gensec_gssapi_state->sasl 		    && gensec_gssapi_state->sasl_state == STAGE_DONE) {			return ((gensec_gssapi_state->sasl_protection & NEG_SEAL) 				 && (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG));		}		return gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG;	}	if (feature & GENSEC_FEATURE_SESSION_KEY) {		/* Only for GSSAPI/Krb5 */		if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {			return true;		}	}	if (feature & GENSEC_FEATURE_DCE_STYLE) {		return gensec_gssapi_state->got_flags & GSS_C_DCE_STYLE;	}	/* We can always do async (rather than strict request/reply) packets.  */	if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {		return true;	}	return false;}/* * Extract the 'sesssion key' needed by SMB signing and ncacn_np  * (for encrypting some passwords). *  * This breaks all the abstractions, but what do you expect... */static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security, 					  DATA_BLOB *session_key) {	struct gensec_gssapi_state *gensec_gssapi_state		= talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);	OM_uint32 maj_stat, min_stat;	krb5_keyblock *subkey;	if (gensec_gssapi_state->session_key.data) {		*session_key = gensec_gssapi_state->session_key;		return NT_STATUS_OK;	}	maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 						gensec_gssapi_state->gssapi_context,						&subkey);	if (maj_stat != 0) {		DEBUG(1, ("NO session key for this mech\n"));		return NT_STATUS_NO_USER_SESSION_KEY;	}		DEBUG(10, ("Got KRB5 session key of length %d\n",  		   (int)KRB5_KEY_LENGTH(subkey)));	gensec_gssapi_state->session_key = data_blob_talloc(gensec_gssapi_state, 							    KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));	krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey);	*session_key = gensec_gssapi_state->session_key;	dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);	return NT_STATUS_OK;}/* Get some basic (and authorization) information about the user on * this session.  This uses either the PAC (if present) or a local * database lookup */static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,					   struct auth_session_info **_session_info) {	NTSTATUS nt_status;	TALLOC_CTX *mem_ctx;	struct gensec_gssapi_state *gensec_gssapi_state		= talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);	struct auth_serversupplied_info *server_info = NULL;	struct auth_session_info *session_info = NULL;	struct PAC_LOGON_INFO *logon_info;	OM_uint32 maj_stat, min_stat;	gss_buffer_desc name_token;	gss_buffer_desc pac;	krb5_keyblock *keyblock;	time_t authtime;	krb5_principal principal;	char *principal_string;	DATA_BLOB pac_blob;		if ((gensec_gssapi_state->gss_oid->length != gss_mech_krb5->length)	    || (memcmp(gensec_gssapi_state->gss_oid->elements, gss_mech_krb5->elements, 		       gensec_gssapi_state->gss_oid->length) != 0)) {		DEBUG(1, ("NO session info available for this mech\n"));		return NT_STATUS_INVALID_PARAMETER;	}			mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context"); 	NT_STATUS_HAVE_NO_MEMORY(mem_ctx);	maj_stat = gss_display_name (&min_stat,				     gensec_gssapi_state->client_name,				     &name_token,				     NULL);	if (GSS_ERROR(maj_stat)) {		DEBUG(1, ("GSS display_name failed: %s\n", 			  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));		talloc_free(mem_ctx);		return NT_STATUS_FOOBAR;	}	principal_string = talloc_strndup(mem_ctx, 					  (const char *)name_token.value, 					  name_token.length);	gss_release_buffer(&min_stat, &name_token);	if (!principal_string) {		talloc_free(mem_ctx);		return NT_STATUS_NO_MEMORY;	}	maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 							       gensec_gssapi_state->gssapi_context, 							       KRB5_AUTHDATA_WIN2K_PAC,							       &pac);			if (maj_stat == 0) {		pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length);		gss_release_buffer(&min_stat, &pac);	} else {		pac_blob = data_blob(NULL, 0);	}		/* IF we have the PAC - otherwise we need to get this	 * data from elsewere - local ldb, or (TODO) lookup of some	 * kind... 	 */	if (pac_blob.length) {		krb5_error_code ret;		union netr_Validation validation;		maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,								     gensec_gssapi_state->gssapi_context, 								     &authtime);				if (GSS_ERROR(maj_stat)) {			DEBUG(1, ("gsskrb5_extract_authtime_from_sec_context: %s\n", 				  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));			talloc_free(mem_ctx);			return NT_STATUS_FOOBAR;		}		maj_stat = gsskrb5_extract_service_keyblock(&min_stat, 							    gensec_gssapi_state->gssapi_context, 							    &keyblock);				if (GSS_ERROR(maj_stat)) {			DEBUG(1, ("gsskrb5_copy_service_keyblock failed: %s\n", 				  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));			talloc_free(mem_ctx);			return NT_STATUS_FOOBAR;		} 		ret = krb5_parse_name_flags(gensec_gssapi_state->smb_krb5_context->krb5_context,					    principal_string, 					    KRB5_PRINCIPAL_PARSE_MUST_REALM,					    &principal);		if (ret) {			krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context,					   keyblock);			talloc_free(mem_ctx);			return NT_STATUS_INVALID_PARAMETER;		}				/* decode and verify the pac */		nt_status = kerberos_pac_logon_info(mem_ctx, lp_iconv_convenience(gensec_security->lp_ctx), &logon_info, pac_blob,						    gensec_gssapi_state->smb_krb5_context->krb5_context,						    NULL, keyblock, principal, authtime, NULL);		krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal);		krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context,				   keyblock);		if (!NT_STATUS_IS_OK(nt_status)) {			talloc_free(mem_ctx);			return nt_status;		}		validation.sam3 = &logon_info->info3;		nt_status = make_server_info_netlogon_validation(gensec_gssapi_state, 								 NULL,								 3, &validation,								 &server_info); 		if (!NT_STATUS_IS_OK(nt_status)) {			talloc_free(mem_ctx);			return nt_status;		}	} else if (!lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec", "require_pac", false)) {		DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",			  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));		nt_status = sam_get_server_info_principal(mem_ctx, gensec_security->event_ctx, gensec_security->lp_ctx, principal_string,							  &server_info);		if (!NT_STATUS_IS_OK(nt_status)) {			talloc_free(mem_ctx);			return nt_status;		}	} else {		DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",			  principal_string,			  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));		return NT_STATUS_ACCESS_DENIED;	}	/* references the server_info into the session_info */	nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx, gensec_security->lp_ctx, server_info, &session_info);	if (!NT_STATUS_IS_OK(nt_status)) {		talloc_free(mem_ctx);		return nt_status;	}	nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);	if (!NT_STATUS_IS_OK(nt_status)) {		talloc_free(mem_ctx);		return nt_status;	}	if (!(gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG)) {		DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));	} else {		krb5_error_code ret;		DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));		session_info->credentials = cli_credentials_init(session_info);		if (!session_info->credentials) {			talloc_free(mem_ctx);			return NT_STATUS_NO_MEMORY;		}		cli_credentials_set_conf(session_info->credentials, gensec_security->lp_ctx);		/* Just so we don't segfault trying to get at a username */		cli_credentials_set_anonymous(session_info->credentials);				ret = cli_credentials_set_client_gss_creds(session_info->credentials, 							   gensec_security->event_ctx,							   gensec_security->lp_ctx, 							   gensec_gssapi_state->delegated_cred_handle,							   CRED_SPECIFIED);		if (ret) {			talloc_free(mem_ctx);			return NT_STATUS_NO_MEMORY;		}				/* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */		cli_credentials_set_kerberos_state(session_info->credentials, CRED_MUST_USE_KERBEROS);		/* It has been taken from this place... */		gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;	}	talloc_steal(gensec_gssapi_state, session_info);	talloc_free(mem_ctx);	*_session_info = session_info;	return NT_STATUS_OK;}static const char *gensec_gssapi_krb5_oids[] = { 	GENSEC_OID_KERBEROS5_OLD,	GENSEC_OID_KERBEROS5,	NULL };static const char *gensec_gssapi_spnego_oids[] = { 	GENSEC_OID_SPNEGO,	NULL };/* As a server, this could in theory accept any GSSAPI mech */static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {	.name		= "gssapi_spnego",	.sasl_name	= "GSS-SPNEGO",	.auth_type	= DCERPC_AUTH_TYPE_SPNEGO,	.oid            = gensec_gssapi_spnego_oids,	.client_start   = gensec_gssapi_client_start,	.server_start   = gensec_gssapi_server_start,	.magic  	= gensec_gssapi_magic,	.update 	= gensec_gssapi_update,	.session_key	= gensec_gssapi_session_key,	.session_info	= gensec_gssapi_session_info,	.sign_packet	= gensec_gssapi_sign_packet,	.check_packet	= gensec_gssapi_check_packet,	.seal_packet	= gensec_gssapi_seal_packet,	.unseal_packet	= gensec_gssapi_unseal_packet,	.wrap           = gensec_gssapi_wrap,	.unwrap         = gensec_gssapi_unwrap,	.have_feature   = gensec_gssapi_have_feature,	.enabled        = false,	.kerberos       = true,	.priority       = GENSEC_GSSAPI};/* As a server, this could in theory accept any GSSAPI mech */static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {	.name		= "gssapi_krb5",	.auth_type	= DCERPC_AUTH_TYPE_KRB5,	.oid            = gensec_gssapi_krb5_oids,	.client_start   = gensec_gssapi_client_start,	.server_start   = gensec_gssapi_server_start,	.magic  	= gensec_gssapi_magic,	.update 	= gensec_gssapi_update,	.session_key	= gensec_gssapi_session_key,	.session_info	= gensec_gssapi_session_info,	.sign_packet	= gensec_gssapi_sign_packet,	.check_packet	= gensec_gssapi_check_packet,	.seal_packet	= gensec_gssapi_seal_packet,	.unseal_packet	= gensec_gssapi_unseal_packet,	.wrap           = gensec_gssapi_wrap,	.unwrap         = gensec_gssapi_unwrap,	.have_feature   = gensec_gssapi_have_feature,	.enabled        = true,	.kerberos       = true,	.priority       = GENSEC_GSSAPI};/* As a server, this could in theory accept any GSSAPI mech */static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {	.name		  = "gssapi_krb5_sasl",	.sasl_name        = "GSSAPI",	.client_start     = gensec_gssapi_sasl_client_start,	.server_start     = gensec_gssapi_sasl_server_start,	.update 	  = gensec_gssapi_update,	.session_key	  = gensec_gssapi_session_key,	.session_info	  = gensec_gssapi_session_info,	.max_input_size	  = gensec_gssapi_max_input_size,	.max_wrapped_size = gensec_gssapi_max_wrapped_size,	.wrap             = gensec_gssapi_wrap,	.unwrap           = gensec_gssapi_unwrap,	.have_feature     = gensec_gssapi_have_feature,	.enabled          = true,	.kerberos         = true,	.priority         = GENSEC_GSSAPI};_PUBLIC_ NTSTATUS gensec_gssapi_init(void){	NTSTATUS ret;	ret = gensec_register(&gensec_gssapi_spnego_security_ops);	if (!NT_STATUS_IS_OK(ret)) {		DEBUG(0,("Failed to register '%s' gensec backend!\n",			gensec_gssapi_spnego_security_ops.name));		return ret;	}	ret = gensec_register(&gensec_gssapi_krb5_security_ops);	if (!NT_STATUS_IS_OK(ret)) {		DEBUG(0,("Failed to register '%s' gensec backend!\n",			gensec_gssapi_krb5_security_ops.name));		return ret;	}	ret = gensec_register(&gensec_gssapi_sasl_krb5_security_ops);	if (!NT_STATUS_IS_OK(ret)) {		DEBUG(0,("Failed to register '%s' gensec backend!\n",			gensec_gssapi_sasl_krb5_security_ops.name));		return ret;	}	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -