View | Details | Raw Unified
Collapse All | Expand All

(-) nfs-utils-1.0.8/utils/gssd/err_util.c~CITI_NFS4_ALL (-30 / +31 lines)
 Lines 38-44   static int verbosity = 0; Link Here 
static int fg = 0;
static int fg = 0;
static char message_buf[500];
static char message_buf[500];
static char tmp_buf[500];
void initerr(char *progname, int set_verbosity, int set_fg)
void initerr(char *progname, int set_verbosity, int set_fg)
{
{
 Lines 48-92   void initerr(char *progname, int set_ver Link Here 
		openlog(progname, LOG_PID, LOG_DAEMON);
		openlog(progname, LOG_PID, LOG_DAEMON);
}
}
void printerr(int priority, char *format, ...)
void printerr(int priority, char *format, ...)
{
{
	va_list args;
	va_list args;
	int ret;
	int ret;
	int buf_used, buf_available;
	char *buf;
	/* Don't bother formatting a message we're never going to print! */
	if (priority > verbosity)
		return;
	buf_used = strlen(message_buf);
	/* subtract 4 to leave room for "...\n" if necessary */
	buf_available = sizeof(message_buf) - buf_used - 4;
	buf = message_buf + buf_used;
	/* aggregate lines: only print buffer when we get to the end of a
	/*
	 * line or run out of space: */
	 * Aggregate lines: only print buffer when we get to the
	 * end of a line or run out of space
	 */
	va_start(args, format);
	va_start(args, format);
	ret = vsnprintf(tmp_buf, sizeof(tmp_buf), format, args);
	ret = vsnprintf(buf, buf_available, format, args);
	va_end(args);
	va_end(args);
	if ((ret < 0) || (ret >= sizeof(tmp_buf)))
		goto output;
	if (ret < 0)
	if (strlen(tmp_buf) + strlen(message_buf) + 1 > sizeof(message_buf))
		goto printit;
			goto output;
	if (ret >= buf_available) {
	strcat(message_buf, tmp_buf);
		/* Indicate we're truncating */
	if (tmp_buf[strlen(tmp_buf) - 1] == '\n')
		strcat(message_buf, "...\n");
		goto output;
		goto printit;
	}
	if (message_buf[strlen(message_buf) - 1] == '\n')
		goto printit;
	return;
	return;
output:
printit:
	priority -= verbosity;
	if (priority < 0)
		priority = 0;
	if (fg) {
	if (fg) {
		if (priority == 0)
		fprintf(stderr, "%s", message_buf);
			fprintf(stderr, "%s", message_buf);
	} else {
	} else {
		int sys_pri;
		syslog(LOG_ERR, "%s", message_buf);
		switch (priority) {
			case 0:
				sys_pri = LOG_ERR;
				break;
			case 1:
				sys_pri = LOG_DEBUG;
				break;
			default:
				goto out;
		}
		syslog(sys_pri, "%s", message_buf);
	}
	}
out:
	/* reset the buffer */
	memset(message_buf, 0, sizeof(message_buf));
	memset(message_buf, 0, sizeof(message_buf));
}
}
(-) nfs-utils-1.0.8/utils/gssd/gssd.c~CITI_NFS4_ALL (+5 lines)
 Lines 145-150   main(int argc, char *argv[]) Link Here 
			    "support setting debug level\n");
			    "support setting debug level\n");
#endif
#endif
	if (gssd_check_mechs() != 0)
		errx(1, "Problem with gssapi library");
	if (!fg && daemon(0, 0) < 0)
	if (!fg && daemon(0, 0) < 0)
		errx(1, "fork");
		errx(1, "fork");
 Lines 154-159   main(int argc, char *argv[]) Link Here 
	/* Process keytab file and get machine credentials */
	/* Process keytab file and get machine credentials */
	gssd_refresh_krb5_machine_creds();
	gssd_refresh_krb5_machine_creds();
	/* Determine Kerberos information from the kernel */
	gssd_obtain_kernel_krb5_info();
	gssd_run();
	gssd_run();
	printerr(0, "gssd_run returned!\n");
	printerr(0, "gssd_run returned!\n");
(-) nfs-utils-1.0.8/utils/gssd/gss_util.c~CITI_NFS4_ALL (+25 lines)
 Lines 224-226   gssd_acquire_cred(char *server_name) Link Here 
	return (maj_stat == GSS_S_COMPLETE);
	return (maj_stat == GSS_S_COMPLETE);
}
}
int gssd_check_mechs(void)
{
	u_int32_t maj_stat, min_stat;
	gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
	int retval = -1;
	maj_stat = gss_indicate_mechs(&min_stat, &supported_mechs);
	if (maj_stat != GSS_S_COMPLETE) {
		printerr(0, "Unable to obtain list of supported mechanisms. "
			 "Check that gss library is properly configured.\n");
		goto out;
	}
	if (supported_mechs == GSS_C_NO_OID_SET ||
	    supported_mechs->count == 0) {
		printerr(0, "Unable to obtain list of supported mechanisms. "
			 "Check that gss library is properly configured.\n");
		goto out;
	}
	maj_stat = gss_release_oid_set(&min_stat, &supported_mechs);
	retval = 0;
out:
	return retval;
}
(-) nfs-utils-1.0.8/utils/gssd/gss_util.h~CITI_NFS4_ALL (+1 lines)
 Lines 40-44   extern gss_cred_id_t gssd_creds; Link Here 
int gssd_acquire_cred(char *server_name);
int gssd_acquire_cred(char *server_name);
void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
	const gss_OID mech);
	const gss_OID mech);
int gssd_check_mechs(void);
#endif /* _GSS_UTIL_H_ */
#endif /* _GSS_UTIL_H_ */
(-) nfs-utils-1.0.8/utils/gssd/svcgssd.c~CITI_NFS4_ALL (+5 lines)
 Lines 204-209   main(int argc, char *argv[]) Link Here 
			    "support setting debug level\n");
			    "support setting debug level\n");
#endif
#endif
	if (gssd_check_mechs() != 0) {
		printerr(0, "ERROR: Problem with gssapi library\n");
		exit(1);
	}
	if (!fg)
	if (!fg)
		mydaemon(0, 0);
		mydaemon(0, 0);
(-) nfs-utils-1.0.8/utils/gssd/krb5_util.c~CITI_NFS4_ALL (-45 / +176 lines)
 Lines 97-102    Link Here 
#include "config.h"
#include "config.h"
#include <sys/param.h>
#include <sys/param.h>
#include <rpc/rpc.h>
#include <rpc/rpc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <arpa/inet.h>
 Lines 105-110    Link Here 
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <dirent.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <errno.h>
#include <time.h>
#include <time.h>
#include <gssapi/gssapi.h>
#include <gssapi/gssapi.h>
 Lines 123-128    Link Here 
/* Global list of principals/cache file names for machine credentials */
/* Global list of principals/cache file names for machine credentials */
struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
/* Encryption types supported by the kernel rpcsec_gss code */
int num_krb5_enctypes = 0;
krb5_enctype *krb5_enctypes = NULL;
/*==========================*/
/*==========================*/
/*===  Internal routines ===*/
/*===  Internal routines ===*/
/*==========================*/
/*==========================*/
 Lines 261-311   gssd_find_existing_krb5_ccache(uid_t uid Link Here 
}
}
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
/*
 * this routine obtains a credentials handle via gss_acquire_cred()
 * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
 * types negotiated.
 *
 * XXX Should call some function to determine the enctypes supported
 * by the kernel. (Only need to do that once!)
 *
 * Returns:
 *	0 => all went well
 *     -1 => there was an error
 */
int
limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
{
	u_int maj_stat, min_stat;
	gss_cred_id_t credh;
	krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
	maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
				    GSS_C_NULL_OID_SET, GSS_C_INITIATE,
				    &credh, NULL, NULL);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_acquire_cred",
			maj_stat, min_stat, &krb5oid);
		return -1;
	}
	maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
					     num_enctypes, &enctypes);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_set_allowable_enctypes",
			maj_stat, min_stat, &krb5oid);
		return -1;
	}
	sec->cred = credh;
	return 0;
}
#endif	/* HAVE_SET_ALLOWABLE_ENCTYPES */
/*
/*
 * Obtain credentials via a key in the keytab given
 * Obtain credentials via a key in the keytab given
 * a keytab handle and a gssd_k5_kt_princ structure.
 * a keytab handle and a gssd_k5_kt_princ structure.
 Lines 603-608   gssd_set_krb5_ccache_name(char *ccname) Link Here 
#endif
#endif
}
}
/*
 * Parse the supported encryption type information
 */
static int
parse_enctypes(char *enctypes)
{
	int n = 0;
	char *curr, *comma;
	int i;
	/* Just in case this ever gets called more than once */
	if (krb5_enctypes != NULL) {
		free(krb5_enctypes);
		krb5_enctypes = NULL;
		num_krb5_enctypes = 0;
	}
	/* count the number of commas */
	for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
		comma = strchr(curr, ',');
		if (comma != NULL)
			n++;
		else
			break;
	}
	/* If no more commas and we're not at the end, there's one more value */
	if (*curr != '\0')
		n++;
	/* Empty string, return an error */
	if (n == 0)
		return ENOENT;
	/* Allocate space for enctypes array */
	if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
		return ENOMEM;
	}
	/* Now parse each value into the array */
	for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
		krb5_enctypes[i++] = atoi(curr);
		comma = strchr(curr, ',');
		if (comma == NULL)
			break;
	}
	num_krb5_enctypes = n;
	return 0;
}
/*==========================*/
/*==========================*/
/*===  External routines ===*/
/*===  External routines ===*/
/*==========================*/
/*==========================*/
 Lines 854-856   gssd_destroy_krb5_machine_creds(void) Link Here 
	krb5_free_context(context);
	krb5_free_context(context);
}
}
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
/*
 * this routine obtains a credentials handle via gss_acquire_cred()
 * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
 * types negotiated.
 *
 * Returns:
 *	0 => all went well
 *     -1 => there was an error
 */
int
limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
{
	u_int maj_stat, min_stat;
	gss_cred_id_t credh;
	gss_OID_set_desc  desired_mechs;
	krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC};
	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
	/* We only care about getting a krb5 cred */
	desired_mechs.count = 1;
	desired_mechs.elements = &krb5oid;
	maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
				    &desired_mechs, GSS_C_INITIATE,
				    &credh, NULL, NULL);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_acquire_cred",
			maj_stat, min_stat, &krb5oid);
		return -1;
	}
	/*
	 * If we failed for any reason to produce global
	 * list of supported enctypes, use local default here.
	 */
	if (krb5_enctypes == NULL)
		maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
					&krb5oid, num_enctypes, &enctypes);
	else
		maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
					&krb5oid, num_krb5_enctypes,
					krb5_enctypes);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_set_allowable_enctypes",
			maj_stat, min_stat, &krb5oid);
		return -1;
	}
	sec->cred = credh;
	return 0;
}
#endif	/* HAVE_SET_ALLOWABLE_ENCTYPES */
/*
 * Obtain supported enctypes from kernel.
 * Set defaults if info is not available.
 */
void
gssd_obtain_kernel_krb5_info(void)
{
	char enctype_file_name[128];
	char buf[1024];
	char enctypes[128];
	char extrainfo[1024];
	int fd;
	int use_default_enctypes = 0;
	int nbytes, numfields;
	char default_enctypes[] = "1,3,2";
	int code;
	snprintf(enctype_file_name, sizeof(enctype_file_name),
		 "%s/%s", pipefsdir, "krb5_info");
	if ((fd = open(enctype_file_name, O_RDONLY)) == -1) {
		printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: "
			 "Unable to open '%s'. Unable to determine "
			 "Kerberos encryption types supported by the "
			 "kernel; using defaults (%s).\n",
			 enctype_file_name, default_enctypes);
		use_default_enctypes = 1;
		goto do_the_parse;
	}
	if ((nbytes = read(fd, buf, sizeof(buf))) == -1) {
		printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
			 "Error reading Kerberos encryption type "
			 "information file '%s'; using defaults (%s).\n",
			 enctype_file_name, default_enctypes);
		use_default_enctypes = 1;
		goto do_the_parse;
	}
	numfields = sscanf(buf, "enctypes: %s\n%s", enctypes, extrainfo);
	if (numfields < 1) {
		printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
			 "error parsing Kerberos encryption type "
			 "information from file '%s'; using defaults (%s).\n",
			 enctype_file_name, default_enctypes);
		use_default_enctypes = 1;
		goto do_the_parse;
	}
	if (numfields > 1) {
		printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
			 "Extra information, '%s', from '%s' is ignored\n",
			 enctype_file_name, extrainfo);
		use_default_enctypes = 1;
		goto do_the_parse;
	}
  do_the_parse:
  	if (use_default_enctypes)
		strcpy(enctypes, default_enctypes);
	if ((code = parse_enctypes(enctypes)) != 0) {
		printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: "
			 "parse_enctypes%s failed with code %d\n",
			 use_default_enctypes ? " (with default enctypes)" : "",
			 code);
	}
}
(-) nfs-utils-1.0.8/utils/gssd/krb5_util.h~CITI_NFS4_ALL (+2 lines)
 Lines 22-27   int gssd_refresh_krb5_machine_creds(voi Link Here 
void gssd_free_krb5_machine_cred_list(char **list);
void gssd_free_krb5_machine_cred_list(char **list);
void gssd_setup_krb5_machine_gss_ccache(char *servername);
void gssd_setup_krb5_machine_gss_ccache(char *servername);
void gssd_destroy_krb5_machine_creds(void);
void gssd_destroy_krb5_machine_creds(void);
void gssd_obtain_kernel_krb5_info(void);
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
(-) nfs-utils-1.0.8/utils/gssd/context_mit.c~CITI_NFS4_ALL (-37 / +474 lines)
 Lines 32-37    Link Here 
#include <stdio.h>
#include <stdio.h>
#include <syslog.h>
#include <syslog.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <gssapi/gssapi.h>
#include <gssapi/gssapi.h>
#include <rpc/rpc.h>
#include <rpc/rpc.h>
#include <rpc/auth_gss.h>
#include <rpc/auth_gss.h>
 Lines 43-51    Link Here 
#ifdef HAVE_KRB5
#ifdef HAVE_KRB5
#include <krb5.h>
#include <krb5.h>
/* for 3DES */
#define KG_USAGE_SEAL 22
#define KG_USAGE_SIGN 23
#define KG_USAGE_SEQ  24
/* for rfc???? */
#define KG_USAGE_ACCEPTOR_SEAL  22
#define KG_USAGE_ACCEPTOR_SIGN  23
#define KG_USAGE_INITIATOR_SEAL 24
#define KG_USAGE_INITIATOR_SIGN 25
/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
enum seal_alg {
  SEAL_ALG_NONE            = 0xffff,
  SEAL_ALG_DES             = 0x0000,
  SEAL_ALG_1               = 0x0001, /* not published */
  SEAL_ALG_MICROSOFT_RC4   = 0x0010, /* microsoft w2k;  */
  SEAL_ALG_DES3KD          = 0x0002
};
#define KEY_USAGE_SEED_ENCRYPTION	0xAA
#define KEY_USAGE_SEED_INTEGRITY	0x55
#define KEY_USAGE_SEED_CHECKSUM		0x99
#define K5CLENGTH 5
/* Flags for version 2 context flags */
#define KRB5_CTX_FLAG_INITIATOR		0x00000001
#define KRB5_CTX_FLAG_CFX		0x00000002
#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY	0x00000004
/*
 * XXX Hack alert.  We don't have "legal" access to these
 * structures located in libk5crypto
 */
extern void krb5int_enc_arcfour;
extern void krb5int_enc_des3;
extern void krb5int_enc_aes128;
extern void krb5int_enc_aes256;
extern int krb5_derive_key();
void *get_enc_provider();
/* XXX spkm3 seems to actually want it this big, yipes. */
/* XXX spkm3 seems to actually want it this big, yipes. */
#define MAX_CTX_LEN 4096
#define MAX_CTX_LEN 4096
#ifdef HAVE_LUCID_CONTEXT_SUPPORT
#ifdef HAVE_LUCID_CONTEXT_SUPPORT
/* Don't use the private structure, use the exported lucid structure */
/* Don't use the private structure, use the exported lucid structure */
 Lines 86-92   typedef struct _krb5_gss_ctx_id_rec { Link Here 
   uint64_t seq_recv;		/* gssint_uint64 */
   uint64_t seq_recv;		/* gssint_uint64 */
   void *seqstate;
   void *seqstate;
   krb5_auth_context auth_context;
   krb5_auth_context auth_context;
   gss_buffer_desc *mech_used;	/* gss_OID_desc */
   gss_OID_desc *mech_used;	/* gss_OID_desc */
    /* Protocol spec revision
    /* Protocol spec revision
       0 => RFC 1964 with 3DES and RC4 enhancements
       0 => RFC 1964 with 3DES and RC4 enhancements
       1 => draft-ietf-krb-wg-gssapi-cfx-01
       1 => draft-ietf-krb-wg-gssapi-cfx-01
 Lines 123-129   typedef struct _krb5_gss_ctx_id_rec { Link Here 
	int established;
	int established;
	int big_endian;
	int big_endian;
	krb5_auth_context auth_context;
	krb5_auth_context auth_context;
	gss_buffer_desc *mech_used;
	gss_OID_desc *mech_used;
	int nctypes;
	int nctypes;
	krb5_cksumtype *ctypes;
	krb5_cksumtype *ctypes;
} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
 Lines 144-149   write_lucid_keyblock(char **p, char *end Link Here 
	return 0;
	return 0;
}
}
static void
key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
{
	memset(kout, '\0', sizeof(kout));
	kout->enctype = lin->type;
	kout->length = lin->length;
	kout->contents = lin->data;
}
static void
key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
{
	memset(lout, '\0', sizeof(lout));
	lout->type = kin->enctype;
	lout->length = kin->length;
	lout->data = kin->contents;
}
/*
 * Function to derive a new key from a given key and given constant data.
 */
static krb5_error_code
derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
		 int usage, char extra)
{
	krb5_error_code code;
	unsigned char constant_data[K5CLENGTH];
	krb5_data datain;
	int keylength;
	void *enc;
	krb5_keyblock kin, kout;  /* must send krb5_keyblock, not lucid! */
	/*
	 * XXX Hack alert.  We don't have "legal" access to these
	 * values and structures located in libk5crypto
	 */
	switch (in->type) {
	case ENCTYPE_DES3_CBC_RAW:
		keylength = 24;
		enc = &krb5int_enc_des3;
		break;
	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
		keylength = 16;
		enc = &krb5int_enc_aes128;
		break;
	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
		keylength = 32;
		enc = &krb5int_enc_aes256;
		break;
	default:
		code = KRB5_BAD_ENCTYPE;
		goto out;
	}
	/* allocate memory for output key */
	if ((out->data = malloc(keylength)) == NULL) {
		code = ENOMEM;
		goto out;
	}
	out->length = keylength;
	out->type = in->type;
	/* Convert to correct format for call to krb5_derive_key */
	key_lucid_to_krb5(in, &kin);
	key_lucid_to_krb5(out, &kout);
	datain.data = (char *) constant_data;
	datain.length = K5CLENGTH;
	datain.data[0] = (usage>>24)&0xff;
	datain.data[1] = (usage>>16)&0xff;
	datain.data[2] = (usage>>8)&0xff;
	datain.data[3] = usage&0xff;
	datain.data[4] = (char) extra;
	if ((code = krb5_derive_key(enc, &kin, &kout, &datain))) {
		free(out->data);
		out->data = NULL;
		goto out;
	}
	key_krb5_to_lucid(&kout, out);
  out:
  	if (code)
		printerr(0, "ERROR: derive_key_lucid returning error %d (%s)\n",
			 code, error_message(code));
	return (code);
}
static int
static int
prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
	gss_buffer_desc *buf)
	gss_buffer_desc *buf)
 Lines 183-189   prepare_krb5_rfc1964_buffer(gss_krb5_luc Link Here 
	if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
	if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
	word_send_seq = lctx->send_seq;	/* XXX send_seq is 64-bit */
	word_send_seq = lctx->send_seq;	/* XXX send_seq is 64-bit */
	if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err;
	if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err;
	if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err;
	if (write_oid(&p, end, &krb5oid)) goto out_err;
	printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
	printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
		 "enctype %d and length %d\n",
		 "enctype %d and length %d\n",
 Lines 212-228   prepare_krb5_rfc1964_buffer(gss_krb5_luc Link Here 
	return 0;
	return 0;
out_err:
out_err:
	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
	if (buf->value) free(buf->value);
	if (buf->value) {
		free(buf->value);
		buf->value = NULL;
	}
	buf->length = 0;
	buf->length = 0;
	if (enc_key.data) free(enc_key.data);
	if (enc_key.data) {
		free(enc_key.data);
		enc_key.data = NULL;
	}
	return -1;
	return -1;
}
}
/*
 * Prepare a new-style buffer to send to the kernel for newer encryption
 * types -- or for DES3.
 *
 * The new format is:
 *
 *	u32 version;          This is two (2)
 *	s32 endtime;
 *	u32 flags;
 *	#define KRB5_CTX_FLAG_INITIATOR		0x00000001
 *	#define KRB5_CTX_FLAG_CFX		0x00000002
 *	#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY	0x00000004
 *	u64 seq_send;
 *	u32  enctype;			( encrption type of keys )
 *	u32  size_of_each_key;		( size of each key in bytes )
 *	u32  number_of_keys;		( N -- should always be 3 for now )
 *	keydata-1;                      ( Ke )
 *	keydata-2;                      ( Ki )
 *	keydata-3;                      ( Kc )
 *
 */
static int
static int
prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
prepare_krb5_ctx_v2_buffer(gss_krb5_lucid_context_v1_t *lctx,
	gss_buffer_desc *buf)
	gss_buffer_desc *buf)
{
{
	printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
	char *p, *end;
	static uint32_t version = 2;
	uint32_t v2_flags = 0;
	gss_krb5_lucid_key_t enc_key;
	gss_krb5_lucid_key_t derived_key;
	gss_buffer_desc fakeoid;
	uint32_t enctype;
	uint32_t keysize;
	uint32_t numkeys;
	memset(&enc_key, 0, sizeof(enc_key));
	memset(&fakeoid, 0, sizeof(fakeoid));
	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
		goto out_err;
	p = buf->value;
	end = buf->value + MAX_CTX_LEN;
	/* Version 2 */
	if (WRITE_BYTES(&p, end , version)) goto out_err;
	if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
	if (lctx->initiate)
		v2_flags |= KRB5_CTX_FLAG_INITIATOR;
	if (lctx->protocol != 0)
		v2_flags |= KRB5_CTX_FLAG_CFX;
	if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
		v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
	if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
	if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
	/* Protocol 0 here implies DES3 or RC4 */
	if (lctx->protocol == 0) {
		enctype = lctx->rfc1964_kd.ctx_key.type;
		keysize = lctx->rfc1964_kd.ctx_key.length;
		numkeys = 3;	/* XXX is always gonna be three? */
	} else {
		if (lctx->cfx_kd.have_acceptor_subkey) {
			enctype = lctx->cfx_kd.acceptor_subkey.type;
			keysize = lctx->cfx_kd.acceptor_subkey.length;
		} else {
			enctype = lctx->cfx_kd.ctx_key.type;
			keysize = lctx->cfx_kd.ctx_key.length;
		}
		numkeys = 3;
	}
	printerr(2, "prepare_krb5_ctx_v2_buffer: serializing %d keys with "
		 "enctype %d and size %d\n", numkeys, enctype, keysize);
	if (WRITE_BYTES(&p, end, enctype)) goto out_err;
	if (WRITE_BYTES(&p, end, keysize)) goto out_err;
	if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
	if (lctx->protocol == 0) {
		/* derive and send down: Ke, Ki, and Kc */
		/* Ke */
		if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
				lctx->rfc1964_kd.ctx_key.length))
			goto out_err;
		/* Ki */
		if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
				lctx->rfc1964_kd.ctx_key.length))
			goto out_err;
		/* Kc */
		if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key,
				&derived_key,
				KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
			goto out_err;
		if (write_bytes(&p, end, derived_key.data,
				derived_key.length))
			goto out_err;
		free(derived_key.data);
	} else {
		gss_krb5_lucid_key_t *keyptr;
		uint32_t sign_usage, seal_usage;
		if (lctx->cfx_kd.have_acceptor_subkey)
			keyptr = &lctx->cfx_kd.acceptor_subkey;
		else
			keyptr = &lctx->cfx_kd.ctx_key;
		if (lctx->initiate == 1) {
			sign_usage = KG_USAGE_INITIATOR_SIGN;
			seal_usage = KG_USAGE_INITIATOR_SEAL;
		} else {
			sign_usage = KG_USAGE_ACCEPTOR_SIGN;
			seal_usage = KG_USAGE_ACCEPTOR_SEAL;
		}
		/* derive and send down: Ke, Ki, and Kc */
		/* Ke */
		if (derive_key_lucid(keyptr, &derived_key,
			       seal_usage, KEY_USAGE_SEED_ENCRYPTION))
			goto out_err;
		if (write_bytes(&p, end, derived_key.data,
				derived_key.length))
			goto out_err;
		free(derived_key.data);
		/* Ki */
		if (derive_key_lucid(keyptr, &derived_key,
			       seal_usage, KEY_USAGE_SEED_INTEGRITY))
			goto out_err;
		if (write_bytes(&p, end, derived_key.data,
				derived_key.length))
			goto out_err;
		free(derived_key.data);
		/* Kc */
		if (derive_key_lucid(keyptr, &derived_key,
			       sign_usage, KEY_USAGE_SEED_CHECKSUM))
			goto out_err;
		if (write_bytes(&p, end, derived_key.data,
				derived_key.length))
			goto out_err;
		free(derived_key.data);
	}
	buf->length = p - (char *)buf->value;
	return 0;
out_err:
	printerr(0, "ERROR: prepare_krb5_ctx_v2_buffer: "
		 "failed serializing krb5 context for kernel\n");
	if (buf->value) {
		free(buf->value);
		buf->value = NULL;
	}
	buf->length = 0;
	if (enc_key.data) {
		free(enc_key.data);
		enc_key.data = NULL;
	}
	return -1;
	return -1;
}
}
 Lines 258-268   serialize_krb5_ctx(gss_ctx_id_t ctx, gss Link Here 
		break;
		break;
	}
	}
	/* Now lctx points to a lucid context that we can send down to kernel */
	/*
	if (lctx->protocol == 0)
	 * Now lctx points to a lucid context that we can send down to kernel
	 *
	 * Note: we send down different information to the kernel depending
	 * on the protocol version and the enctyption type.
	 * For protocol version 0 with all enctypes besides DES3, we use
	 * the original format.  For protocol version != 0 or DES3, we
	 * send down the new style information.
	 */
	if (lctx->protocol == 0 &&
		lctx->rfc1964_kd.ctx_key.type == ENCTYPE_DES_CBC_RAW)
		retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
		retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
	else
	else
		retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
		retcode = prepare_krb5_ctx_v2_buffer(lctx, buf);
	maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
	maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
	if (maj_stat != GSS_S_COMPLETE) {
	if (maj_stat != GSS_S_COMPLETE) {
 Lines 300-305   write_keyblock(char **p, char *end, stru Link Here 
}
}
/*
/*
 * Function to derive a new key from a given key and given constant data.
 */
static krb5_error_code
derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
{
	krb5_error_code code;
	unsigned char constant_data[K5CLENGTH];
	krb5_data datain;
	int keylength;
	void *enc;
	/*
	 * XXX Hack alert.  We don't have "legal" access to these
	 * values and structures located in libk5crypto
	 */
	switch (in->enctype) {
	case ENCTYPE_DES3_CBC_RAW:
		keylength = 24;
		enc = &krb5int_enc_des3;
		break;
	case ENCTYPE_ARCFOUR_HMAC:
		keylength = 16;
		enc = &krb5int_enc_arcfour;
		break;
	default:
		code = KRB5_BAD_ENCTYPE;
		goto out;
	}
	/* allocate memory for output key */
	if ((out->contents = malloc(keylength)) == NULL) {
		code = ENOMEM;
		goto out;
	}
	out->length = keylength;
	out->enctype = in->enctype;
	datain.data = (char *) constant_data;
	datain.length = K5CLENGTH;
	datain.data[0] = (usage>>24)&0xff;
	datain.data[1] = (usage>>16)&0xff;
	datain.data[2] = (usage>>8)&0xff;
	datain.data[3] = usage&0xff;
	datain.data[4] = (char) extra;
	if ((code = krb5_derive_key(enc, in, out, &datain))) {
		free(out->contents);
		out->contents = NULL;
	}
  out:
  	if (code)
		printerr(0, "ERROR: derive_key returning error %d (%s)\n",
			 code, error_message(code));
	return (code);
}
/*
 * We really shouldn't know about glue-layer context structure, but
 * We really shouldn't know about glue-layer context structure, but
 * we need to get at the real krb5 context pointer.  This should be
 * we need to get at the real krb5 context pointer.  This should be
 * removed as soon as we say there is no support for MIT Kerberos
 * removed as soon as we say there is no support for MIT Kerberos
 Lines 315-359   serialize_krb5_ctx(gss_ctx_id_t ctx, gss Link Here 
{
{
	krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
	krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
	char *p, *end;
	char *p, *end;
	static int constant_one = 1;
	static int constant_zero = 0;
	static int constant_zero = 0;
	static int constant_one = 1;
	static int constant_two = 2;
	uint32_t word_seq_send;
	uint32_t word_seq_send;
	u_int64_t seq_send_64bit;
	uint32_t v2_flags = 0;
	krb5_keyblock derived_key;
	uint32_t numkeys;
	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
		goto out_err;
		goto out_err;
	p = buf->value;
	p = buf->value;
	end = buf->value + MAX_CTX_LEN;
	end = buf->value + MAX_CTX_LEN;
	if (kctx->initiate) {
	switch (kctx->sealalg) {
		if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
	case SEAL_ALG_DES:
	}
		/* Versions 0 and 1 */
	else {
		if (kctx->initiate) {
		if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
			if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
	}
		}
	if (kctx->seed_init) {
		else {
		if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
			if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
	}
		}
	else {
		if (kctx->seed_init) {
		if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
			if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
	}
		}
	if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
		else {
		goto out_err;
			if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
	if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
		}
	if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
		if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
	if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
			goto out_err;
	word_seq_send = kctx->seq_send;
		if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
	if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
		if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
	if (write_buffer(&p, end, kctx->mech_used)) goto out_err;
		if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
		word_seq_send = kctx->seq_send;
	printerr(2, "serialize_krb5_ctx: serializing keys with "
		if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
		 "enctype %d and length %d\n",
		if (write_oid(&p, end, kctx->mech_used)) goto out_err;
		 kctx->enc->enctype, kctx->enc->length);
		printerr(2, "serialize_krb5_ctx: serializing keys with "
			 "enctype %d and length %d\n",
			 kctx->enc->enctype, kctx->enc->length);
	if (write_keyblock(&p, end, kctx->enc)) goto out_err;
		if (write_keyblock(&p, end, kctx->enc)) goto out_err;
	if (write_keyblock(&p, end, kctx->seq)) goto out_err;
		if (write_keyblock(&p, end, kctx->seq)) goto out_err;
		break;
	case SEAL_ALG_MICROSOFT_RC4:
	case SEAL_ALG_DES3KD:
		/* u32 version;   ( 2 )
		 * s32 endtime;
		 * u32 flags;
		 * #define KRB5_CTX_FLAG_INITIATOR        0x00000001
		 * #define KRB5_CTX_FLAG_CFX              0x00000002
		 * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
		 * u64 seq_send;
		 * u32  enctype;
		 * u32  size_of_each_key;    (  size in bytes )
		 * u32  number_of_keys;      (  N (assumed to be 3 for now) )
		 * keydata-1;                (  Ke  (Kenc for DES3) )
		 * keydata-2;                (  Ki  (Kseq for DES3) )
		 * keydata-3;                (  Kc (derived checksum key) )
		 */
		 /* Version 2 */
		if (WRITE_BYTES(&p, end , constant_two)) goto out_err;
		if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
		/* Only applicable flag for is initiator */
		if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR;
		if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
		seq_send_64bit = kctx->seq_send;
		if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
		if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
		if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
		numkeys = 3;
		if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
		printerr(2, "serialize_krb5_ctx: serializing %d keys with "
			 "enctype %d and size %d\n",
			 numkeys, kctx->enc->enctype, kctx->enc->length);
		/* Ke */
		if (write_bytes(&p, end, kctx->enc->contents,
				kctx->enc->length))
			goto out_err;
		/* Ki */
		if (write_bytes(&p, end, kctx->enc->contents,
				kctx->enc->length))
			goto out_err;
		/* Kc */
		if (derive_key(kctx->seq, &derived_key,
			       KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
			goto out_err;
		if (write_bytes(&p, end, derived_key.contents,
				derived_key.length))
			goto out_err;
		free(derived_key.contents);
		break;
	default:
		printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
			 "algorithm %d\n", kctx->sealalg);
		goto out_err;
	}
	buf->length = p - (char *)buf->value;
	buf->length = p - (char *)buf->value;
	return 0;
	return 0;
out_err:
out_err:
	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
	if (buf->value) free(buf->value);
	if (buf->value) free(buf->value);
(-) nfs-utils-1.0.8/utils/gssd/write_bytes.h~CITI_NFS4_ALL (-1 / +14 lines)
 Lines 56-68   write_buffer(char **p, char *end, gss_bu Link Here 
	int len = (int)arg->length;		/* make an int out of size_t */
	int len = (int)arg->length;		/* make an int out of size_t */
	if (WRITE_BYTES(p, end, len))
	if (WRITE_BYTES(p, end, len))
		return -1;
		return -1;
	if (*p + arg->length > end)
	if (*p + len > end)
		return -1;
		return -1;
	memcpy(*p, arg->value, len);
	memcpy(*p, arg->value, len);
	*p += len;
	*p += len;
	return 0;
	return 0;
}
}
inline static int
write_oid(char **p, char *end, gss_OID_desc *arg)
{
	int len = (int)arg->length;		/* make an int out of size_t */
	if (WRITE_BYTES(p, end, len))
		return -1;
	if (*p + arg->length > end)
		return -1;
	memcpy(*p, arg->elements, len);
	*p += len;
	return 0;
}
static inline int
static inline int
get_bytes(char **ptr, const char *end, void *res, int len)
get_bytes(char **ptr, const char *end, void *res, int len)
{
{
(-) nfs-utils-1.0.8/utils/gssd/cacheio.c~CITI_NFS4_ALL (-6 / +12 lines)
 Lines 55-60    Link Here 
#include <time.h>
#include <time.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include "err_util.h"
#include "err_util.h"
void qword_add(char **bpp, int *lp, char *str)
void qword_add(char **bpp, int *lp, char *str)
 Lines 244-249   int qword_get_int(char **bpp, int *anint Link Here 
	return 0;
	return 0;
}
}
#define READLINE_BUFFER_INCREMENT 2048
int readline(int fd, char **buf, int *lenp)
int readline(int fd, char **buf, int *lenp)
{
{
	/* read a line into *buf, which is malloced *len long
	/* read a line into *buf, which is malloced *len long
 Lines 254-268   int readline(int fd, char **buf, int *le Link Here 
	int len;
	int len;
	if (*lenp == 0) {
	if (*lenp == 0) {
		char *b = malloc(128);
		char *b = malloc(READLINE_BUFFER_INCREMENT);
		if (b == NULL)
		if (b == NULL)
			return 0;
			return 0;
		*buf = b;
		*buf = b;
		*lenp = 128;
		*lenp = READLINE_BUFFER_INCREMENT;
	}
	}
	len = read(fd, *buf, *lenp);
	len = read(fd, *buf, *lenp);
	if (len <= 0) {
	if (len <= 0) {
		printerr(2, "read error in readline: %d\n", len);
		printerr(0, "readline: read error: len %d errno %d (%s)\n",
			 len, errno, strerror(errno));
		return 0;
		return 0;
	}
	}
	while ((*buf)[len-1] != '\n') {
	while ((*buf)[len-1] != '\n') {
 Lines 271-289   int readline(int fd, char **buf, int *le Link Here 
	 */
	 */
		char *new;
		char *new;
		int nl;
		int nl;
		*lenp += 128;
		*lenp += READLINE_BUFFER_INCREMENT;
		new = realloc(*buf, *lenp);
		new = realloc(*buf, *lenp);
		if (new == NULL)
		if (new == NULL)
			return 0;
			return 0;
		*buf = new;
		*buf = new;
		nl = read(fd, *buf +len, *lenp - len);
		nl = read(fd, *buf +len, *lenp - len);
		if (nl <= 0 ) {
		if (nl <= 0 ) {
			printerr(2, "read error in readline: %d\n", nl);
			printerr(0, "readline: read error: len %d "
				 "errno %d (%s)\n", nl, errno, strerror(errno));
			return 0;
			return 0;
		}
		}
		len += nl;
		len += nl;
	}
	}
	(*buf)[len-1] = 0;
	(*buf)[len-1] = 0;
	printerr(1, "read line with %d characters:\n%s\n", *lenp, *buf);
	printerr(3, "readline: read %d chars into buffer of size %d:\n%s\n",
		 len, *lenp, *buf);
	return 1;
	return 1;
}
}
(-) nfs-utils-1.0.8/utils/gssd/svcgssd_proc.c~CITI_NFS4_ALL (-3 / +16 lines)
 Lines 140-146   send_response(FILE *f, gss_buffer_desc * Link Here 
		return -1;
		return -1;
	}
	}
	*bp = '\0';
	*bp = '\0';
	printerr(1, "writing message: %s", buf);
	printerr(3, "writing message: %s", buf);
	if (write(g, buf, bp - buf) == -1) {
	if (write(g, buf, bp - buf) == -1) {
		printerr(0, "WARNING: failed to write message\n");
		printerr(0, "WARNING: failed to write message\n");
		close(g);
		close(g);
 Lines 220-227   get_ids(gss_name_t client_name, gss_OID Link Here 
	nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
	nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
	res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid);
	res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid);
	if (res < 0) {
	if (res < 0) {
		printerr(0, "WARNING: get_ids: unable to map "
		/*
			"name '%s' to a uid\n", sname);
		 * -ENOENT means there was no mapping, any other error
		 * value means there was an error trying to do the
		 * mapping.
		 */
		if (res == -ENOENT) {
			cred->cr_uid = -2;	/* XXX */
			cred->cr_gid = -2;	/* XXX */
			cred->cr_groups[0] = -2;/* XXX */
			cred->cr_ngroups = 1;
			res = 0;
			goto out_free;
		}
		printerr(0, "WARNING: get_ids: failed to map name '%s' "
			"to uid/gid: %s\n", sname, strerror(-res));
		goto out_free;
		goto out_free;
	}
	}
	cred->cr_uid = uid;
	cred->cr_uid = uid;