17c478bd9Sstevel@tonic-gate /*
2a0a37ffdSShawn Emery  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * lib/krb5/krb/init_ctx.c
87c478bd9Sstevel@tonic-gate  *
9505d05c7Sgtb  * Copyright 1994,1999,2000, 2002, 2003  by the Massachusetts Institute of Technology.
107c478bd9Sstevel@tonic-gate  * All Rights Reserved.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
137c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
147c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
157c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
16*55fea89dSDan Cross  *
177c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
197c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
207c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
217c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
227c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
237c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
247c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
257c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
267c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
277c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
287c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
297c478bd9Sstevel@tonic-gate  * or implied warranty.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * krb5_init_contex()
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
36*55fea89dSDan Cross  *
377c478bd9Sstevel@tonic-gate  * All rights reserved.
38*55fea89dSDan Cross  *
397c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
407c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
417c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
427c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
43*55fea89dSDan Cross  *
447c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
457c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
467c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
477c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
487c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
497c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
507c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
517c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
527c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
537c478bd9Sstevel@tonic-gate  * or implied warranty.
54*55fea89dSDan Cross  *
557c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
567c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
577c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate 
60159d09a2SMark Phalan #include "k5-int.h"
617c478bd9Sstevel@tonic-gate 
62*55fea89dSDan Cross /*
637c478bd9Sstevel@tonic-gate  * Solaris Kerberos: the code related to EF/pkcs11 and fork safety are mods Sun
647c478bd9Sstevel@tonic-gate  * has made to the MIT code.
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate #ifndef _KERNEL
687c478bd9Sstevel@tonic-gate #include <ctype.h>
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate pid_t __krb5_current_pid; /* fork safety: contains the current process ID */
717c478bd9Sstevel@tonic-gate #endif
727c478bd9Sstevel@tonic-gate 
73505d05c7Sgtb #ifndef _KERNEL
74505d05c7Sgtb #include <krb5_libinit.h>
75505d05c7Sgtb #endif
76505d05c7Sgtb 
77505d05c7Sgtb /* The des-mdX entries are last for now, because it's easy to
78505d05c7Sgtb    configure KDCs to issue TGTs with des-mdX keys and then not accept
79505d05c7Sgtb    them.  This'll be fixed, but for better compatibility, let's prefer
80505d05c7Sgtb    des-crc for now.  */
81a0a37ffdSShawn Emery /*
82a0a37ffdSShawn Emery  * Solaris Kerberos:
83a0a37ffdSShawn Emery  * Added arcfour-hmac-md5-exp as default enc type.
84a0a37ffdSShawn Emery  * Changed des3-hmac-sha1 to des3-cbc-sha1-kd, as specified in RFC3961.
85a0a37ffdSShawn Emery  */
86505d05c7Sgtb #define DEFAULT_ETYPE_LIST	\
87505d05c7Sgtb 	"aes256-cts-hmac-sha1-96 " \
88505d05c7Sgtb 	"aes128-cts-hmac-sha1-96 " \
89a0a37ffdSShawn Emery 	"des3-cbc-sha1-kd " \
90505d05c7Sgtb 	"arcfour-hmac-md5 " \
91a0a37ffdSShawn Emery 	"arcfour-hmac-md5-exp " \
92505d05c7Sgtb 	"des-cbc-md5 " \
93505d05c7Sgtb 	"des-cbc-crc"
94505d05c7Sgtb 
95505d05c7Sgtb 
967c478bd9Sstevel@tonic-gate /* The only functions that are needed from this file when in kernel are
977c478bd9Sstevel@tonic-gate  * krb5_init_context and krb5_free_context.
987c478bd9Sstevel@tonic-gate  * In krb5_init_context we need only os_init_context since we don'it need the
997c478bd9Sstevel@tonic-gate  * profile info unless we do init/accept in kernel. Currently only mport,
1007c478bd9Sstevel@tonic-gate  * delete , sign/verify, wrap/unwrap routines are ported to the kernel.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate 
103159d09a2SMark Phalan #if (defined(_WIN32))
1047c478bd9Sstevel@tonic-gate extern krb5_error_code krb5_vercheck();
1057c478bd9Sstevel@tonic-gate extern void krb5_win_ccdll_load(krb5_context context);
1067c478bd9Sstevel@tonic-gate #endif
1077c478bd9Sstevel@tonic-gate 
10854925bf6Swillf static krb5_error_code init_common (krb5_context *, krb5_boolean, krb5_boolean);
1097c478bd9Sstevel@tonic-gate 
110505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_init_context(krb5_context * context)111159d09a2SMark Phalan krb5_init_context(krb5_context *context)
1127c478bd9Sstevel@tonic-gate {
113159d09a2SMark Phalan 
11454925bf6Swillf 	return init_common (context, FALSE, FALSE);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
117505d05c7Sgtb krb5_error_code KRB5_CALLCONV
krb5_init_secure_context(krb5_context * context)118159d09a2SMark Phalan krb5_init_secure_context(krb5_context *context)
1197c478bd9Sstevel@tonic-gate {
120159d09a2SMark Phalan 
121159d09a2SMark Phalan #if 0 /* Solaris Kerberos */
122159d09a2SMark Phalan         /* This is to make gcc -Wall happy */
123159d09a2SMark Phalan         if(0) krb5_brand[0] = krb5_brand[0];
124159d09a2SMark Phalan #endif
12554925bf6Swillf 	return init_common (context, TRUE, FALSE);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate #ifndef _KERNEL
12954925bf6Swillf 
13054925bf6Swillf krb5_error_code
krb5int_init_context_kdc(krb5_context * context)13154925bf6Swillf krb5int_init_context_kdc(krb5_context *context)
13254925bf6Swillf {
13354925bf6Swillf     return init_common (context, FALSE, TRUE);
13454925bf6Swillf }
13554925bf6Swillf 
136159d09a2SMark Phalan /* Solaris Kerberos */
1377c478bd9Sstevel@tonic-gate krb5_error_code
krb5_open_pkcs11_session(CK_SESSION_HANDLE * hSession)1387c478bd9Sstevel@tonic-gate krb5_open_pkcs11_session(CK_SESSION_HANDLE *hSession)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	krb5_error_code retval = 0;
141*55fea89dSDan Cross 	CK_RV rv;
142*55fea89dSDan Cross 	CK_SLOT_ID_PTR slotlist = NULL_PTR;
143*55fea89dSDan Cross 	CK_ULONG slotcount;
1447c478bd9Sstevel@tonic-gate 	CK_ULONG i;
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	/* List of all Slots */
1477c478bd9Sstevel@tonic-gate 	rv = C_GetSlotList(FALSE, NULL_PTR, &slotcount);
1487c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1497c478bd9Sstevel@tonic-gate 		KRB5_LOG(KRB5_ERR, "C_GetSlotList failed with 0x%x.", rv);
1507c478bd9Sstevel@tonic-gate 		retval = PKCS_ERR;
1517c478bd9Sstevel@tonic-gate 		goto cleanup;
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	if (slotcount == 0) {
1557c478bd9Sstevel@tonic-gate 		KRB5_LOG0(KRB5_ERR, "No slot is found in PKCS11.");
1567c478bd9Sstevel@tonic-gate 		retval = PKCS_ERR;
1577c478bd9Sstevel@tonic-gate 		goto cleanup;
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 
160*55fea89dSDan Cross 	slotlist = (CK_SLOT_ID_PTR)malloc(slotcount * sizeof(CK_SLOT_ID));
1617c478bd9Sstevel@tonic-gate 	if (slotlist == NULL) {
1627c478bd9Sstevel@tonic-gate 		KRB5_LOG0(KRB5_ERR, "malloc failed for slotcount.");
1637c478bd9Sstevel@tonic-gate 		retval = PKCS_ERR;
1647c478bd9Sstevel@tonic-gate 		goto cleanup;
1657c478bd9Sstevel@tonic-gate 	}
166*55fea89dSDan Cross 
1677c478bd9Sstevel@tonic-gate 	rv = C_GetSlotList(FALSE, slotlist, &slotcount);
1687c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1697c478bd9Sstevel@tonic-gate 		KRB5_LOG(KRB5_ERR, "C_GetSlotList failed with 0x%x", rv);
1707c478bd9Sstevel@tonic-gate 		retval = PKCS_ERR;
1717c478bd9Sstevel@tonic-gate 		goto cleanup;
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 	for (i = 0; i < slotcount; i++) {
1747c478bd9Sstevel@tonic-gate 		if (slot_supports_krb5(slotlist + i))
1757c478bd9Sstevel@tonic-gate 			break;
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate 	if (i == slotcount){
1787c478bd9Sstevel@tonic-gate 		KRB5_LOG0(KRB5_ERR, "Could not find slot which supports "
1797c478bd9Sstevel@tonic-gate 		   "Kerberos");
1807c478bd9Sstevel@tonic-gate 		retval = PKCS_ERR;
1817c478bd9Sstevel@tonic-gate 		goto cleanup;
1827c478bd9Sstevel@tonic-gate 	}
1837c478bd9Sstevel@tonic-gate 	rv = C_OpenSession(slotlist[i], CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR,
1847c478bd9Sstevel@tonic-gate 	    hSession);
1857c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1867c478bd9Sstevel@tonic-gate 		retval = PKCS_ERR;
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate cleanup:
1897c478bd9Sstevel@tonic-gate 	if (slotlist != NULL)
1907c478bd9Sstevel@tonic-gate 		free(slotlist);
1917c478bd9Sstevel@tonic-gate 	return(retval);
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * krb5_reinit_ef_handle()
1967c478bd9Sstevel@tonic-gate  *
1977c478bd9Sstevel@tonic-gate  * deal with fork safety issue regarding the krb ctx and the pkcs11 hSession
1987c478bd9Sstevel@tonic-gate  * field.  This function is called if it is determined that the krb ctx hSession
1997c478bd9Sstevel@tonic-gate  * is being accessed in a child process after a fork().  This function
2007c478bd9Sstevel@tonic-gate  * re-initilizes the pkcs11 session and returns the session handle.
2017c478bd9Sstevel@tonic-gate  */
2027c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE
krb5_reinit_ef_handle(krb5_context ctx)2037c478bd9Sstevel@tonic-gate krb5_reinit_ef_handle(krb5_context ctx)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate     ctx->cryptoki_initialized = FALSE;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate     if (krb5_init_ef_handle(ctx) != 0) {
2087c478bd9Sstevel@tonic-gate 	/*
2097c478bd9Sstevel@tonic-gate 	 * krb5_free_ef_handle() not needed here -- we assume that an equivalent
2107c478bd9Sstevel@tonic-gate 	 * of C_Finalize() was done in the child-side of the fork(), so all EF
2117c478bd9Sstevel@tonic-gate 	 * resources in this context will be invalid.
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 	return(CK_INVALID_HANDLE);
2147c478bd9Sstevel@tonic-gate     }
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate     /* reset the ctx pid since we're in a new process (child) */
217*55fea89dSDan Cross     ctx->pid = __krb5_current_pid;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate     /* If the RC4 handles were initialized, reset them here */
2207c478bd9Sstevel@tonic-gate     if (ctx->arcfour_ctx.initialized) {
2217c478bd9Sstevel@tonic-gate 	krb5_error_code ret;
2227c478bd9Sstevel@tonic-gate 	ret = krb5_open_pkcs11_session(&ctx->arcfour_ctx.eSession);
2237c478bd9Sstevel@tonic-gate         if (ret) {
2247c478bd9Sstevel@tonic-gate 		ctx->arcfour_ctx.initialized = 0;
2257c478bd9Sstevel@tonic-gate 		ctx->arcfour_ctx.eSession = CK_INVALID_HANDLE;
2267c478bd9Sstevel@tonic-gate 		C_CloseSession(ctx->hSession);
2277c478bd9Sstevel@tonic-gate 		ctx->hSession = CK_INVALID_HANDLE;
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate         ret = krb5_open_pkcs11_session(&ctx->arcfour_ctx.dSession);
2307c478bd9Sstevel@tonic-gate         if (ret) {
2317c478bd9Sstevel@tonic-gate 		ctx->arcfour_ctx.initialized = 0;
2327c478bd9Sstevel@tonic-gate 		ctx->arcfour_ctx.eSession = CK_INVALID_HANDLE;
2337c478bd9Sstevel@tonic-gate 		ctx->arcfour_ctx.dSession = CK_INVALID_HANDLE;
2347c478bd9Sstevel@tonic-gate 		C_CloseSession(ctx->hSession);
2357c478bd9Sstevel@tonic-gate 		ctx->hSession = CK_INVALID_HANDLE;
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate     }
2387c478bd9Sstevel@tonic-gate 
239*55fea89dSDan Cross     /*
2407c478bd9Sstevel@tonic-gate      * It is safe for this function to access ctx->hSession directly.  Do
2417c478bd9Sstevel@tonic-gate      * NOT use the krb_ctx_hSession() here.
2427c478bd9Sstevel@tonic-gate      */
2437c478bd9Sstevel@tonic-gate     return(ctx->hSession);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate /*
2477c478bd9Sstevel@tonic-gate  * krb5_pthread_atfork_child_handler() sets a global that indicates the current
2487c478bd9Sstevel@tonic-gate  * PID.  This is an optimization to keep getpid() from being called a zillion
2497c478bd9Sstevel@tonic-gate  * times.
2507c478bd9Sstevel@tonic-gate  */
2517c478bd9Sstevel@tonic-gate void
krb5_pthread_atfork_child_handler()2527c478bd9Sstevel@tonic-gate krb5_pthread_atfork_child_handler()
2537c478bd9Sstevel@tonic-gate {
254*55fea89dSDan Cross     /*
2557c478bd9Sstevel@tonic-gate      * __krb5_current_pid should always be set to current process ID, see the
256*55fea89dSDan Cross      * definition of krb_ctx_hSession() for more info
2577c478bd9Sstevel@tonic-gate      */
2587c478bd9Sstevel@tonic-gate     __krb5_current_pid = getpid();
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate  * krb5_ld_init() contains code that will be executed at load time (via the
2637c478bd9Sstevel@tonic-gate  * ld -zinitarray directive).
2647c478bd9Sstevel@tonic-gate  */
2657c478bd9Sstevel@tonic-gate void
krb5_ld_init()2667c478bd9Sstevel@tonic-gate krb5_ld_init()
2677c478bd9Sstevel@tonic-gate {
268*55fea89dSDan Cross     /*
2697c478bd9Sstevel@tonic-gate      * fork safety: __krb5_current_pid should always be set to current process
270*55fea89dSDan Cross      * ID, see the definition of krb_ctx_hSession() for more info
2717c478bd9Sstevel@tonic-gate      */
2727c478bd9Sstevel@tonic-gate     __krb5_current_pid = getpid();
273*55fea89dSDan Cross     /*
2747c478bd9Sstevel@tonic-gate      * The child handler below will help reduce the number of times getpid() is
2757c478bd9Sstevel@tonic-gate      * called by updating a global PID var. with the current PID whenever a fork
2767c478bd9Sstevel@tonic-gate      * occurrs.
2777c478bd9Sstevel@tonic-gate      */
2787c478bd9Sstevel@tonic-gate     (void) pthread_atfork(NULL, NULL, krb5_pthread_atfork_child_handler);
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate #endif /* !_KERNEL */
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate krb5_error_code
krb5_init_ef_handle(krb5_context ctx)2837c478bd9Sstevel@tonic-gate krb5_init_ef_handle(krb5_context ctx)
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate 	krb5_error_code retval = 0;
2867c478bd9Sstevel@tonic-gate #ifndef _KERNEL
2877c478bd9Sstevel@tonic-gate 	CK_RV rv = C_Initialize(NULL_PTR);
2887c478bd9Sstevel@tonic-gate 	if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
2897c478bd9Sstevel@tonic-gate 		KRB5_LOG(KRB5_ERR, "C_Initialize failed with 0x%x.", rv);
2907c478bd9Sstevel@tonic-gate 		return (PKCS_ERR);
291*55fea89dSDan Cross 
2927c478bd9Sstevel@tonic-gate 	}
293*55fea89dSDan Cross 	/*
2947c478bd9Sstevel@tonic-gate 	 * It is safe for this function to access ctx->hSession directly.  Do
2957c478bd9Sstevel@tonic-gate 	 * NOT use the krb_ctx_hSession() here.
2967c478bd9Sstevel@tonic-gate 	 */
2977c478bd9Sstevel@tonic-gate 	retval = krb5_open_pkcs11_session(&ctx->hSession);
2987c478bd9Sstevel@tonic-gate 	if (retval != 0)
2997c478bd9Sstevel@tonic-gate 		return (retval);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	ctx->cryptoki_initialized = TRUE;
3027c478bd9Sstevel@tonic-gate #else /* ! _KERNEL */
3037c478bd9Sstevel@tonic-gate 	ctx->kef_cipher_mt = CRYPTO_MECH_INVALID;
3047c478bd9Sstevel@tonic-gate 	ctx->kef_hash_mt = CRYPTO_MECH_INVALID;
3057c478bd9Sstevel@tonic-gate 	ctx->kef_cksum_mt = CRYPTO_MECH_INVALID;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	setup_kef_keytypes();
3087c478bd9Sstevel@tonic-gate 	setup_kef_cksumtypes();
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate #endif /* ! _KERNEL */
3117c478bd9Sstevel@tonic-gate 	return(retval);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate #ifndef _KERNEL
3157c478bd9Sstevel@tonic-gate krb5_error_code
krb5_free_ef_handle(krb5_context ctx)3167c478bd9Sstevel@tonic-gate krb5_free_ef_handle(krb5_context ctx)
3177c478bd9Sstevel@tonic-gate {
318*55fea89dSDan Cross 	/*
3197c478bd9Sstevel@tonic-gate 	 * fork safety: Don't free any PKCS state if we've forked since
3207c478bd9Sstevel@tonic-gate 	 * allocating the pkcs handles.
3217c478bd9Sstevel@tonic-gate 	 */
3227c478bd9Sstevel@tonic-gate 	if (ctx->cryptoki_initialized == TRUE &&
3237c478bd9Sstevel@tonic-gate 	    ctx->pid == __krb5_current_pid) {
324*55fea89dSDan Cross 		/*
3257c478bd9Sstevel@tonic-gate 		 * It is safe for this function to access ctx->hSession
3267c478bd9Sstevel@tonic-gate 		 * directly.  Do NOT use the krb_ctx_hSession() here.
3277c478bd9Sstevel@tonic-gate 		 */
3287c478bd9Sstevel@tonic-gate 		if (ctx->hSession) {
3297c478bd9Sstevel@tonic-gate 			C_CloseSession(ctx->hSession);
3307c478bd9Sstevel@tonic-gate 			ctx->hSession = 0;
3317c478bd9Sstevel@tonic-gate 		}
3327c478bd9Sstevel@tonic-gate 		if (ctx->arcfour_ctx.dKey) {
3337c478bd9Sstevel@tonic-gate 			C_DestroyObject(ctx->arcfour_ctx.dSession,
3347c478bd9Sstevel@tonic-gate 				ctx->arcfour_ctx.dKey);
3357c478bd9Sstevel@tonic-gate 			ctx->arcfour_ctx.dKey = 0;
3367c478bd9Sstevel@tonic-gate 		}
3377c478bd9Sstevel@tonic-gate 		if (ctx->arcfour_ctx.eKey) {
3387c478bd9Sstevel@tonic-gate 			C_DestroyObject(ctx->arcfour_ctx.eSession,
3397c478bd9Sstevel@tonic-gate 				ctx->arcfour_ctx.eKey);
3407c478bd9Sstevel@tonic-gate 			ctx->arcfour_ctx.eKey = 0;
3417c478bd9Sstevel@tonic-gate 		}
3427c478bd9Sstevel@tonic-gate 		if (ctx->arcfour_ctx.eSession) {
3437c478bd9Sstevel@tonic-gate 			C_CloseSession(ctx->arcfour_ctx.eSession);
3447c478bd9Sstevel@tonic-gate 			ctx->arcfour_ctx.eSession = 0;
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 		if (ctx->arcfour_ctx.dSession) {
3477c478bd9Sstevel@tonic-gate 			C_CloseSession(ctx->arcfour_ctx.dSession);
3487c478bd9Sstevel@tonic-gate 			ctx->arcfour_ctx.eSession = 0;
3497c478bd9Sstevel@tonic-gate 		}
3507c478bd9Sstevel@tonic-gate 		ctx->arcfour_ctx.initialized = 0;
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 		ctx->cryptoki_initialized = FALSE;
3537c478bd9Sstevel@tonic-gate 	}
3547c478bd9Sstevel@tonic-gate 	return(0);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate #endif /* !_KERNEL */
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate static krb5_error_code
init_common(krb5_context * context,krb5_boolean secure,krb5_boolean kdc)35954925bf6Swillf init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc)
3607c478bd9Sstevel@tonic-gate {
3617c478bd9Sstevel@tonic-gate 	krb5_context ctx = 0;
3627c478bd9Sstevel@tonic-gate 	krb5_error_code retval;
3637c478bd9Sstevel@tonic-gate #ifndef _KERNEL
3647c478bd9Sstevel@tonic-gate 	struct {
3657c478bd9Sstevel@tonic-gate 	    krb5_int32 now, now_usec;
3667c478bd9Sstevel@tonic-gate 	    long pid;
3677c478bd9Sstevel@tonic-gate 	} seed_data;
3687c478bd9Sstevel@tonic-gate 	krb5_data seed;
3697c478bd9Sstevel@tonic-gate 	int tmp;
370159d09a2SMark Phalan /* Solaris Kerberos */
371159d09a2SMark Phalan #if 0
372159d09a2SMark Phalan 	/* Verify some assumptions.  If the assumptions hold and the
373159d09a2SMark Phalan 	   compiler is optimizing, this should result in no code being
374159d09a2SMark Phalan 	   executed.  If we're guessing "unsigned long long" instead
375159d09a2SMark Phalan 	   of using uint64_t, the possibility does exist that we're
376159d09a2SMark Phalan 	   wrong.  */
377159d09a2SMark Phalan 	{
378159d09a2SMark Phalan 	    krb5_ui_8 i64;
379159d09a2SMark Phalan 	    assert(sizeof(i64) == 8);
380159d09a2SMark Phalan 	    i64 = 0, i64--, i64 >>= 62;
381159d09a2SMark Phalan 	    assert(i64 == 3);
382159d09a2SMark Phalan 	    i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1;
383159d09a2SMark Phalan 	    assert(i64 != 0);
384159d09a2SMark Phalan 	    i64 <<= 1;
385159d09a2SMark Phalan 	    assert(i64 == 0);
386159d09a2SMark Phalan 	}
387159d09a2SMark Phalan #endif
388159d09a2SMark Phalan 	retval = krb5int_initialize_library();
389159d09a2SMark Phalan 	if (retval)
390159d09a2SMark Phalan 	    return retval;
3917c478bd9Sstevel@tonic-gate #endif
3927c478bd9Sstevel@tonic-gate 
393505d05c7Sgtb #if (defined(_WIN32))
394*55fea89dSDan Cross 	/*
3957c478bd9Sstevel@tonic-gate 	 * Load the krbcc32.dll if necessary.  We do this here so that
3967c478bd9Sstevel@tonic-gate 	 * we know to use API: later on during initialization.
3977c478bd9Sstevel@tonic-gate 	 * The context being NULL is ok.
3987c478bd9Sstevel@tonic-gate 	 */
3997c478bd9Sstevel@tonic-gate 	krb5_win_ccdll_load(ctx);
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	/*
4027c478bd9Sstevel@tonic-gate 	 * krb5_vercheck() is defined in win_glue.c, and this is
4037c478bd9Sstevel@tonic-gate 	 * where we handle the timebomb and version server checks.
4047c478bd9Sstevel@tonic-gate 	 */
4057c478bd9Sstevel@tonic-gate 	retval = krb5_vercheck();
4067c478bd9Sstevel@tonic-gate 	if (retval)
4077c478bd9Sstevel@tonic-gate 		return retval;
4087c478bd9Sstevel@tonic-gate #endif
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	*context = 0;
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	ctx = MALLOC(sizeof(struct _krb5_context));
4137c478bd9Sstevel@tonic-gate 	if (!ctx)
4147c478bd9Sstevel@tonic-gate 		return ENOMEM;
4157c478bd9Sstevel@tonic-gate 	(void) memset(ctx, 0, sizeof(struct _krb5_context));
4167c478bd9Sstevel@tonic-gate 	ctx->magic = KV5M_CONTEXT;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	ctx->profile_secure = secure;
4197c478bd9Sstevel@tonic-gate 
42054925bf6Swillf 	if ((retval = krb5_os_init_context(ctx, kdc)))
4217c478bd9Sstevel@tonic-gate 		goto cleanup;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	/*
4247c478bd9Sstevel@tonic-gate 	 * Initialize the EF handle, its needed before doing
4257c478bd9Sstevel@tonic-gate 	 * the random seed.
4267c478bd9Sstevel@tonic-gate 	 */
4277c478bd9Sstevel@tonic-gate 	if ((retval = krb5_init_ef_handle(ctx)))
4287c478bd9Sstevel@tonic-gate 		goto cleanup;
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate #ifndef _KERNEL
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/* fork safety: set pid to current process ID for later checking */
4337c478bd9Sstevel@tonic-gate 	ctx->pid = __krb5_current_pid;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	/* Set the default encryption types, possible defined in krb5/conf */
4367c478bd9Sstevel@tonic-gate 	if ((retval = krb5_set_default_in_tkt_ktypes(ctx, NULL)))
4377c478bd9Sstevel@tonic-gate 		goto cleanup;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL)))
4407c478bd9Sstevel@tonic-gate 		goto cleanup;
4417c478bd9Sstevel@tonic-gate 
442d9976468Sps 	if (ctx->tgs_ktype_count != 0) {
443d9976468Sps 		ctx->conf_tgs_ktypes = MALLOC(ctx->tgs_ktype_count *
444d9976468Sps 					sizeof(krb5_enctype));
445d9976468Sps 		if (ctx->conf_tgs_ktypes == NULL)
446d9976468Sps 			goto cleanup;
4477c478bd9Sstevel@tonic-gate 
448d9976468Sps 		(void) memcpy(ctx->conf_tgs_ktypes, ctx->tgs_ktypes,
449d9976468Sps 				sizeof(krb5_enctype) * ctx->tgs_ktype_count);
450d9976468Sps 	}
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	ctx->conf_tgs_ktypes_count = ctx->tgs_ktype_count;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	/* initialize the prng (not well, but passable) */
4567c478bd9Sstevel@tonic-gate 	if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec)))
4577c478bd9Sstevel@tonic-gate 		goto cleanup;
4587c478bd9Sstevel@tonic-gate 	seed_data.pid = getpid ();
4597c478bd9Sstevel@tonic-gate 	seed.length = sizeof(seed_data);
4607c478bd9Sstevel@tonic-gate 	seed.data = (char *) &seed_data;
4617c478bd9Sstevel@tonic-gate 	if ((retval = krb5_c_random_seed(ctx, &seed)))
4627c478bd9Sstevel@tonic-gate 		/*
4637c478bd9Sstevel@tonic-gate 		 * Solaris Kerberos: we use /dev/urandom, which is
4647c478bd9Sstevel@tonic-gate 		 * automatically seeded, so its OK if this fails.
4657c478bd9Sstevel@tonic-gate 		 */
4667c478bd9Sstevel@tonic-gate 		retval = 0;
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	ctx->default_realm = 0;
4697c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults", "clockskew",
4707c478bd9Sstevel@tonic-gate 			    0, 5 * 60, &tmp);
4717c478bd9Sstevel@tonic-gate 	ctx->clockskew = tmp;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate #if 0
4747c478bd9Sstevel@tonic-gate 	/* Default ticket lifetime is currently not supported */
4757c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults", "tkt_lifetime",
4767c478bd9Sstevel@tonic-gate 			    0, 10 * 60 * 60, &tmp);
4777c478bd9Sstevel@tonic-gate 	ctx->tkt_lifetime = tmp;
4787c478bd9Sstevel@tonic-gate #endif
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	/* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2)  */
4817c478bd9Sstevel@tonic-gate 	/* DCE add kdc_req_checksum_type = 2 to krb5.conf */
4827c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults",
483*55fea89dSDan Cross 			    "kdc_req_checksum_type", 0, CKSUMTYPE_RSA_MD5,
4847c478bd9Sstevel@tonic-gate 			    &tmp);
4857c478bd9Sstevel@tonic-gate 	ctx->kdc_req_sumtype = tmp;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults",
4887c478bd9Sstevel@tonic-gate 			    "ap_req_checksum_type", 0, CKSUMTYPE_RSA_MD5,
4897c478bd9Sstevel@tonic-gate 			    &tmp);
4907c478bd9Sstevel@tonic-gate 	ctx->default_ap_req_sumtype = tmp;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults",
4937c478bd9Sstevel@tonic-gate 			    "safe_checksum_type", 0,
4947c478bd9Sstevel@tonic-gate 			    CKSUMTYPE_RSA_MD5_DES, &tmp);
4957c478bd9Sstevel@tonic-gate 	ctx->default_safe_sumtype = tmp;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults",
4987c478bd9Sstevel@tonic-gate 			    "kdc_default_options", 0,
4997c478bd9Sstevel@tonic-gate 			    KDC_OPT_RENEWABLE_OK, &tmp);
500505d05c7Sgtb 	ctx->kdc_default_options = tmp;
5017c478bd9Sstevel@tonic-gate #define DEFAULT_KDC_TIMESYNC 1
5027c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults",
5037c478bd9Sstevel@tonic-gate 			    "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC,
5047c478bd9Sstevel@tonic-gate 			    &tmp);
5057c478bd9Sstevel@tonic-gate 	ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	/*
5087c478bd9Sstevel@tonic-gate 	 * We use a default file credentials cache of 3.  See
5097c478bd9Sstevel@tonic-gate 	 * lib/krb5/krb/ccache/file/fcc.h for a description of the
5107c478bd9Sstevel@tonic-gate 	 * credentials cache types.
5117c478bd9Sstevel@tonic-gate 	 *
5127c478bd9Sstevel@tonic-gate 	 * Note: DCE 1.0.3a only supports a cache type of 1
5137c478bd9Sstevel@tonic-gate 	 * 	DCE 1.1 supports a cache type of 2.
5147c478bd9Sstevel@tonic-gate 	 */
5157c478bd9Sstevel@tonic-gate #define DEFAULT_CCACHE_TYPE 4
5167c478bd9Sstevel@tonic-gate 	profile_get_integer(ctx->profile, "libdefaults", "ccache_type",
5177c478bd9Sstevel@tonic-gate 			    0, DEFAULT_CCACHE_TYPE, &tmp);
5187c478bd9Sstevel@tonic-gate 	ctx->fcc_default_format = tmp + 0x0500;
5197c478bd9Sstevel@tonic-gate 	ctx->scc_default_format = tmp + 0x0500;
5207c478bd9Sstevel@tonic-gate 	ctx->prompt_types = 0;
5217c478bd9Sstevel@tonic-gate 	ctx->use_conf_ktypes = 0;
5227c478bd9Sstevel@tonic-gate 
52356a424ccSmp 	ctx->udp_pref_limit = -1;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate #endif  /* !_KERNEL */
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	*context = ctx;
5287c478bd9Sstevel@tonic-gate 	return 0;
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate cleanup:
5317c478bd9Sstevel@tonic-gate 	krb5_free_context(ctx);
5327c478bd9Sstevel@tonic-gate 	return retval;
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate 
535505d05c7Sgtb void KRB5_CALLCONV
krb5_free_context(krb5_context ctx)536505d05c7Sgtb krb5_free_context(krb5_context ctx)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	KRB5_LOG0(KRB5_INFO,"krb5_free_context() start");
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate #ifndef _KERNEL
5417c478bd9Sstevel@tonic-gate 	krb5_free_ef_handle(ctx);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate      if (ctx->conf_tgs_ktypes) {
5447c478bd9Sstevel@tonic-gate 	 FREE(ctx->conf_tgs_ktypes, sizeof(krb5_enctype) *(ctx->conf_tgs_ktypes_count));
5457c478bd9Sstevel@tonic-gate 	 ctx->conf_tgs_ktypes = 0;
5467c478bd9Sstevel@tonic-gate 	 ctx->conf_tgs_ktypes_count = 0;
5477c478bd9Sstevel@tonic-gate      }
5487c478bd9Sstevel@tonic-gate 
549159d09a2SMark Phalan      krb5_clear_error_message(ctx);
550159d09a2SMark Phalan 
5517c478bd9Sstevel@tonic-gate #endif
5527c478bd9Sstevel@tonic-gate      krb5_os_free_context(ctx);
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate      if (ctx->in_tkt_ktypes) {
5557c478bd9Sstevel@tonic-gate           FREE(ctx->in_tkt_ktypes, sizeof(krb5_enctype) *(ctx->in_tkt_ktype_count+1) );
5567c478bd9Sstevel@tonic-gate 	  ctx->in_tkt_ktypes = 0;
5577c478bd9Sstevel@tonic-gate      }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate      if (ctx->tgs_ktypes) {
5607c478bd9Sstevel@tonic-gate           FREE(ctx->tgs_ktypes, sizeof(krb5_enctype) *(ctx->tgs_ktype_count+1));
5617c478bd9Sstevel@tonic-gate 	  ctx->tgs_ktypes = 0;
5627c478bd9Sstevel@tonic-gate      }
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate      if (ctx->default_realm) {
5657c478bd9Sstevel@tonic-gate 	  FREE(ctx->default_realm, strlen(ctx->default_realm) + 1);
5667c478bd9Sstevel@tonic-gate 	  ctx->default_realm = 0;
5677c478bd9Sstevel@tonic-gate      }
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate      if (ctx->ser_ctx_count && ctx->ser_ctx) {
5707c478bd9Sstevel@tonic-gate 	  FREE(ctx->ser_ctx,sizeof(krb5_ser_entry) * (ctx->ser_ctx_count) );
5717c478bd9Sstevel@tonic-gate 	  ctx->ser_ctx = 0;
5727c478bd9Sstevel@tonic-gate 	  ctx->ser_ctx_count = 0;
5737c478bd9Sstevel@tonic-gate      }
5747c478bd9Sstevel@tonic-gate 
575159d09a2SMark Phalan 
5767c478bd9Sstevel@tonic-gate      ctx->magic = 0;
5777c478bd9Sstevel@tonic-gate      FREE(ctx, sizeof(struct _krb5_context));
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate #ifndef _KERNEL
5817c478bd9Sstevel@tonic-gate /*
5827c478bd9Sstevel@tonic-gate  * Set the desired default ktypes, making sure they are valid.
5837c478bd9Sstevel@tonic-gate  */
5847c478bd9Sstevel@tonic-gate krb5_error_code
krb5_set_default_in_tkt_ktypes(krb5_context context,const krb5_enctype * ktypes)585505d05c7Sgtb krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes)
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate     krb5_enctype * new_ktypes;
5887c478bd9Sstevel@tonic-gate     int i;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate     if (ktypes) {
5917c478bd9Sstevel@tonic-gate 	for (i = 0; ktypes[i]; i++) {
592*55fea89dSDan Cross 	    if (!krb5_c_valid_enctype(ktypes[i]))
5937c478bd9Sstevel@tonic-gate 		return KRB5_PROG_ETYPE_NOSUPP;
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/* Now copy the default ktypes into the context pointer */
5977c478bd9Sstevel@tonic-gate 	if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
5987c478bd9Sstevel@tonic-gate 	    (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
5997c478bd9Sstevel@tonic-gate 	else
6007c478bd9Sstevel@tonic-gate 	    return ENOMEM;
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate     } else {
6037c478bd9Sstevel@tonic-gate 	i = 0;
6047c478bd9Sstevel@tonic-gate 	new_ktypes = 0;
6057c478bd9Sstevel@tonic-gate     }
6067c478bd9Sstevel@tonic-gate 
607*55fea89dSDan Cross     if (context->in_tkt_ktypes)
6087c478bd9Sstevel@tonic-gate         free(context->in_tkt_ktypes);
6097c478bd9Sstevel@tonic-gate     context->in_tkt_ktypes = new_ktypes;
6107c478bd9Sstevel@tonic-gate     context->in_tkt_ktype_count = i;
6117c478bd9Sstevel@tonic-gate     return 0;
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate static krb5_error_code
get_profile_etype_list(krb5_context context,krb5_enctype ** ktypes,char * profstr,unsigned int ctx_count,krb5_enctype * ctx_list)615505d05c7Sgtb get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profstr,
616159d09a2SMark Phalan 		       unsigned int ctx_count, krb5_enctype *ctx_list)
6177c478bd9Sstevel@tonic-gate {
6187c478bd9Sstevel@tonic-gate     krb5_enctype *old_ktypes = NULL;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate     if (ctx_count) {
6217c478bd9Sstevel@tonic-gate 	/* application-set defaults */
622*55fea89dSDan Cross 	if ((old_ktypes =
6237c478bd9Sstevel@tonic-gate 	     (krb5_enctype *)malloc(sizeof(krb5_enctype) *
6247c478bd9Sstevel@tonic-gate 				    (ctx_count + 1)))) {
6257c478bd9Sstevel@tonic-gate 	    (void) memcpy(old_ktypes, ctx_list,
6267c478bd9Sstevel@tonic-gate 		sizeof(krb5_enctype) * ctx_count);
6277c478bd9Sstevel@tonic-gate 	    old_ktypes[ctx_count] = 0;
6287c478bd9Sstevel@tonic-gate 	} else {
6297c478bd9Sstevel@tonic-gate 	    return ENOMEM;
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate     } else {
6327c478bd9Sstevel@tonic-gate         /*
6337c478bd9Sstevel@tonic-gate 	   XXX - For now, we only support libdefaults
6347c478bd9Sstevel@tonic-gate 	   Perhaps this should be extended to allow for per-host / per-realm
6357c478bd9Sstevel@tonic-gate 	   session key types.
6367c478bd9Sstevel@tonic-gate 	 */
6377c478bd9Sstevel@tonic-gate 
638505d05c7Sgtb 	char *retval = NULL;
6397c478bd9Sstevel@tonic-gate 	char *sp, *ep;
6407c478bd9Sstevel@tonic-gate 	int j, checked_enctypes, count;
6417c478bd9Sstevel@tonic-gate 	krb5_error_code code;
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	code = profile_get_string(context->profile, "libdefaults", profstr,
644505d05c7Sgtb 				  NULL, DEFAULT_ETYPE_LIST, &retval);
6457c478bd9Sstevel@tonic-gate 	if (code)
6467c478bd9Sstevel@tonic-gate 	    return code;
6477c478bd9Sstevel@tonic-gate 
648505d05c7Sgtb 	if (!retval)  /* SUNW14resync - just in case */
649505d05c7Sgtb             return PROF_EINVAL;  /* XXX */
650505d05c7Sgtb 
6517c478bd9Sstevel@tonic-gate 	count = 0;
6527c478bd9Sstevel@tonic-gate 	sp = retval;
653505d05c7Sgtb 	while (*sp) {
654505d05c7Sgtb 	    for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++)
6557c478bd9Sstevel@tonic-gate 		;
6567c478bd9Sstevel@tonic-gate 	    if (*ep) {
6577c478bd9Sstevel@tonic-gate 		*ep++ = '\0';
658505d05c7Sgtb 		while (isspace((int) (*ep)) || *ep == ',')
659505d05c7Sgtb 		    *ep++ = '\0';
660505d05c7Sgtb 	    }
6617c478bd9Sstevel@tonic-gate 	    count++;
6627c478bd9Sstevel@tonic-gate 	    sp = ep;
6637c478bd9Sstevel@tonic-gate 	}
664*55fea89dSDan Cross 
6657c478bd9Sstevel@tonic-gate 	if ((old_ktypes =
6667c478bd9Sstevel@tonic-gate 	     (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) ==
6677c478bd9Sstevel@tonic-gate 	    (krb5_enctype *) NULL)
6687c478bd9Sstevel@tonic-gate 	    return ENOMEM;
669*55fea89dSDan Cross 
6707c478bd9Sstevel@tonic-gate 	sp = retval;
6717c478bd9Sstevel@tonic-gate 	j = checked_enctypes = 0;
6727c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
6737c478bd9Sstevel@tonic-gate 	while (TRUE) {
6747c478bd9Sstevel@tonic-gate 	    checked_enctypes++;
6757c478bd9Sstevel@tonic-gate 	    if (krb5_string_to_enctype(sp, &old_ktypes[j]))
6767c478bd9Sstevel@tonic-gate 		old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN;
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	    /*
6797c478bd9Sstevel@tonic-gate 	     * If 'null' has been specified as a tkt_enctype in
6807c478bd9Sstevel@tonic-gate 	     * krb5.conf, we need to assign an ENCTYPE_UNKNOWN
6817c478bd9Sstevel@tonic-gate 	     * value to the corresponding old_ktypes[j] entry.
6827c478bd9Sstevel@tonic-gate 	     */
6837c478bd9Sstevel@tonic-gate 	    if (old_ktypes[j] == (unsigned int)ENCTYPE_NULL)
6847c478bd9Sstevel@tonic-gate 		old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN;
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	    /* Only include known/valid enctypes in the final list */
6877c478bd9Sstevel@tonic-gate 	    if (old_ktypes[j] != ENCTYPE_UNKNOWN) {
6887c478bd9Sstevel@tonic-gate 		j++;
6897c478bd9Sstevel@tonic-gate 	    }
6907c478bd9Sstevel@tonic-gate 	    /* If we checked all the enctypes, we are done */
6917c478bd9Sstevel@tonic-gate 	    if (checked_enctypes == count) {
6927c478bd9Sstevel@tonic-gate 		break;
6937c478bd9Sstevel@tonic-gate 	    }
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	    /* skip to next token */
6967c478bd9Sstevel@tonic-gate 	    while (*sp) sp++;
697159d09a2SMark Phalan 	    while (! *sp) sp++;
6987c478bd9Sstevel@tonic-gate 	}
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	old_ktypes[j] = (krb5_enctype) 0;
7017c478bd9Sstevel@tonic-gate 	profile_release_string(retval);
7027c478bd9Sstevel@tonic-gate     }
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate     if (old_ktypes[0] == 0) {
7057c478bd9Sstevel@tonic-gate 	free (old_ktypes);
7067c478bd9Sstevel@tonic-gate 	*ktypes = 0;
7077c478bd9Sstevel@tonic-gate 	return KRB5_CONFIG_ETYPE_NOSUPP;
7087c478bd9Sstevel@tonic-gate     }
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate     *ktypes = old_ktypes;
7117c478bd9Sstevel@tonic-gate     return 0;
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate krb5_error_code
krb5_get_default_in_tkt_ktypes(krb5_context context,krb5_enctype ** ktypes)715505d05c7Sgtb krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes)
7167c478bd9Sstevel@tonic-gate {
7177c478bd9Sstevel@tonic-gate     return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes",
7187c478bd9Sstevel@tonic-gate 				  context->in_tkt_ktype_count,
7197c478bd9Sstevel@tonic-gate 				  context->in_tkt_ktypes));
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate 
722159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV
krb5_set_default_tgs_enctypes(krb5_context context,const krb5_enctype * ktypes)723505d05c7Sgtb krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes)
7247c478bd9Sstevel@tonic-gate {
7257c478bd9Sstevel@tonic-gate     krb5_enctype * new_ktypes;
7267c478bd9Sstevel@tonic-gate     int i;
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate     if (ktypes) {
7297c478bd9Sstevel@tonic-gate 	for (i = 0; ktypes[i]; i++) {
730*55fea89dSDan Cross 	    if (!krb5_c_valid_enctype(ktypes[i]))
7317c478bd9Sstevel@tonic-gate 		return KRB5_PROG_ETYPE_NOSUPP;
7327c478bd9Sstevel@tonic-gate 	}
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	/* Now copy the default ktypes into the context pointer */
7357c478bd9Sstevel@tonic-gate 	if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i)))
7367c478bd9Sstevel@tonic-gate 	    (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i);
7377c478bd9Sstevel@tonic-gate 	else
7387c478bd9Sstevel@tonic-gate 	    return ENOMEM;
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate     } else {
7417c478bd9Sstevel@tonic-gate 	i = 0;
7427c478bd9Sstevel@tonic-gate 	new_ktypes = (krb5_enctype *)NULL;
7437c478bd9Sstevel@tonic-gate     }
7447c478bd9Sstevel@tonic-gate 
745*55fea89dSDan Cross     if (context->tgs_ktypes)
7467c478bd9Sstevel@tonic-gate         krb5_free_ktypes(context, context->tgs_ktypes);
7477c478bd9Sstevel@tonic-gate     context->tgs_ktypes = new_ktypes;
7487c478bd9Sstevel@tonic-gate     context->tgs_ktype_count = i;
7497c478bd9Sstevel@tonic-gate     return 0;
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate 
krb5_set_default_tgs_ktypes(krb5_context context,const krb5_enctype * etypes)7527c478bd9Sstevel@tonic-gate krb5_error_code krb5_set_default_tgs_ktypes
7537c478bd9Sstevel@tonic-gate (krb5_context context, const krb5_enctype *etypes)
7547c478bd9Sstevel@tonic-gate {
7557c478bd9Sstevel@tonic-gate   return (krb5_set_default_tgs_enctypes (context, etypes));
7567c478bd9Sstevel@tonic-gate }
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7607c478bd9Sstevel@tonic-gate void
7617c478bd9Sstevel@tonic-gate KRB5_CALLCONV
krb5_free_ktypes(krb5_context context,krb5_enctype * val)762505d05c7Sgtb krb5_free_ktypes (krb5_context context, krb5_enctype *val)
7637c478bd9Sstevel@tonic-gate {
7647c478bd9Sstevel@tonic-gate     free (val);
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7687c478bd9Sstevel@tonic-gate krb5_error_code
7697c478bd9Sstevel@tonic-gate KRB5_CALLCONV
krb5_get_tgs_ktypes(krb5_context context,krb5_const_principal princ,krb5_enctype ** ktypes)770505d05c7Sgtb krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate     if (context->use_conf_ktypes)
7737c478bd9Sstevel@tonic-gate 	/* This one is set *only* by reading the config file; it's not
7747c478bd9Sstevel@tonic-gate 	   set by the application.  */
7757c478bd9Sstevel@tonic-gate 	return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
7767c478bd9Sstevel@tonic-gate                                       context->conf_tgs_ktypes_count,
7777c478bd9Sstevel@tonic-gate                                       context->conf_tgs_ktypes));
7787c478bd9Sstevel@tonic-gate     else
7797c478bd9Sstevel@tonic-gate 	return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes",
7807c478bd9Sstevel@tonic-gate 				  context->tgs_ktype_count,
7817c478bd9Sstevel@tonic-gate 				  context->tgs_ktypes));
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate krb5_error_code
krb5_get_permitted_enctypes(krb5_context context,krb5_enctype ** ktypes)785505d05c7Sgtb krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
7867c478bd9Sstevel@tonic-gate {
7877c478bd9Sstevel@tonic-gate     return(get_profile_etype_list(context, ktypes, "permitted_enctypes",
7887c478bd9Sstevel@tonic-gate 				  context->tgs_ktype_count,
7897c478bd9Sstevel@tonic-gate 				  context->tgs_ktypes));
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate krb5_boolean
krb5_is_permitted_enctype(krb5_context context,krb5_enctype etype)793505d05c7Sgtb krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate     krb5_enctype *list, *ptr;
7967c478bd9Sstevel@tonic-gate     krb5_boolean ret;
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate     if (krb5_get_permitted_enctypes(context, &list))
7997c478bd9Sstevel@tonic-gate 	return(0);
8007c478bd9Sstevel@tonic-gate 
801*55fea89dSDan Cross 
8027c478bd9Sstevel@tonic-gate     ret = 0;
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate     for (ptr = list; *ptr; ptr++)
8057c478bd9Sstevel@tonic-gate 	if (*ptr == etype)
8067c478bd9Sstevel@tonic-gate 	    ret = 1;
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate     krb5_free_ktypes (context, list);
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate     return(ret);
8117c478bd9Sstevel@tonic-gate }
812159d09a2SMark Phalan 
813159d09a2SMark Phalan static krb5_error_code
copy_ktypes(krb5_context ctx,unsigned int nktypes,krb5_enctype * oldktypes,krb5_enctype ** newktypes)814159d09a2SMark Phalan copy_ktypes(krb5_context ctx,
815159d09a2SMark Phalan 	    unsigned int nktypes,
816159d09a2SMark Phalan 	    krb5_enctype *oldktypes,
817159d09a2SMark Phalan 	    krb5_enctype **newktypes)
818159d09a2SMark Phalan {
819159d09a2SMark Phalan     unsigned int i;
820159d09a2SMark Phalan 
821159d09a2SMark Phalan     *newktypes = NULL;
822159d09a2SMark Phalan     if (!nktypes)
823159d09a2SMark Phalan 	return 0;
824159d09a2SMark Phalan 
825159d09a2SMark Phalan     *newktypes = MALLOC(nktypes * sizeof(krb5_enctype));
826159d09a2SMark Phalan     if (*newktypes == NULL)
827159d09a2SMark Phalan 	return ENOMEM;
828159d09a2SMark Phalan     for (i = 0; i < nktypes; i++)
829159d09a2SMark Phalan 	(*newktypes)[i] = oldktypes[i];
830159d09a2SMark Phalan     return 0;
831159d09a2SMark Phalan }
832159d09a2SMark Phalan 
833159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV
krb5_copy_context(krb5_context ctx,krb5_context * nctx_out)834159d09a2SMark Phalan krb5_copy_context(krb5_context ctx, krb5_context *nctx_out)
835159d09a2SMark Phalan {
836159d09a2SMark Phalan     krb5_error_code ret;
837159d09a2SMark Phalan     krb5_context nctx;
838159d09a2SMark Phalan 
839159d09a2SMark Phalan     *nctx_out = NULL;
840159d09a2SMark Phalan     if (ctx == NULL)
841159d09a2SMark Phalan 	return EINVAL;		/* XXX */
842159d09a2SMark Phalan 
843159d09a2SMark Phalan     nctx = MALLOC(sizeof(*nctx));
844159d09a2SMark Phalan     if (nctx == NULL)
845159d09a2SMark Phalan 	return ENOMEM;
846159d09a2SMark Phalan 
847159d09a2SMark Phalan     *nctx = *ctx;
848159d09a2SMark Phalan 
849159d09a2SMark Phalan     nctx->in_tkt_ktypes = NULL;
850159d09a2SMark Phalan     nctx->in_tkt_ktype_count = 0;
851159d09a2SMark Phalan     nctx->tgs_ktypes = NULL;
852159d09a2SMark Phalan     nctx->tgs_ktype_count = 0;
853159d09a2SMark Phalan     nctx->default_realm = NULL;
854159d09a2SMark Phalan     nctx->profile = NULL;
855159d09a2SMark Phalan     nctx->db_context = NULL;
856159d09a2SMark Phalan     nctx->ser_ctx_count = 0;
857159d09a2SMark Phalan     nctx->ser_ctx = NULL;
858159d09a2SMark Phalan     nctx->prompt_types = NULL;
859159d09a2SMark Phalan     nctx->os_context->default_ccname = NULL;
860159d09a2SMark Phalan 
861159d09a2SMark Phalan     memset(&nctx->preauth_plugins, 0, sizeof(nctx->preauth_plugins));
862159d09a2SMark Phalan     nctx->preauth_context = NULL;
863159d09a2SMark Phalan 
864159d09a2SMark Phalan     memset(&nctx->libkrb5_plugins, 0, sizeof(nctx->libkrb5_plugins));
865159d09a2SMark Phalan     nctx->vtbl = NULL;
866159d09a2SMark Phalan     nctx->locate_fptrs = NULL;
867159d09a2SMark Phalan 
868159d09a2SMark Phalan     memset(&nctx->err, 0, sizeof(nctx->err));
869159d09a2SMark Phalan 
870159d09a2SMark Phalan     ret = copy_ktypes(nctx, ctx->in_tkt_ktype_count,
871159d09a2SMark Phalan 		      ctx->in_tkt_ktypes, &nctx->in_tkt_ktypes);
872159d09a2SMark Phalan     if (ret)
873159d09a2SMark Phalan 	goto errout;
874159d09a2SMark Phalan     nctx->in_tkt_ktype_count = ctx->in_tkt_ktype_count;
875159d09a2SMark Phalan 
876159d09a2SMark Phalan     ret = copy_ktypes(nctx, ctx->tgs_ktype_count,
877159d09a2SMark Phalan 		      ctx->tgs_ktypes, &nctx->in_tkt_ktypes);
878159d09a2SMark Phalan     if (ret)
879159d09a2SMark Phalan 	goto errout;
880159d09a2SMark Phalan     nctx->tgs_ktype_count = ctx->tgs_ktype_count;
881159d09a2SMark Phalan 
882159d09a2SMark Phalan     if (ctx->os_context->default_ccname != NULL) {
883159d09a2SMark Phalan 	nctx->os_context->default_ccname =
884159d09a2SMark Phalan 	    strdup(ctx->os_context->default_ccname);
885159d09a2SMark Phalan 	if (nctx->os_context->default_ccname == NULL) {
886159d09a2SMark Phalan 	    ret = ENOMEM;
887159d09a2SMark Phalan 	    goto errout;
888159d09a2SMark Phalan 	}
889159d09a2SMark Phalan     }
890159d09a2SMark Phalan     ret = krb5_get_profile(ctx, &nctx->profile);
891159d09a2SMark Phalan     if (ret)
892159d09a2SMark Phalan 	goto errout;
893159d09a2SMark Phalan 
894159d09a2SMark Phalan errout:
895159d09a2SMark Phalan     if (ret) {
896159d09a2SMark Phalan 	krb5_free_context(nctx);
897159d09a2SMark Phalan     } else {
898159d09a2SMark Phalan 	*nctx_out = nctx;
899159d09a2SMark Phalan     }
900159d09a2SMark Phalan     return ret;
901159d09a2SMark Phalan }
9027c478bd9Sstevel@tonic-gate #endif /* !KERNEL */
903159d09a2SMark Phalan 
904159d09a2SMark Phalan 
905