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

📄 kerberos.c

📁 samba-3.0.22.tar.gz 编译smb服务器的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   kerberos utility library   Copyright (C) Andrew Tridgell 2001   Copyright (C) Remus Koos 2001   Copyright (C) Nalin Dahyabhai <nalin@redhat.com> 2004.   Copyright (C) Jeremy Allison 2004.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"#ifdef HAVE_KRB5#define LIBADS_CCACHE_NAME "MEMORY:libads"/*  we use a prompter to avoid a crash bug in the kerberos libs when   dealing with empty passwords  this prompter is just a string copy ...*/static krb5_error_code kerb_prompter(krb5_context ctx, void *data,	       const char *name,	       const char *banner,	       int num_prompts,	       krb5_prompt prompts[]){	if (num_prompts == 0) return 0;	memset(prompts[0].reply->data, '\0', prompts[0].reply->length);	if (prompts[0].reply->length > 0) {		if (data) {			strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1);			prompts[0].reply->length = strlen(prompts[0].reply->data);		} else {			prompts[0].reply->length = 0;		}	}	return 0;}/*  simulate a kinit, putting the tgt in the given cache location. If cache_name == NULL  place in default cache location.  remus@snapserver.com*/int kerberos_kinit_password(const char *principal,				const char *password,				int time_offset,				time_t *expire_time,				const char *cache_name){	krb5_context ctx = NULL;	krb5_error_code code = 0;	krb5_ccache cc = NULL;	krb5_principal me;	krb5_creds my_creds;	initialize_krb5_error_table();	if ((code = krb5_init_context(&ctx)))		return code;	if (time_offset != 0) {		krb5_set_real_time(ctx, time(NULL) + time_offset, 0);	}		if ((code = krb5_cc_resolve(ctx, cache_name ?			cache_name : krb5_cc_default_name(ctx), &cc))) {		krb5_free_context(ctx);		return code;	}		if ((code = krb5_parse_name(ctx, principal, &me))) {		krb5_free_context(ctx);			return code;	}		if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password), 						 kerb_prompter, 						 NULL, 0, NULL, NULL))) {		krb5_free_principal(ctx, me);		krb5_free_context(ctx);				return code;	}		if ((code = krb5_cc_initialize(ctx, cc, me))) {		krb5_free_cred_contents(ctx, &my_creds);		krb5_free_principal(ctx, me);		krb5_free_context(ctx);				return code;	}		if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {		krb5_cc_close(ctx, cc);		krb5_free_cred_contents(ctx, &my_creds);		krb5_free_principal(ctx, me);		krb5_free_context(ctx);				return code;	}		if (expire_time)		*expire_time = (time_t) my_creds.times.endtime;	krb5_cc_close(ctx, cc);	krb5_free_cred_contents(ctx, &my_creds);	krb5_free_principal(ctx, me);	krb5_free_context(ctx);				return 0;}/* run kinit to setup our ccache */int ads_kinit_password(ADS_STRUCT *ads){	char *s;	int ret;	const char *account_name;	fstring acct_name;	if ( IS_DC ) {		/* this will end up getting a ticket for DOMAIN@RUSTED.REA.LM */		account_name = lp_workgroup();	} else {		/* always use the sAMAccountName for security = domain */		/* global_myname()$@REA.LM */		if ( lp_security() == SEC_DOMAIN ) {			fstr_sprintf( acct_name, "%s$", global_myname() );			account_name = acct_name;		}		else 			/* This looks like host/global_myname()@REA.LM */			account_name = ads->auth.user_name;	}	if (asprintf(&s, "%s@%s", account_name, ads->auth.realm) == -1) {		return KRB5_CC_NOMEM;	}	if (!ads->auth.password) {		return KRB5_LIBOS_CANTREADPWD;	}		ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset,			&ads->auth.expire, NULL);	if (ret) {		DEBUG(0,("kerberos_kinit_password %s failed: %s\n", 			 s, error_message(ret)));	}	free(s);	return ret;}int ads_kdestroy(const char *cc_name){	krb5_error_code code;	krb5_context ctx = NULL;	krb5_ccache cc = NULL;	initialize_krb5_error_table();	if ((code = krb5_init_context (&ctx))) {		DEBUG(3, ("ads_kdestroy: kdb5_init_context failed: %s\n", 			error_message(code)));		return code;	}  	if (!cc_name) {		if ((code = krb5_cc_default(ctx, &cc))) {			krb5_free_context(ctx);			return code;		}	} else {		if ((code = krb5_cc_resolve(ctx, cc_name, &cc))) {			DEBUG(3, ("ads_kdestroy: krb5_cc_resolve failed: %s\n",				  error_message(code)));			krb5_free_context(ctx);			return code;		}	}	if ((code = krb5_cc_destroy (ctx, cc))) {		DEBUG(3, ("ads_kdestroy: krb5_cc_destroy failed: %s\n", 			error_message(code)));	}	krb5_free_context (ctx);	return code;}/************************************************************************ Routine to fetch the salting principal for a service.  Active Directory may use a non-obvious principal name to generate the salt when it determines the key to use for encrypting tickets for a service, and hopefully we detected that when we joined the domain. ************************************************************************/static char *kerberos_secrets_fetch_salting_principal(const char *service, int enctype){	char *key = NULL;	char *ret = NULL;	asprintf(&key, "%s/%s/enctype=%d", SECRETS_SALTING_PRINCIPAL, service, enctype);	if (!key) {		return NULL;	}	ret = (char *)secrets_fetch(key, NULL);	SAFE_FREE(key);	return ret;}/************************************************************************ Routine to get the salting principal for this service.  Active Directory may use a non-obvious principal name to generate the salt when it determines the key to use for encrypting tickets for a service, and hopefully we detected that when we joined the domain. Caller must free if return is not null. ************************************************************************/krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,							krb5_principal host_princ,							int enctype){	char *unparsed_name = NULL, *salt_princ_s = NULL;	krb5_principal ret_princ = NULL;	if (krb5_unparse_name(context, host_princ, &unparsed_name) != 0) {		return (krb5_principal)NULL;	}	if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) {		krb5_free_unparsed_name(context, unparsed_name);		return (krb5_principal)NULL;	}	if (krb5_parse_name(context, salt_princ_s, &ret_princ) != 0) {		krb5_free_unparsed_name(context, unparsed_name);		SAFE_FREE(salt_princ_s);		return (krb5_principal)NULL;	}	krb5_free_unparsed_name(context, unparsed_name);	SAFE_FREE(salt_princ_s);	return ret_princ;}/************************************************************************ Routine to set the salting principal for this service.  Active Directory may use a non-obvious principal name to generate the salt when it determines the key to use for encrypting tickets for a service, and hopefully we detected that when we joined the domain. Setting principal to NULL deletes this entry. ************************************************************************/BOOL kerberos_secrets_store_salting_principal(const char *service,					      int enctype,					      const char *principal){	char *key = NULL;	BOOL ret = False;	krb5_context context = NULL;	krb5_principal princ = NULL;	char *princ_s = NULL;	char *unparsed_name = NULL;	krb5_init_context(&context);	if (!context) {		return False;	}	if (strchr_m(service, '@')) {		asprintf(&princ_s, "%s", service);	} else {		asprintf(&princ_s, "%s@%s", service, lp_realm());	}	if (krb5_parse_name(context, princ_s, &princ) != 0) {		goto out;			}	if (krb5_unparse_name(context, princ, &unparsed_name) != 0) {		goto out;	}	asprintf(&key, "%s/%s/enctype=%d", SECRETS_SALTING_PRINCIPAL, unparsed_name, enctype);	if (!key)  {		goto out;	}	if ((principal != NULL) && (strlen(principal) > 0)) {		ret = secrets_store(key, principal, strlen(principal) + 1);	} else {		ret = secrets_delete(key);	} out:	SAFE_FREE(key);	SAFE_FREE(princ_s);	if (unparsed_name) {		krb5_free_unparsed_name(context, unparsed_name);	}	if (context) {		krb5_free_context(context);	}	return ret;}/************************************************************************ Routine to get initial credentials as a service ticket for the local machine. Returns a buffer initialized with krb5_mk_req_extended. ************************************************************************/static krb5_error_code get_service_ticket(krb5_context ctx,					krb5_ccache ccache,					const char *service_principal,					int enctype,					krb5_data *p_outbuf){	krb5_creds creds, *new_creds = NULL;	char *service_s = NULL;	char *machine_account = NULL, *password = NULL;	krb5_data in_data;	krb5_auth_context auth_context = NULL;	krb5_error_code err = 0;	ZERO_STRUCT(creds);	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 ((err = kerberos_kinit_password(machine_account, password, 0, NULL, LIBADS_CCACHE_NAME)) != 0) {		DEBUG(0,("get_service_ticket: kerberos_kinit_password %s@%s failed: %s\n", 			machine_account,			lp_realm(),			error_message(err)));		goto out;	}	/* Ok - the above call has gotten a TGT. Now we need to get a service	   ticket to ourselves. */	/* Set up the enctype and client and server principal fields for krb5_get_credentials. */	kerberos_set_creds_enctype(&creds, enctype);	if ((err = krb5_cc_get_principal(ctx, ccache, &creds.client))) {		DEBUG(3, ("get_service_ticket: krb5_cc_get_principal failed: %s\n", 			error_message(err)));		goto out;	}	if (strchr_m(service_principal, '@')) {		asprintf(&service_s, "%s", service_principal);	} else {		asprintf(&service_s, "%s@%s", service_principal, lp_realm());	}	if ((err = krb5_parse_name(ctx, service_s, &creds.server))) {		DEBUG(0,("get_service_ticket: krb5_parse_name %s failed: %s\n", 			service_s, error_message(err)));		goto out;	}	if ((err = krb5_get_credentials(ctx, 0, ccache, &creds, &new_creds))) {		DEBUG(5,("get_service_ticket: krb5_get_credentials for %s enctype %d failed: %s\n", 			service_s, enctype, error_message(err)));		goto out;	}	memset(&in_data, '\0', sizeof(in_data));	if ((err = krb5_mk_req_extended(ctx, &auth_context, 0, &in_data,			new_creds, p_outbuf)) != 0) {

⌨️ 快捷键说明

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