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

📄 kerberos.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		DEBUG(0,("get_service_ticket: krb5_mk_req_extended failed: %s\n", 			error_message(err)));		goto out;	} out:	if (auth_context) {		krb5_auth_con_free(ctx, auth_context);	}	if (new_creds) {		krb5_free_creds(ctx, new_creds);	}	if (creds.server) {		krb5_free_principal(ctx, creds.server);	}	if (creds.client) {		krb5_free_principal(ctx, creds.client);	}	SAFE_FREE(service_s);	SAFE_FREE(password);	SAFE_FREE(machine_account);	return err;}/************************************************************************ Check if the machine password can be used in conjunction with the salting_principal to generate a key which will successfully decrypt the AP_REQ already gotten as a message to the local machine. ************************************************************************/static BOOL verify_service_password(krb5_context ctx,				    int enctype,				    const char *salting_principal,				    krb5_data *in_data){	BOOL ret = False;	krb5_principal salting_kprinc = NULL;	krb5_ticket *ticket = NULL;	krb5_keyblock key;	krb5_data passdata;	char *salting_s = NULL;	char *machine_account = NULL, *password = NULL;	krb5_auth_context auth_context = NULL;	krb5_error_code err;	memset(&passdata, '\0', sizeof(passdata));	memset(&key, '\0', sizeof(key));	asprintf(&machine_account, "%s$@%s", global_myname(), lp_realm());	if (machine_account == NULL) {		goto out;	}	password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);	if (password == NULL) {		goto out;	}	if (strchr_m(salting_principal, '@')) {		asprintf(&salting_s, "%s", salting_principal);	} else {		asprintf(&salting_s, "%s@%s", salting_principal, lp_realm());	}	if ((err = krb5_parse_name(ctx, salting_s, &salting_kprinc))) {		DEBUG(0,("verify_service_password: krb5_parse_name %s failed: %s\n", 			salting_s, error_message(err)));		goto out;	}	passdata.length = strlen(password);	passdata.data = (char*)password;	if ((err = create_kerberos_key_from_string_direct(ctx, salting_kprinc, &passdata, &key, enctype))) {		DEBUG(0,("verify_service_password: create_kerberos_key_from_string %d failed: %s\n",			enctype, error_message(err)));		goto out;	}	if ((err = krb5_auth_con_init(ctx, &auth_context)) != 0) {		DEBUG(0,("verify_service_password: krb5_auth_con_init failed %s\n", error_message(err)));		goto out;	}	if ((err = krb5_auth_con_setuseruserkey(ctx, auth_context, &key)) != 0) {		DEBUG(0,("verify_service_password: krb5_auth_con_setuseruserkey failed %s\n", error_message(err)));		goto out;	}	if (!(err = krb5_rd_req(ctx, &auth_context, in_data, NULL, NULL, NULL, &ticket))) {		DEBUG(10,("verify_service_password: decrypted message with enctype %u salt %s!\n",				(unsigned int)enctype, salting_s));		ret = True;	} out:	memset(&passdata, 0, sizeof(passdata));	krb5_free_keyblock_contents(ctx, &key);	if (ticket != NULL) {		krb5_free_ticket(ctx, ticket);	}	if (salting_kprinc) {		krb5_free_principal(ctx, salting_kprinc);	}	SAFE_FREE(salting_s);	SAFE_FREE(password);	SAFE_FREE(machine_account);	return ret;}/************************************************************************ * * From the current draft of kerberos-clarifications: * *     It is not possible to reliably generate a user's key given a pass *     phrase without contacting the KDC, since it will not be known *     whether alternate salt or parameter values are required. * * And because our server has a password, we have this exact problem.  We * make multiple guesses as to which principal name provides the salt which * the KDC is using. * ************************************************************************/static void kerberos_derive_salting_principal_for_enctype(const char *service_principal,							  krb5_context ctx,							  krb5_ccache ccache,							  krb5_enctype enctype,							  krb5_enctype *enctypes){	char *salting_principals[3] = {NULL, NULL, NULL}, *second_principal = NULL;	krb5_error_code err = 0;	krb5_data outbuf;	int i, j;	memset(&outbuf, '\0', sizeof(outbuf));	/* Check that the service_principal is useful. */	if ((service_principal == NULL) || (strlen(service_principal) == 0)) {		return;	}	/* Generate our first guess -- the principal as-given. */	asprintf(&salting_principals[0], "%s", service_principal);	if ((salting_principals[0] == NULL) || (strlen(salting_principals[0]) == 0)) {		return;	}	/* Generate our second guess -- the computer's principal, as Win2k3. */	asprintf(&second_principal, "host/%s.%s", global_myname(), lp_realm());	if (second_principal != NULL) {		strlower_m(second_principal);		asprintf(&salting_principals[1], "%s@%s", second_principal, lp_realm());		SAFE_FREE(second_principal);	}	if ((salting_principals[1] == NULL) || (strlen(salting_principals[1]) == 0)) {		goto out;	}	/* Generate our third guess -- the computer's principal, as Win2k. */	asprintf(&second_principal, "HOST/%s", global_myname());	if (second_principal != NULL) {		strlower_m(second_principal + 5);		asprintf(&salting_principals[2], "%s@%s",			second_principal, lp_realm());		SAFE_FREE(second_principal);	}	if ((salting_principals[2] == NULL) || (strlen(salting_principals[2]) == 0)) {		goto out;	}	/* Get a service ticket for ourselves into our memory ccache. */	/* This will commonly fail if there is no principal by that name (and we're trying	   many names). So don't print a debug 0 error. */	if ((err = get_service_ticket(ctx, ccache, service_principal, enctype, &outbuf)) != 0) {		DEBUG(3, ("verify_service_password: get_service_ticket failed: %s\n", 			error_message(err)));		goto out;	}	/* At this point we have a message to ourselves, salted only the KDC knows how. We	   have to work out what that salting is. */	/* Try and find the correct salting principal. */	for (i = 0; i < sizeof(salting_principals) / sizeof(salting_principals[i]); i++) {		if (verify_service_password(ctx, enctype, salting_principals[i], &outbuf)) {			break;		}	}	/* If we failed to get a match, return. */	if (i >= sizeof(salting_principals) / sizeof(salting_principals[i])) {		goto out;	}	/* If we succeeded, store the principal for use for all enctypes which	 * share the same cipher and string-to-key function.  Doing this here	 * allows servers which just pass a keytab to krb5_rd_req() to work	 * correctly. */	for (j = 0; enctypes[j] != 0; j++) {		if (enctype != enctypes[j]) {			/* If this enctype isn't compatible with the one which			 * we used, skip it. */			if (!kerberos_compatible_enctypes(ctx, enctypes[j], enctype))				continue;		}		/* If the principal which gives us the proper salt is the one		 * which we would normally guess, don't bother noting anything		 * in the secrets tdb. */		if (strcmp(service_principal, salting_principals[i]) != 0) {			kerberos_secrets_store_salting_principal(service_principal,								enctypes[j],								salting_principals[i]);		}	} out :	kerberos_free_data_contents(ctx, &outbuf);	SAFE_FREE(salting_principals[0]);	SAFE_FREE(salting_principals[1]);	SAFE_FREE(salting_principals[2]);	SAFE_FREE(second_principal);}/************************************************************************ Go through all the possible enctypes for this principal. ************************************************************************/static void kerberos_derive_salting_principal_direct(krb5_context context,					krb5_ccache ccache,					krb5_enctype *enctypes,					char *service_principal){	int i;	/* Try for each enctype separately, because the rules are	 * different for different enctypes. */	for (i = 0; enctypes[i] != 0; i++) {		/* Delete secrets entry first. */		kerberos_secrets_store_salting_principal(service_principal, 0, NULL);#ifdef ENCTYPE_ARCFOUR_HMAC		if (enctypes[i] == ENCTYPE_ARCFOUR_HMAC) {			/* Of course this'll always work, so just save			 * ourselves the effort. */			continue;		}#endif		/* Try to figure out what's going on with this		 * principal. */		kerberos_derive_salting_principal_for_enctype(service_principal,								context,								ccache,								enctypes[i],								enctypes);	}}/************************************************************************ Wrapper function for the above. ************************************************************************/BOOL kerberos_derive_salting_principal(char *service_principal){	krb5_context context = NULL;	krb5_enctype *enctypes = NULL;	krb5_ccache ccache = NULL;	krb5_error_code ret = 0;	initialize_krb5_error_table();	if ((ret = krb5_init_context(&context)) != 0) {		DEBUG(1,("kerberos_derive_cifs_salting_principals: krb5_init_context failed. %s\n",			error_message(ret)));		return False;	}	if ((ret = get_kerberos_allowed_etypes(context, &enctypes)) != 0) {		DEBUG(1,("kerberos_derive_cifs_salting_principals: get_kerberos_allowed_etypes failed. %s\n",			error_message(ret)));		goto out;	}	if ((ret = krb5_cc_resolve(context, LIBADS_CCACHE_NAME, &ccache)) != 0) {		DEBUG(3, ("get_service_ticket: krb5_cc_resolve for %s failed: %s\n", 			LIBADS_CCACHE_NAME, error_message(ret)));		goto out;	}	kerberos_derive_salting_principal_direct(context, ccache, enctypes, service_principal);  out: 	if (enctypes) {		free_kerberos_etypes(context, enctypes);	}	if (ccache) {		krb5_cc_destroy(context, ccache);	}	if (context) {		krb5_free_context(context);	}	return ret ? False : True;}/************************************************************************ Core function to try and determine what salt is being used for any keytab keys. ************************************************************************/BOOL kerberos_derive_cifs_salting_principals(void){	fstring my_fqdn;	char *service = NULL;	krb5_context context = NULL;	krb5_enctype *enctypes = NULL;	krb5_ccache ccache = NULL;	krb5_error_code ret = 0;	BOOL retval = False;	initialize_krb5_error_table();	if ((ret = krb5_init_context(&context)) != 0) {		DEBUG(1,("kerberos_derive_cifs_salting_principals: krb5_init_context failed. %s\n",			error_message(ret)));		return False;	}	if ((ret = get_kerberos_allowed_etypes(context, &enctypes)) != 0) {		DEBUG(1,("kerberos_derive_cifs_salting_principals: get_kerberos_allowed_etypes failed. %s\n",			error_message(ret)));		goto out;	}	if ((ret = krb5_cc_resolve(context, LIBADS_CCACHE_NAME, &ccache)) != 0) {		DEBUG(3, ("get_service_ticket: krb5_cc_resolve for %s failed: %s\n", 			LIBADS_CCACHE_NAME, error_message(ret)));		goto out;	}	if (asprintf(&service, "%s$", global_myname()) != -1) {		strlower_m(service);		kerberos_derive_salting_principal_direct(context, ccache, enctypes, service);		SAFE_FREE(service);	}	if (asprintf(&service, "cifs/%s", global_myname()) != -1) {		strlower_m(service);		kerberos_derive_salting_principal_direct(context, ccache, enctypes, service);		SAFE_FREE(service);	}	if (asprintf(&service, "host/%s", global_myname()) != -1) {		strlower_m(service);		kerberos_derive_salting_principal_direct(context, ccache, enctypes, service);		SAFE_FREE(service);	}	if (asprintf(&service, "cifs/%s.%s", global_myname(), lp_realm()) != -1) {		strlower_m(service);		kerberos_derive_salting_principal_direct(context, ccache, enctypes, service);		SAFE_FREE(service);	}	if (asprintf(&service, "host/%s.%s", global_myname(), lp_realm()) != -1) {		strlower_m(service);		kerberos_derive_salting_principal_direct(context, ccache, enctypes, service);		SAFE_FREE(service);	}	name_to_fqdn(my_fqdn, global_myname());	if (asprintf(&service, "cifs/%s", my_fqdn) != -1) {		strlower_m(service);		kerberos_derive_salting_principal_direct(context, ccache, enctypes, service);		SAFE_FREE(service);	}	if (asprintf(&service, "host/%s", my_fqdn) != -1) {		strlower_m(service);		kerberos_derive_salting_principal_direct(context, ccache, enctypes, service);		SAFE_FREE(service);	}	retval = True;  out: 	if (enctypes) {		free_kerberos_etypes(context, enctypes);	}	if (ccache) {		krb5_cc_destroy(context, ccache);	}	if (context) {		krb5_free_context(context);	}	return retval;}#endif

⌨️ 快捷键说明

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