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

📄 gensec_krb5.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (gensec_krb5_state->gssapi) {			if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {				DEBUG(1,("gensec_gssapi_parse_krb5_wrap(mutual authentication) failed to parse\n"));				dump_data_pw("Mutual authentication message:\n", in.data, in.length);				return NT_STATUS_INVALID_PARAMETER;			}		} else {			unwrapped_in = in;		}		/* TODO: check the tok_id */		inbuf.data = unwrapped_in.data;		inbuf.length = unwrapped_in.length;		ret = krb5_rd_rep(gensec_krb5_state->smb_krb5_context->krb5_context, 				  gensec_krb5_state->auth_context,				  &inbuf, &repl);		if (ret) {			DEBUG(1,("krb5_rd_rep (mutual authentication) failed (%s)\n",				 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, out_mem_ctx)));			dump_data_pw("Mutual authentication message:\n", (uint8_t *)inbuf.data, inbuf.length);			nt_status = NT_STATUS_ACCESS_DENIED;		} else {			*out = data_blob(NULL, 0);			nt_status = NT_STATUS_OK;			gensec_krb5_state->state_position = GENSEC_KRB5_DONE;		}		if (repl) {			krb5_free_ap_rep_enc_part(gensec_krb5_state->smb_krb5_context->krb5_context, repl);		}		return nt_status;	}	case GENSEC_KRB5_SERVER_START:	{		DATA_BLOB unwrapped_in;		DATA_BLOB unwrapped_out = data_blob(NULL, 0);		krb5_data inbuf, outbuf;		uint8_t tok_id[2];		struct keytab_container *keytab;		krb5_principal server_in_keytab;		if (!in.data) {			return NT_STATUS_INVALID_PARAMETER;		}			/* Grab the keytab, however generated */		ret = cli_credentials_get_keytab(gensec_get_credentials(gensec_security), 					         gensec_security->event_ctx, 						 gensec_security->lp_ctx, &keytab);		if (ret) {			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;		}				/* This ensures we lookup the correct entry in that keytab */		ret = principal_from_credentials(out_mem_ctx, gensec_get_credentials(gensec_security), 						 gensec_krb5_state->smb_krb5_context, 						 &server_in_keytab);		if (ret) {			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;		}		/* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */		if (gensec_krb5_state->gssapi		    && gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {			inbuf.data = unwrapped_in.data;			inbuf.length = unwrapped_in.length;		} else {			inbuf.data = in.data;			inbuf.length = in.length;		}		ret = smb_rd_req_return_stuff(gensec_krb5_state->smb_krb5_context->krb5_context,					      &gensec_krb5_state->auth_context, 					      &inbuf, keytab->keytab, server_in_keytab,  					      &outbuf, 					      &gensec_krb5_state->ticket, 					      &gensec_krb5_state->keyblock);		if (ret) {			return NT_STATUS_LOGON_FAILURE;		}		unwrapped_out.data = (uint8_t *)outbuf.data;		unwrapped_out.length = outbuf.length;		gensec_krb5_state->state_position = GENSEC_KRB5_DONE;		/* wrap that up in a nice GSS-API wrapping */		if (gensec_krb5_state->gssapi) {			*out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);		} else {			*out = data_blob_talloc(out_mem_ctx, outbuf.data, outbuf.length);		}		krb5_data_free(&outbuf);		return NT_STATUS_OK;	}	case GENSEC_KRB5_DONE:	default:		/* Asking too many times... */		return NT_STATUS_INVALID_PARAMETER;	}}static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security, 					DATA_BLOB *session_key) {	struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;	krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;	krb5_auth_context auth_context = gensec_krb5_state->auth_context;	krb5_keyblock *skey;	krb5_error_code err = -1;	if (gensec_krb5_state->session_key.data) {		*session_key = gensec_krb5_state->session_key;		return NT_STATUS_OK;	}	switch (gensec_security->gensec_role) {	case GENSEC_CLIENT:		err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);		break;	case GENSEC_SERVER:		err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);		break;	}	if (err == 0 && skey != NULL) {		DEBUG(10, ("Got KRB5 session key of length %d\n",  			   (int)KRB5_KEY_LENGTH(skey)));		gensec_krb5_state->session_key = data_blob_talloc(gensec_krb5_state, 						KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));		*session_key = gensec_krb5_state->session_key;		dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);		krb5_free_keyblock(context, skey);		return NT_STATUS_OK;	} else {		DEBUG(10, ("KRB5 error getting session key %d\n", err));		return NT_STATUS_NO_USER_SESSION_KEY;	}}static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security,					 struct auth_session_info **_session_info) {	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;	struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;	krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;	struct auth_serversupplied_info *server_info = NULL;	struct auth_session_info *session_info = NULL;	struct PAC_LOGON_INFO *logon_info;	krb5_principal client_principal;	char *principal_string;		DATA_BLOB pac;	krb5_data pac_data;	krb5_error_code ret;	TALLOC_CTX *mem_ctx = talloc_new(gensec_security);	if (!mem_ctx) {		return NT_STATUS_NO_MEMORY;	}		ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);	if (ret) {		DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", 			  smb_get_krb5_error_message(context, 						     ret, mem_ctx)));		talloc_free(mem_ctx);		return NT_STATUS_NO_MEMORY;	}		ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context, 				client_principal, &principal_string);	if (ret) {		DEBUG(1, ("Unable to parse client principal: %s\n",			  smb_get_krb5_error_message(context, 						     ret, mem_ctx)));		talloc_free(mem_ctx);		return NT_STATUS_NO_MEMORY;	}	ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket, 						      KRB5_AUTHDATA_WIN2K_PAC, 						      &pac_data);		if (ret && lp_parm_bool(gensec_security->lp_ctx, NULL, "gensec", "require_pac", false)) {		DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s \n",			  principal_string,			  smb_get_krb5_error_message(context, 						     ret, mem_ctx)));		krb5_free_principal(context, client_principal);		free(principal_string);		return NT_STATUS_ACCESS_DENIED;	} else if (ret) {		/* NO pac */		DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n", 			  smb_get_krb5_error_message(context, 						     ret, mem_ctx)));		nt_status = sam_get_server_info_principal(mem_ctx, gensec_security->event_ctx, gensec_security->lp_ctx, principal_string,							  &server_info);		krb5_free_principal(context, client_principal);		free(principal_string);				if (!NT_STATUS_IS_OK(nt_status)) {			talloc_free(mem_ctx);			return nt_status;		}	} else {		/* Found pac */		union netr_Validation validation;		free(principal_string);		pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length);		if (!pac.data) {			krb5_free_principal(context, client_principal);			talloc_free(mem_ctx);			return NT_STATUS_NO_MEMORY;		}		/* decode and verify the pac */		nt_status = kerberos_pac_logon_info(gensec_krb5_state, 						    lp_iconv_convenience(gensec_security->lp_ctx),						    &logon_info, pac,						    gensec_krb5_state->smb_krb5_context->krb5_context,						    NULL, gensec_krb5_state->keyblock,						    client_principal,						    gensec_krb5_state->ticket->ticket.authtime, NULL);		krb5_free_principal(context, client_principal);		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(mem_ctx, 								 NULL,								 3, &validation,								 &server_info); 		if (!NT_STATUS_IS_OK(nt_status)) {			talloc_free(mem_ctx);			return nt_status;		}	}	/* 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_krb5_session_key(gensec_security, &session_info->session_key);	if (!NT_STATUS_IS_OK(nt_status)) {		talloc_free(mem_ctx);		return nt_status;	}	*_session_info = session_info;	talloc_steal(gensec_krb5_state, session_info);	talloc_free(mem_ctx);	return NT_STATUS_OK;}static NTSTATUS gensec_krb5_wrap(struct gensec_security *gensec_security, 				   TALLOC_CTX *mem_ctx, 				   const DATA_BLOB *in, 				   DATA_BLOB *out){	struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;	krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;	krb5_auth_context auth_context = gensec_krb5_state->auth_context;	krb5_error_code ret;	krb5_data input, output;	input.length = in->length;	input.data = in->data;		if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {		ret = krb5_mk_priv(context, auth_context, &input, &output, NULL);		if (ret) {			DEBUG(1, ("krb5_mk_priv failed: %s\n", 				  smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, 							     ret, mem_ctx)));			return NT_STATUS_ACCESS_DENIED;		}		*out = data_blob_talloc(mem_ctx, output.data, output.length);				krb5_data_free(&output);	} else {		return NT_STATUS_ACCESS_DENIED;	}	return NT_STATUS_OK;}static NTSTATUS gensec_krb5_unwrap(struct gensec_security *gensec_security, 				     TALLOC_CTX *mem_ctx, 				     const DATA_BLOB *in, 				     DATA_BLOB *out){	struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;	krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;	krb5_auth_context auth_context = gensec_krb5_state->auth_context;	krb5_error_code ret;	krb5_data input, output;	krb5_replay_data replay;	input.length = in->length;	input.data = in->data;		if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {		ret = krb5_rd_priv(context, auth_context, &input, &output, &replay);		if (ret) {			DEBUG(1, ("krb5_rd_priv failed: %s\n", 				  smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, 							     ret, mem_ctx)));			return NT_STATUS_ACCESS_DENIED;		}		*out = data_blob_talloc(mem_ctx, output.data, output.length);				krb5_data_free(&output);	} else {		return NT_STATUS_ACCESS_DENIED;	}	return NT_STATUS_OK;}static bool gensec_krb5_have_feature(struct gensec_security *gensec_security,				     uint32_t feature){	struct gensec_krb5_state *gensec_krb5_state = (struct gensec_krb5_state *)gensec_security->private_data;	if (feature & GENSEC_FEATURE_SESSION_KEY) {		return true;	} 	if (!gensec_krb5_state->gssapi && 	    (feature & GENSEC_FEATURE_SEAL)) {		return true;	} 		return false;}static const char *gensec_krb5_oids[] = { 	GENSEC_OID_KERBEROS5,	GENSEC_OID_KERBEROS5_OLD,	NULL };static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {	.name		= "fake_gssapi_krb5",	.auth_type	= DCERPC_AUTH_TYPE_KRB5,	.oid            = gensec_krb5_oids,	.client_start   = gensec_fake_gssapi_krb5_client_start,	.server_start   = gensec_fake_gssapi_krb5_server_start,	.update 	= gensec_krb5_update,	.magic   	= gensec_fake_gssapi_krb5_magic,	.session_key	= gensec_krb5_session_key,	.session_info	= gensec_krb5_session_info,	.have_feature   = gensec_krb5_have_feature,	.enabled        = false,	.kerberos       = true,	.priority       = GENSEC_KRB5};static const struct gensec_security_ops gensec_krb5_security_ops = {	.name		= "krb5",	.client_start   = gensec_krb5_client_start,	.server_start   = gensec_krb5_server_start,	.update 	= gensec_krb5_update,	.session_key	= gensec_krb5_session_key,	.session_info	= gensec_krb5_session_info,	.have_feature   = gensec_krb5_have_feature,	.wrap           = gensec_krb5_wrap,	.unwrap         = gensec_krb5_unwrap,	.enabled        = true,	.kerberos       = true,	.priority       = GENSEC_KRB5};_PUBLIC_ NTSTATUS gensec_krb5_init(void){	NTSTATUS ret;	auth_init();	ret = gensec_register(&gensec_krb5_security_ops);	if (!NT_STATUS_IS_OK(ret)) {		DEBUG(0,("Failed to register '%s' gensec backend!\n",			gensec_krb5_security_ops.name));		return ret;	}	ret = gensec_register(&gensec_fake_gssapi_krb5_security_ops);	if (!NT_STATUS_IS_OK(ret)) {		DEBUG(0,("Failed to register '%s' gensec backend!\n",			gensec_krb5_security_ops.name));		return ret;	}	return ret;}

⌨️ 快捷键说明

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