/*
+ * Copyright (c) 2004, 2005, 2006, 2007 Secure Endpoints Inc.
* Copyright (c) 2003 SkyRope, LLC
* All rights reserved.
*
*/
-#define USE_MS2MIT
-#define USE_KRB4
+#undef USE_KRB4
+#ifndef _WIN64
+#define USE_KRB524 1
+#endif
+#define USE_MS2MIT 1
+#define USE_LEASH 1
+
#include "afskfw-int.h"
#include "afskfw.h"
+#include <userenv.h>
+
+#include <Sddl.h>
+#include <Aclapi.h>
#include <osilog.h>
-#include <rxkad_prototypes.h> /* for life_to_time */
+#include <afs/ptserver.h>
+#include <afs/ptuser.h>
+#include <rx/rxkad.h>
+
+#include <WINNT\afsreg.h>
/*
* TIMING _____________________________________________________________________
DECL_FUNC_PTR(cc_get_NC_info);
DECL_FUNC_PTR(cc_free_NC_info);
+#ifdef USE_LEASH
// leash functions
DECL_FUNC_PTR(Leash_get_default_lifetime);
DECL_FUNC_PTR(Leash_get_default_forwardable);
DECL_FUNC_PTR(Leash_get_default_renew_min);
DECL_FUNC_PTR(Leash_get_default_renew_max);
DECL_FUNC_PTR(Leash_get_default_renewable);
+DECL_FUNC_PTR(Leash_get_default_mslsa_import);
+#endif
// krb5 functions
DECL_FUNC_PTR(krb5_change_password);
DECL_FUNC_PTR(krb5_get_default_config_files);
DECL_FUNC_PTR(krb5_free_config_files);
DECL_FUNC_PTR(krb5_get_default_realm);
+DECL_FUNC_PTR(krb5_free_default_realm);
DECL_FUNC_PTR(krb5_free_ticket);
DECL_FUNC_PTR(krb5_decode_ticket);
DECL_FUNC_PTR(krb5_get_host_realm);
DECL_FUNC_PTR(krb5_free_addresses);
DECL_FUNC_PTR(krb5_c_random_make_octets);
+#ifdef USE_KRB524
// Krb524 functions
DECL_FUNC_PTR(krb524_init_ets);
DECL_FUNC_PTR(krb524_convert_creds_kdc);
+#endif
+#ifdef USE_KRB4
// krb4 functions
DECL_FUNC_PTR(krb_get_cred);
DECL_FUNC_PTR(tkt_string);
DECL_FUNC_PTR(krb_get_tf_realm);
DECL_FUNC_PTR(krb_mk_req);
+#endif
// ComErr functions
DECL_FUNC_PTR(com_err);
END_FUNC_INFO
};
+#ifdef USE_LEASH
FUNC_INFO leash_fi[] = {
MAKE_FUNC_INFO(Leash_get_default_lifetime),
MAKE_FUNC_INFO(Leash_get_default_renew_till),
END_FUNC_INFO
};
+FUNC_INFO leash_opt_fi[] = {
+ MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
+ END_FUNC_INFO
+};
+#endif
+
FUNC_INFO k5_fi[] = {
MAKE_FUNC_INFO(krb5_change_password),
MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
MAKE_FUNC_INFO(krb5_get_default_config_files),
MAKE_FUNC_INFO(krb5_free_config_files),
MAKE_FUNC_INFO(krb5_get_default_realm),
+ MAKE_FUNC_INFO(krb5_free_default_realm),
MAKE_FUNC_INFO(krb5_free_ticket),
MAKE_FUNC_INFO(krb5_decode_ticket),
MAKE_FUNC_INFO(krb5_get_host_realm),
END_FUNC_INFO
};
+#ifdef USE_KRB4
FUNC_INFO k4_fi[] = {
MAKE_FUNC_INFO(krb_get_cred),
MAKE_FUNC_INFO(krb_get_tf_realm),
MAKE_FUNC_INFO(tkt_string),
END_FUNC_INFO
};
+#endif
+#ifdef USE_KRB524
FUNC_INFO k524_fi[] = {
MAKE_FUNC_INFO(krb524_init_ets),
MAKE_FUNC_INFO(krb524_convert_creds_kdc),
END_FUNC_INFO
};
+#endif
FUNC_INFO profile_fi[] = {
MAKE_FUNC_INFO(profile_init),
#endif /* USE_MS2MIT */
/* Static Prototypes */
-char *afs_realm_of_cell(struct afsconf_cell *);
+char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
static int mid_cnt = 0;
static struct textField * mid_tb = NULL;
static HINSTANCE hKrb5 = 0;
+#ifdef USE_KRB4
static HINSTANCE hKrb4 = 0;
+#endif /* USE_KRB4 */
+#ifdef USE_KRB524
static HINSTANCE hKrb524 = 0;
+#endif
#ifdef USE_MS2MIT
static HINSTANCE hSecur32 = 0;
#endif /* USE_MS2MIT */
static HINSTANCE hComErr = 0;
static HINSTANCE hService = 0;
static HINSTANCE hProfile = 0;
+#ifdef USE_LEASH
static HINSTANCE hLeash = 0;
+static HINSTANCE hLeashOpt = 0;
+#endif
static HINSTANCE hCCAPI = 0;
static struct principal_ccache_data * princ_cc_data = NULL;
static struct cell_principal_map * cell_princ_map = NULL;
if ( !inited ) {
inited = 1;
LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
- LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
+ LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+#ifdef USE_KRB4
+ LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
+#endif /* USE_KRB4 */
LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
#ifdef USE_MS2MIT
LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
#endif /* USE_MS2MIT */
+#ifdef USE_KRB524
LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
- LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+#endif
+#ifdef USE_LEASH
LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
+ LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
+#endif
LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
if ( KFW_is_available() ) {
void
KFW_cleanup(void)
{
- if (hKrb5)
- FreeLibrary(hKrb5);
- if (hKrb4)
- FreeLibrary(hKrb4);
- if (hProfile)
- FreeLibrary(hProfile);
- if (hComErr)
- FreeLibrary(hComErr);
- if (hService)
- FreeLibrary(hService);
-#ifdef USE_MS2MIT
- if (hSecur32)
- FreeLibrary(hSecur32);
-#endif /* USE_MS2MIT */
- if (hKrb524)
- FreeLibrary(hKrb524);
+#ifdef USE_LEASH
+ if (hLeashOpt)
+ FreeLibrary(hLeashOpt);
if (hLeash)
FreeLibrary(hLeash);
+#endif
+#ifdef USE_KRB524
+ if (hKrb524)
+ FreeLibrary(hKrb524);
+#endif
if (hCCAPI)
FreeLibrary(hCCAPI);
+#ifdef USE_MS2MIT
+ if (hSecur32)
+ FreeLibrary(hSecur32);
+#endif /* USE_MS2MIT */
+ if (hService)
+ FreeLibrary(hService);
+ if (hComErr)
+ FreeLibrary(hComErr);
+ if (hProfile)
+ FreeLibrary(hProfile);
+#ifdef USE_KRB4
+ if (hKrb4)
+ FreeLibrary(hKrb4);
+#endif /* USE_KRB4 */
+ if (hKrb5)
+ FreeLibrary(hKrb5);
+}
+
+
+int
+KFW_accept_dotted_usernames(void)
+{
+ HKEY parmKey;
+ DWORD code, len;
+ DWORD value = 1;
+
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(value);
+ code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
+ (BYTE *) &value, &len);
+ RegCloseKey(parmKey);
+ }
+ if (code != ERROR_SUCCESS) {
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(value);
+ code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
+ (BYTE *) &value, &len);
+ RegCloseKey (parmKey);
+ }
+ }
+ return value;
}
-static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
+
+int
+KFW_use_krb524(void)
+{
+ HKEY parmKey;
+ DWORD code, len;
+ DWORD use524 = 0;
+
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(use524);
+ code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+ (BYTE *) &use524, &len);
+ RegCloseKey(parmKey);
+ }
+ if (code != ERROR_SUCCESS) {
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(use524);
+ code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+ (BYTE *) &use524, &len);
+ RegCloseKey (parmKey);
+ }
+ }
+ return use524;
+}
int
KFW_is_available(void)
{
HKEY parmKey;
- DWORD code, len;
+ DWORD code, len;
DWORD enableKFW = 1;
- code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
0, KEY_QUERY_VALUE, &parmKey);
- if (code != ERROR_SUCCESS)
- code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
- if (code == ERROR_SUCCESS) {
+ if (code == ERROR_SUCCESS) {
len = sizeof(enableKFW);
code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
(BYTE *) &enableKFW, &len);
- if (code != ERROR_SUCCESS) {
- enableKFW = 1;
- }
RegCloseKey (parmKey);
- }
+ }
+
+ if (code != ERROR_SUCCESS) {
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+ 0, KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(enableKFW);
+ code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
+ (BYTE *) &enableKFW, &len);
+ RegCloseKey (parmKey);
+ }
+ }
if ( !enableKFW )
return FALSE;
#ifdef USE_MS2MIT
hSecur32 &&
#endif /* USE_MS2MIT */
+#ifdef USE_KRB524
hKrb524 &&
- hProfile && hLeash && hCCAPI )
+#endif
+#ifdef USE_LEASH
+ hLeash &&
+#endif
+ hProfile && hCCAPI )
return TRUE;
return FALSE;
}
krb5_principal principal = 0;
char * pname = NULL;
const char * ccname = NULL;
+ const char * cctype = NULL;
krb5_error_code code = 0;
krb5_error_code cc_code = 0;
krb5_cc_cursor cur;
ccname = pkrb5_cc_get_name(ctx, cc);
if (!ccname) goto cleanup;
+ cctype = pkrb5_cc_get_type(ctx, cc);
+ if (!cctype) goto cleanup;
+
// Search the existing list to see if we have a match
if ( next ) {
for ( ; next ; next = next->next ) {
next->next = princ_cc_data;
princ_cc_data = next;
next->principal = _strdup(pname);
- next->ccache_name = _strdup(ccname);
+ next->ccache_name = malloc(strlen(ccname) + strlen(cctype) + 2);
+ if (next->ccache_name)
+ sprintf(next->ccache_name, "%s:%s", cctype, ccname);
next->from_lsa = lsa;
next->expired = 1;
next->expiration_time = 0;
int
KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
{
- krb5_context ctx;
- char * pname = 0;
- char * ccname = 0;
+ krb5_context ctx = NULL;
+ char * pname = NULL;
+ char * ccname = NULL;
krb5_error_code code;
if (!pkrb5_init_context)
void
KFW_import_windows_lsa(void)
{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal princ = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal princ = NULL;
char * pname = NULL;
- krb5_data * realm;
+ krb5_data * princ_realm;
krb5_error_code code;
- char cell[128]="";
+ char cell[128]="", realm[128]="", *def_realm = 0;
int i;
+ DWORD dwMsLsaImport;
if (!pkrb5_init_context)
return;
-#ifdef COMMENT
- if ( !MSLSA_IsKerberosLogon() )
- return;
-#endif
-
code = pkrb5_init_context(&ctx);
if (code) goto cleanup;
code = pkrb5_cc_get_principal(ctx, cc, &princ);
if ( code ) goto cleanup;
+ dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
+ switch ( dwMsLsaImport ) {
+ case 0: /* do not import */
+ goto cleanup;
+ case 1: /* always import */
+ break;
+ case 2: { /* matching realm */
+ char ms_realm[128] = "", *r;
+ int i;
+
+ for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
+ *r = krb5_princ_realm(ctx, princ)->data[i];
+ }
+ *r = '\0';
+
+ if (code = pkrb5_get_default_realm(ctx, &def_realm))
+ goto cleanup;
+
+ if (strcmp(def_realm, ms_realm))
+ goto cleanup;
+ break;
+ }
+ default:
+ break;
+ }
+
code = pkrb5_unparse_name(ctx,princ,&pname);
if ( code ) goto cleanup;
- realm = krb5_princ_realm(ctx, princ);
- for ( i=0; i<realm->length; i++ ) {
- cell[i] = tolower(realm->data[i]);
+ princ_realm = krb5_princ_realm(ctx, princ);
+ for ( i=0; i<princ_realm->length; i++ ) {
+ realm[i] = princ_realm->data[i];
+ cell[i] = tolower(princ_realm->data[i]);
}
- cell[i] = '\0';
+ cell[i] = '\0';
+ realm[i] = '\0';
- code = KFW_AFS_klog(ctx, cc, "afs", cell, realm->data, pLeash_get_default_lifetime(),NULL);
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
if ( IsDebuggerPresent() ) {
char message[256];
sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
pkrb5_free_unparsed_name(ctx,pname);
if (princ)
pkrb5_free_principal(ctx,princ);
+ if (def_realm)
+ pkrb5_free_default_realm(ctx, def_realm);
if (cc)
pkrb5_cc_close(ctx,cc);
if (ctx)
void
KFW_import_ccache_data(void)
{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal principal = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal principal = NULL;
krb5_creds creds;
krb5_error_code code;
krb5_error_code cc_code;
krb5_cc_cursor cur;
- apiCB * cc_ctx = 0;
+ apiCB * cc_ctx = NULL;
struct _infoNC ** pNCi = NULL;
int i, j, flags;
code = pkrb5_cc_close(ctx,cc);
cc = 0;
code = pkrb5_cc_close(ctx,oldcc);
- cc = 0;
+ oldcc = 0;
KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
continue;
}
OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
}
- code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, pLeash_get_default_lifetime(),NULL);
+ code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
+#ifndef USE_LEASH
+ 600,
+#else
+ pLeash_get_default_lifetime(),
+#endif /* USE_LEASH */
+ NULL);
if ( IsDebuggerPresent() ) {
char message[256];
sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
int
-KFW_AFS_get_cred(char * username,
+KFW_AFS_get_cred( char * username,
char * cell,
char * password,
int lifetime,
char * smbname,
char ** reasonP )
{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- char * realm = 0;
- char ** realmlist = 0;
- krb5_principal principal = 0;
- char * pname = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ char * realm = NULL, * userrealm = NULL;
+ krb5_principal principal = NULL;
+ char * pname = NULL;
krb5_error_code code;
- char local_cell[MAXCELLCHARS+1];
+ char local_cell[MAXCELLCHARS+1];
char **cells = NULL;
int cell_count=0;
struct afsconf_cell cellconfig;
+ char * dot;
if (!pkrb5_init_context)
return 0;
code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
if ( code ) goto cleanup;
- realm = strchr(username,'@');
- if (realm) {
- *realm = '\0';
- realm++;
- }
- if ( !realm || !realm[0] )
- realm = afs_realm_of_cell(&cellconfig); // do not free
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
+
+ userrealm = strchr(username,'@');
+ if ( userrealm ) {
+ pname = strdup(username);
+ if (!KFW_accept_dotted_usernames()) {
+ userrealm = strchr(pname, '@');
+ *userrealm = '\0';
+
+ /* handle kerberos iv notation */
+ while ( dot = strchr(pname,'.') ) {
+ *dot = '/';
+ }
+ *userrealm++ = '@';
+ }
+ } else {
+ pname = malloc(strlen(username) + strlen(realm) + 2);
+ strcpy(pname, username);
+
+ if (!KFW_accept_dotted_usernames()) {
+ /* handle kerberos iv notation */
+ while ( dot = strchr(pname,'.') ) {
+ *dot = '/';
+ }
+ }
+ strcat(pname,"@");
+ strcat(pname,realm);
+ }
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
OutputDebugString("\n");
}
- code = pkrb5_build_principal(ctx, &principal, strlen(realm),
- realm, username,
- NULL,
- NULL);
-
- code = KFW_get_ccache(ctx, principal, &cc);
+ code = pkrb5_parse_name(ctx, pname, &principal);
if ( code ) goto cleanup;
- code = pkrb5_unparse_name(ctx, principal, &pname);
+ code = KFW_get_ccache(ctx, principal, &cc);
if ( code ) goto cleanup;
if ( lifetime == 0 )
+#ifndef USE_LEASH
+ lifetime = 600;
+#else
lifetime = pLeash_get_default_lifetime();
+#endif
- code = KFW_kinit(ctx, cc, HWND_DESKTOP,
- pname,
- password,
- lifetime,
- pLeash_get_default_forwardable(),
- pLeash_get_default_proxiable(),
- pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
- pLeash_get_default_noaddresses(),
- pLeash_get_default_publicip());
- if ( IsDebuggerPresent() ) {
- char message[256];
- sprintf(message,"KFW_kinit() returns: %d\n",code);
- OutputDebugString(message);
+ if ( password && password[0] ) {
+ code = KFW_kinit( ctx, cc, HWND_DESKTOP,
+ pname,
+ password,
+ lifetime,
+#ifndef USE_LEASH
+ 1, /* forwardable */
+ 0, /* not proxiable */
+ 1, /* renewable */
+ 1, /* noaddresses */
+ 0 /* no public ip */
+#else
+ pLeash_get_default_forwardable(),
+ pLeash_get_default_proxiable(),
+ pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
+ pLeash_get_default_noaddresses(),
+ pLeash_get_default_publicip()
+#endif /* USE_LEASH */
+ );
+
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_kinit() returns: %d\n",code);
+ OutputDebugString(message);
+ }
+ if ( code ) goto cleanup;
+
+ KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
}
- if ( code ) goto cleanup;
-
- KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
- code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
if ( IsDebuggerPresent() ) {
char message[256];
sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
if ( code ) continue;
- realm = afs_realm_of_cell(&cellconfig); // do not free
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
OutputDebugString("\n");
}
- code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime,smbname);
+ code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
if ( IsDebuggerPresent() ) {
char message[256];
sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
cleanup:
if ( pname )
- pkrb5_free_unparsed_name(ctx,pname);
+ free(pname);
if ( cc )
pkrb5_cc_close(ctx, cc);
int
KFW_AFS_destroy_tickets_for_cell(char * cell)
{
- krb5_context ctx = 0;
- krb5_error_code code;
+ krb5_context ctx = NULL;
+ krb5_error_code code;
int count;
char ** principals = NULL;
return 0;
if ( IsDebuggerPresent() ) {
- OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
+ OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
OutputDebugString(cell);
OutputDebugString("\n");
}
}
free(principals);
}
- pkrb5_free_context(ctx);
+ if (ctx)
+ pkrb5_free_context(ctx);
+ return 0;
+}
+
+int
+KFW_AFS_destroy_tickets_for_principal(char * user)
+{
+ krb5_context ctx = NULL;
+ krb5_error_code code;
+ int count;
+ char ** cells = NULL;
+ krb5_principal princ = NULL;
+ krb5_ccache cc = NULL;
+
+ if (!pkrb5_init_context)
+ return 0;
+
+ if ( IsDebuggerPresent() ) {
+ OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
+ OutputDebugString(user);
+ OutputDebugString("\n");
+ }
+
+ code = pkrb5_init_context(&ctx);
+ if (code) return 0;
+
+ code = pkrb5_parse_name(ctx, user, &princ);
+ if (code) goto loop_cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto loop_cleanup;
+
+ code = pkrb5_cc_destroy(ctx, cc);
+ if (!code) cc = 0;
+
+ loop_cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
+ if ( count >= 1 ) {
+ while ( count-- ) {
+ KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
+ free(cells[count]);
+ }
+ free(cells);
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
return 0;
}
int
KFW_AFS_renew_expiring_tokens(void)
{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
+ krb5_error_code code = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
krb5_timestamp now;
struct principal_ccache_data * pcc_next = princ_cc_data;
int cell_count;
}
code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
if ( code ) continue;
- realm = afs_realm_of_cell(&cellconfig); // do not free
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
OutputDebugString("\n");
}
- code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, pLeash_get_default_lifetime(),NULL);
+ code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
if ( IsDebuggerPresent() ) {
char message[256];
sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
BOOL
KFW_AFS_renew_token_for_cell(char * cell)
{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
+ krb5_error_code code = 0;
+ krb5_context ctx = NULL;
int count;
char ** principals = NULL;
code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
if ( code ) goto loop_cleanup;
- realm = afs_realm_of_cell(&cellconfig); // do not free
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
}
#endif /* COMMENT */
- code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime(),NULL);
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
if ( IsDebuggerPresent() ) {
char message[256];
sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
code = -1; // we did not renew the tokens
cleanup:
- pkrb5_free_context(ctx);
+ if (ctx)
+ pkrb5_free_context(ctx);
return (code ? FALSE : TRUE);
}
int
KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal me = 0;
- krb5_principal server = 0;
- krb5_creds my_creds;
- krb5_data *realm = 0;
+ krb5_error_code code = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal me = NULL;
+ krb5_principal server = NULL;
+ krb5_creds my_creds;
+ krb5_data *realm = NULL;
if (!pkrb5_init_context)
return 0;
DWORD publicIP
)
{
- krb5_error_code code = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
- krb5_principal me = 0;
- char* name = 0;
- krb5_creds my_creds;
+ krb5_error_code code = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
+ krb5_principal me = NULL;
+ char* name = NULL;
+ krb5_creds my_creds;
krb5_get_init_creds_opt options;
krb5_address ** addrs = NULL;
int i = 0, addr_count = 0;
code = pkrb5_parse_name(ctx, principal_name, &me);
if (code)
- goto cleanup;
+ goto cleanup;
code = pkrb5_unparse_name(ctx, me, &name);
if (code)
- goto cleanup;
+ goto cleanup;
if (lifetime == 0)
+#ifndef USE_LEASH
+ lifetime = 600;
+#else
lifetime = pLeash_get_default_lifetime();
- else
- lifetime *= 5*60;
+#endif /* USE_LEASH */
+ lifetime *= 60;
- if (renew_life > 0)
- renew_life *= 5*60;
+ if (renew_life > 0)
+ renew_life *= 60;
if (lifetime)
pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
if (addressless)
pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
else {
- if (publicIP)
+ if (publicIP)
{
// we are going to add the public IP address specified by the user
// to the list provided by the operating system
0, // service name
&options);
if (code)
- goto cleanup;
+ goto cleanup;
code = pkrb5_cc_initialize(ctx, cc, me);
if (code)
- goto cleanup;
+ goto cleanup;
code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
if (code)
- goto cleanup;
+ goto cleanup;
cleanup:
if ( addrs ) {
int
KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
{
- krb5_context ctx;
- krb5_ccache cc;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
krb5_error_code code;
if (!pkrb5_init_context)
static LPWORD
lpwAlign( LPWORD lpIn )
{
- ULONG ul;
+ ULONG_PTR ul;
- ul = (ULONG) lpIn;
+ ul = (ULONG_PTR) lpIn;
ul += 3;
ul >>=2;
ul <<=2;
lpdit->dwExtendedStyle = 0;
lpdit->x = 10;
lpdit->y = 10 + i * 14;
- lpdit->cx = strlen(ptext[i]) * 4 + 10;
+ lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
lpdit->cy = 14;
lpdit->id = ID_TEXT + i; // text identifier
}
for ( i=0, pwid = 0; i<tb_cnt; i++) {
- if ( pwid < strlen(tb[i].label) )
- pwid = strlen(tb[i].label);
+ int len = (int)strlen(tb[i].label);
+ if ( pwid < len )
+ pwid = len;
}
for ( i=0; i<tb_cnt; i++) {
static int
multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
{
- HINSTANCE hInst = 0;
+ HINSTANCE hInst = 0;
int maxwidth = 0;
int numlines = 0;
int len;
*p++ = '\0';
}
if ( strlen(plines[numlines-1]) > maxwidth )
- maxwidth = strlen(plines[numlines-1]);
+ maxwidth = (int)strlen(plines[numlines-1]);
}
for ( i=0;i<n;i++ ) {
- len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
+ len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
if ( maxwidth < len )
maxwidth = len;
}
- return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb));
+ return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
}
static krb5_error_code KRB5_CALLCONV
HWND hParent = (HWND)data;
if (name)
- nlen = strlen(name)+2;
+ nlen = (int)strlen(name)+2;
if (banner)
- blen = strlen(banner)+2;
+ blen = (int)strlen(banner)+2;
tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
if ( tb != NULL ) {
ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
if ( ok ) {
for ( i=0; i < num_prompts; i++ )
- prompts[i].reply->length = strlen(prompts[i].reply->data);
+ prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
} else
errcode = -2;
}
return(0);
}
+
+#define ALLOW_REGISTER 1
+static int
+ViceIDToUsername(char *username,
+ char *realm_of_user,
+ char *realm_of_cell,
+ char * cell_to_use,
+ struct ktc_principal *aclient,
+ struct ktc_principal *aserver,
+ struct ktc_token *atoken)
+{
+ static char lastcell[MAXCELLCHARS+1] = { 0 };
+ static char confname[512] = { 0 };
+#ifdef AFS_ID_TO_NAME
+ char username_copy[BUFSIZ];
+#endif /* AFS_ID_TO_NAME */
+ long viceId = ANONYMOUSID; /* AFS uid of user */
+ int status = 0;
+#ifdef ALLOW_REGISTER
+ afs_int32 id;
+#endif /* ALLOW_REGISTER */
+
+ if (confname[0] == '\0') {
+ strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
+ confname[sizeof(confname) - 2] = '\0';
+ }
+
+ strcpy(lastcell, aserver->cell);
+
+ if (!pr_Initialize (0, confname, aserver->cell)) {
+ char sname[PR_MAXNAMELEN];
+ strncpy(sname, username, PR_MAXNAMELEN);
+ sname[PR_MAXNAMELEN-1] = '\0';
+ status = pr_SNameToId (sname, &viceId);
+ pr_End();
+ }
+
+ /*
+ * This is a crock, but it is Transarc's crock, so
+ * we have to play along in order to get the
+ * functionality. The way the afs id is stored is
+ * as a string in the username field of the token.
+ * Contrary to what you may think by looking at
+ * the code for tokens, this hack (AFS ID %d) will
+ * not work if you change %d to something else.
+ */
+
+ /*
+ * This code is taken from cklog -- it lets people
+ * automatically register with the ptserver in foreign cells
+ */
+
+#ifdef ALLOW_REGISTER
+ if (status == 0) {
+ if (viceId != ANONYMOUSID) {
+#else /* ALLOW_REGISTER */
+ if ((status == 0) && (viceId != ANONYMOUSID))
+#endif /* ALLOW_REGISTER */
+ {
+#ifdef AFS_ID_TO_NAME
+ strncpy(username_copy, username, BUFSIZ);
+ snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
+#endif /* AFS_ID_TO_NAME */
+ }
+#ifdef ALLOW_REGISTER
+ } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
+ id = 0;
+ strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
+ strcpy(aclient->instance, "");
+ strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
+ if (status = ktc_SetToken(aserver, atoken, aclient, 0))
+ return status;
+ if (status = pr_Initialize(1L, confname, aserver->cell))
+ return status;
+ status = pr_CreateUser(username, &id);
+ pr_End();
+ if (status)
+ return status;
+#ifdef AFS_ID_TO_NAME
+ strncpy(username_copy, username, BUFSIZ);
+ snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
+#endif /* AFS_ID_TO_NAME */
+ }
+ }
+#endif /* ALLOW_REGISTER */
+ return status;
+}
+
+
int
KFW_AFS_klog(
krb5_context alt_ctx,
char *service,
char *cell,
char *realm,
- int LifeTime,
+ int lifetime, /* unused parameter */
char *smbname
)
{
long rc = 0;
CREDENTIALS creds;
+#ifdef USE_KRB4
KTEXT_ST ticket;
+#endif /* USE_KRB4 */
struct ktc_principal aserver;
struct ktc_principal aclient;
char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
DWORD CurrentState;
char HostName[64];
BOOL try_krb5 = 0;
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
krb5_creds increds;
- krb5_creds * k5creds = 0;
+ krb5_creds * k5creds = NULL;
krb5_error_code code;
- krb5_principal client_principal = 0;
+ krb5_principal client_principal = NULL;
+ krb5_data * k5data = NULL;
int i, retry = 0;
CurrentState = 0;
memset(ServiceName, '\0', sizeof(ServiceName));
memset(realm_of_user, '\0', sizeof(realm_of_user));
memset(realm_of_cell, '\0', sizeof(realm_of_cell));
- if (cell && cell[0])
- strcpy(Dmycell, cell);
- else
- memset(Dmycell, '\0', sizeof(Dmycell));
+ if (cell && cell[0])
+ strcpy(Dmycell, cell);
+ else
+ memset(Dmycell, '\0', sizeof(Dmycell));
// NULL or empty cell returns information on local cell
if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
memset((char *)&increds, 0, sizeof(increds));
code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
- if (code) {
+ if (code) {
if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
{
OutputDebugString("Principal Not Found for ccache\n");
}
goto skip_krb5_init;
}
+
+ if (!KFW_accept_dotted_usernames()) {
+ /* look for client principals which cannot be distinguished
+ * from Kerberos 4 multi-component principal names
+ */
+ k5data = krb5_princ_component(ctx,client_principal,0);
+ for ( i=0; i<k5data->length; i++ ) {
+ if ( k5data->data[i] == '.' )
+ break;
+ }
+ if (i != k5data->length)
+ {
+ OutputDebugString("Illegal Principal name contains dot in first component\n");
+ rc = KRB5KRB_ERR_GENERIC;
+ goto cleanup;
+ }
+ }
+
i = krb5_princ_realm(ctx, client_principal)->length;
if (i > REALM_SZ-1)
i = REALM_SZ-1;
}
}
#else
- goto cleanup;
+ if (!try_krb5)
+ goto cleanup;
#endif
- strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig));
+ strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
if (strlen(service) == 0)
strcpy(ServiceName, "afs");
/* First try service/cell@REALM */
if (code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
+ (int)strlen(RealmName),
RealmName,
ServiceName,
CellName,
code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) {
+ code == KRB5KRB_AP_ERR_MSG_TYPE) {
/* Or service@REALM */
pkrb5_free_principal(ctx,increds.server);
increds.server = 0;
code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
+ (int)strlen(RealmName),
RealmName,
ServiceName,
0);
if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) &&
+ code == KRB5KRB_AP_ERR_MSG_TYPE) &&
strcmp(RealmName, realm_of_cell)) {
/* Or service/cell@REALM_OF_CELL */
strcpy(RealmName, realm_of_cell);
pkrb5_free_principal(ctx,increds.server);
increds.server = 0;
code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
+ (int)strlen(RealmName),
RealmName,
ServiceName,
CellName,
pkrb5_free_principal(ctx,increds.server);
increds.server = 0;
code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
+ (int)strlen(RealmName),
RealmName,
ServiceName,
0);
* No need to perform a krb524 translation which is
* commented out in the code below
*/
- if (k5creds->ticket.length > MAXKTCTICKETLEN)
+ if (KFW_use_krb524() ||
+ k5creds->ticket.length > MAXKTCTICKETLEN)
goto try_krb524d;
memset(&aserver, '\0', sizeof(aserver));
char * p;
strcat(aclient.name, ".");
p = aclient.name + strlen(aclient.name);
- len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
+ len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
strncpy(p, k5creds->client->data[1].data, len);
p[len] = '\0';
}
strcpy(aclient.cell, realm_of_cell);
- len = min(k5creds->client->realm.length,strlen(realm_of_cell));
- if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
+ len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
+ /* For Khimaira, always append the realm name */
+ if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
char * p;
strcat(aclient.name, "@");
p = aclient.name + strlen(aclient.name);
- len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
+ len = min(k5creds->client->realm.length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
strncpy(p, k5creds->client->realm.data, len);
p[len] = '\0';
}
+ GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+ ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
+ &aclient, &aserver, &atoken);
+
if ( smbname ) {
- strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
- aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+ strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+ aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
} else {
aclient.smbname[0] = '\0';
}
- rc = ktc_SetToken(&aserver, &atoken, &aclient, 0);
+ rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
if (!rc)
goto cleanup; /* We have successfully inserted the token */
try_krb524d:
+#ifndef USE_KRB524
+ goto cleanup;
+#else
/* Otherwise, the ticket could have been too large so try to
* convert using the krb524d running with the KDC
*/
try_krb5 = 0;
goto use_krb4;
}
+#endif /* USE_KRB524 */
} else {
use_krb4:
#ifdef USE_KRB4
}
strcpy(aclient.instance, "");
- if ( strcmp(realm_of_cell, creds.realm) )
- {
- strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
- strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
- }
+ strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
+ strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
aclient.name[MAXKTCREALMLEN-1] = '\0';
strcpy(aclient.cell, CellName);
+ GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+ ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
+ &aclient, &aserver, &atoken);
+
if ( smbname ) {
- strncpy(aclient.smbname, smbname, MAXRANDOMNAMELEN);
- aclient.smbname[MAXRANDOMNAMELEN-1] = '\0';
+ strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
+ aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
} else {
aclient.smbname[0] = '\0';
}
- if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0))
+ if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
{
KFW_AFS_error(rc, "ktc_SetToken()");
code = rc;
if (ctx && (ctx != alt_ctx))
pkrb5_free_context(ctx);
- return(rc? rc : code);
+ return(rc? rc : code);
}
/**************************************/
/* afs_realm_of_cell(): */
/**************************************/
static char *
-afs_realm_of_cell(struct afsconf_cell *cellconfig)
+afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
{
static char krbrlm[REALM_SZ+1]="";
- krb5_context ctx = 0;
char ** realmlist=NULL;
krb5_error_code r;
if (!cellconfig)
return 0;
- if (!pkrb5_init_context)
- return 0;
-
- r = pkrb5_init_context(&ctx);
- if ( !r )
- r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
+ r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
if ( !r && realmlist && realmlist[0] ) {
strcpy(krbrlm, realmlist[0]);
pkrb5_free_host_realm(ctx, realmlist);
}
- if (ctx)
- pkrb5_free_context(ctx);
if ( !krbrlm[0] )
{
BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
{
- krb5_context ctx = 0;
- krb5_ccache cc = 0;
+ krb5_context ctx = NULL;
+ krb5_ccache cc = NULL;
krb5_error_code code;
krb5_data pwdata;
- const char * realm = 0;
- krb5_principal principal = 0;
- char * pname = 0;
+ const char * realm = NULL;
+ krb5_principal principal = NULL;
+ char * pname = NULL;
char password[PROBE_PASSWORD_LEN+1];
BOOL serverReachable = 0;
- realm = afs_realm_of_cell(cellconfig); // do not free
+ if (!pkrb5_init_context)
+ return 0;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
- code = pkrb5_build_principal(ctx, &principal, strlen(realm),
+ realm = afs_realm_of_cell(ctx, cellconfig); // do not free
+
+ code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
realm, PROBE_USERNAME, NULL, NULL);
if ( code ) goto cleanup;
return serverReachable;
}
+BOOL
+KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
+{
+ krb5_context ctx = NULL;
+ krb5_error_code code;
+ krb5_ccache mslsa_ccache=NULL;
+ krb5_principal princ = NULL;
+ char * pname = NULL;
+ BOOL success = 0;
+
+ if (!KFW_is_available())
+ return FALSE;
+
+ if (code = pkrb5_init_context(&ctx))
+ goto cleanup;
+
+ if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
+ goto cleanup;
+
+ if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
+ goto cleanup;
+
+ if (code = pkrb5_unparse_name(ctx, princ, &pname))
+ goto cleanup;
+
+ if ( strlen(pname) < *dwSize ) {
+ strncpy(szUser, pname, *dwSize);
+ szUser[*dwSize-1] = '\0';
+ success = 1;
+ }
+ *dwSize = (DWORD)strlen(pname);
+
+ cleanup:
+ if (pname)
+ pkrb5_free_unparsed_name(ctx, pname);
+
+ if (princ)
+ pkrb5_free_principal(ctx, princ);
+
+ if (mslsa_ccache)
+ pkrb5_cc_close(ctx, mslsa_ccache);
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+ return success;
+}
+
+int
+KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
+{
+ // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
+ PSID pSystemSID = NULL;
+ DWORD SystemSIDlength = 0, UserSIDlength = 0;
+ PACL ccacheACL = NULL;
+ DWORD ccacheACLlength = 0;
+ PTOKEN_USER pTokenUser = NULL;
+ DWORD retLen;
+ DWORD gle;
+ int ret = 0;
+
+ if (!filename) {
+ return 1;
+ }
+
+ /* Get System SID */
+ if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
+ ret = 1;
+ goto cleanup;
+ }
+
+ /* Create ACL */
+ SystemSIDlength = GetLengthSid(pSystemSID);
+ ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
+ + SystemSIDlength - sizeof(DWORD);
+
+ if (hUserToken) {
+ if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
+ {
+ if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
+ pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
+
+ GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
+ }
+ }
+
+ if (pTokenUser) {
+ UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
+
+ ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
+ - sizeof(DWORD);
+ }
+ }
+
+ ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
+ if (!ccacheACL) {
+ ret = 1;
+ goto cleanup;
+ }
+ InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+ pSystemSID);
+ if (pTokenUser) {
+ AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
+ STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
+ pTokenUser->User.Sid);
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ ccacheACL,
+ NULL)) {
+ gle = GetLastError();
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION,
+ pTokenUser->User.Sid,
+ NULL,
+ NULL,
+ NULL)) {
+ gle = GetLastError();
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ } else {
+ if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ ccacheACL,
+ NULL)) {
+ gle = GetLastError();
+ if (gle != ERROR_NO_TOKEN)
+ ret = 1;
+ }
+ }
+
+ cleanup:
+ if (pSystemSID)
+ LocalFree(pSystemSID);
+ if (pTokenUser)
+ LocalFree(pTokenUser);
+ if (ccacheACL)
+ LocalFree(ccacheACL);
+ return ret;
+}
+
+int
+KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
+{
+ int retval = 0;
+ DWORD dwSize = size-1; /* leave room for nul */
+ DWORD dwLen = 0;
+
+ if (!hUserToken || !newfilename || size <= 0)
+ return 1;
+
+ *newfilename = '\0';
+
+ dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
+ if ( !dwLen || dwLen > dwSize )
+ dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
+ if ( !dwLen || dwLen > dwSize )
+ return 1;
+
+ newfilename[dwSize] = '\0';
+ return 0;
+}
+
+void
+KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
+{
+ char filename[MAX_PATH] = "";
+ DWORD count;
+ char cachename[MAX_PATH + 8] = "FILE:";
+ krb5_context ctx = NULL;
+ krb5_error_code code;
+ krb5_principal princ = NULL;
+ krb5_ccache cc = NULL;
+ krb5_ccache ncc = NULL;
+
+ if (!pkrb5_init_context || !user || !szLogonId)
+ return;
+
+ count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
+ if ( count > sizeof(filename) || count == 0 ) {
+ GetWindowsDirectory(filename, sizeof(filename));
+ }
+
+ if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
+ return;
+
+ strcat(filename, "\\");
+ strcat(filename, szLogonId);
+
+ strcat(cachename, filename);
+
+ DeleteFile(filename);
+
+ code = pkrb5_init_context(&ctx);
+ if (code) goto cleanup;
+
+ code = pkrb5_parse_name(ctx, user, &princ);
+ if (code) goto cleanup;
+
+ code = KFW_get_ccache(ctx, princ, &cc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_resolve(ctx, cachename, &ncc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_initialize(ctx, ncc, princ);
+ if (code) goto cleanup;
+
+ code = KFW_AFS_set_file_cache_dacl(filename, NULL);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+
+ cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+ if ( ncc ) {
+ pkrb5_cc_close(ctx, ncc);
+ ncc = 0;
+ }
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+}
+
+int
+KFW_AFS_copy_file_cache_to_default_cache(char * filename)
+{
+ char cachename[MAX_PATH + 8] = "FILE:";
+ krb5_context ctx = NULL;
+ krb5_error_code code;
+ krb5_principal princ = NULL;
+ krb5_ccache cc = NULL;
+ krb5_ccache ncc = NULL;
+ int retval = 1;
+
+ if (!pkrb5_init_context || !filename)
+ return 1;
+
+ if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
+ return 1;
+
+ code = pkrb5_init_context(&ctx);
+ if (code) return 1;
+
+ strcat(cachename, filename);
+
+ code = pkrb5_cc_resolve(ctx, cachename, &cc);
+ if (code) goto cleanup;
+
+ code = pkrb5_cc_get_principal(ctx, cc, &princ);
+
+ code = pkrb5_cc_default(ctx, &ncc);
+ if (!code) {
+ code = pkrb5_cc_initialize(ctx, ncc, princ);
+
+ if (!code)
+ code = pkrb5_cc_copy_creds(ctx,cc,ncc);
+ }
+ if ( ncc ) {
+ pkrb5_cc_close(ctx, ncc);
+ ncc = 0;
+ }
+
+ retval=0; /* success */
+
+ cleanup:
+ if ( cc ) {
+ pkrb5_cc_close(ctx, cc);
+ cc = 0;
+ }
+
+ DeleteFile(filename);
+
+ if ( princ ) {
+ pkrb5_free_principal(ctx, princ);
+ princ = 0;
+ }
+
+ if (ctx)
+ pkrb5_free_context(ctx);
+
+ return 0;
+}
+
+/* We are including this
+
+/* Ticket lifetime. This defines the table used to lookup lifetime for the
+ fixed part of rande of the one byte lifetime field. Values less than 0x80
+ are intrpreted as the number of 5 minute intervals. Values from 0x80 to
+ 0xBF should be looked up in this table. The value of 0x80 is the same using
+ both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
+ The intervening values of have a fixed ratio of roughly 1.06914. The value
+ oxFF is defined to mean a ticket has no expiration time. This should be
+ used advisedly since individual servers may impose defacto upperbounds on
+ ticket lifetimes. */
+
+#define TKTLIFENUMFIXED 64
+#define TKTLIFEMINFIXED 0x80
+#define TKTLIFEMAXFIXED 0xBF
+#define TKTLIFENOEXPIRE 0xFF
+#define MAXTKTLIFETIME (30*24*3600) /* 30 days */
+
+static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
+ 38400, /* 10.67 hours, 0.44 days */
+ 41055, /* 11.40 hours, 0.48 days */
+ 43894, /* 12.19 hours, 0.51 days */
+ 46929, /* 13.04 hours, 0.54 days */
+ 50174, /* 13.94 hours, 0.58 days */
+ 53643, /* 14.90 hours, 0.62 days */
+ 57352, /* 15.93 hours, 0.66 days */
+ 61318, /* 17.03 hours, 0.71 days */
+ 65558, /* 18.21 hours, 0.76 days */
+ 70091, /* 19.47 hours, 0.81 days */
+ 74937, /* 20.82 hours, 0.87 days */
+ 80119, /* 22.26 hours, 0.93 days */
+ 85658, /* 23.79 hours, 0.99 days */
+ 91581, /* 25.44 hours, 1.06 days */
+ 97914, /* 27.20 hours, 1.13 days */
+ 104684, /* 29.08 hours, 1.21 days */
+ 111922, /* 31.09 hours, 1.30 days */
+ 119661, /* 33.24 hours, 1.38 days */
+ 127935, /* 35.54 hours, 1.48 days */
+ 136781, /* 37.99 hours, 1.58 days */
+ 146239, /* 40.62 hours, 1.69 days */
+ 156350, /* 43.43 hours, 1.81 days */
+ 167161, /* 46.43 hours, 1.93 days */
+ 178720, /* 49.64 hours, 2.07 days */
+ 191077, /* 53.08 hours, 2.21 days */
+ 204289, /* 56.75 hours, 2.36 days */
+ 218415, /* 60.67 hours, 2.53 days */
+ 233517, /* 64.87 hours, 2.70 days */
+ 249664, /* 69.35 hours, 2.89 days */
+ 266926, /* 74.15 hours, 3.09 days */
+ 285383, /* 79.27 hours, 3.30 days */
+ 305116, /* 84.75 hours, 3.53 days */
+ 326213, /* 90.61 hours, 3.78 days */
+ 348769, /* 96.88 hours, 4.04 days */
+ 372885, /* 103.58 hours, 4.32 days */
+ 398668, /* 110.74 hours, 4.61 days */
+ 426234, /* 118.40 hours, 4.93 days */
+ 455705, /* 126.58 hours, 5.27 days */
+ 487215, /* 135.34 hours, 5.64 days */
+ 520904, /* 144.70 hours, 6.03 days */
+ 556921, /* 154.70 hours, 6.45 days */
+ 595430, /* 165.40 hours, 6.89 days */
+ 636601, /* 176.83 hours, 7.37 days */
+ 680618, /* 189.06 hours, 7.88 days */
+ 727680, /* 202.13 hours, 8.42 days */
+ 777995, /* 216.11 hours, 9.00 days */
+ 831789, /* 231.05 hours, 9.63 days */
+ 889303, /* 247.03 hours, 10.29 days */
+ 950794, /* 264.11 hours, 11.00 days */
+ 1016537, /* 282.37 hours, 11.77 days */
+ 1086825, /* 301.90 hours, 12.58 days */
+ 1161973, /* 322.77 hours, 13.45 days */
+ 1242318, /* 345.09 hours, 14.38 days */
+ 1328218, /* 368.95 hours, 15.37 days */
+ 1420057, /* 394.46 hours, 16.44 days */
+ 1518247, /* 421.74 hours, 17.57 days */
+ 1623226, /* 450.90 hours, 18.79 days */
+ 1735464, /* 482.07 hours, 20.09 days */
+ 1855462, /* 515.41 hours, 21.48 days */
+ 1983758, /* 551.04 hours, 22.96 days */
+ 2120925, /* 589.15 hours, 24.55 days */
+ 2267576, /* 629.88 hours, 26.25 days */
+ 2424367, /* 673.44 hours, 28.06 days */
+ 2592000
+}; /* 720.00 hours, 30.00 days */
+
+/* life_to_time - takes a start time and a Kerberos standard lifetime char and
+ * returns the corresponding end time. There are four simple cases to be
+ * handled. The first is a life of 0xff, meaning no expiration, and results in
+ * an end time of 0xffffffff. The second is when life is less than the values
+ * covered by the table. In this case, the end time is the start time plus the
+ * number of 5 minute intervals specified by life. The third case returns
+ * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
+ * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
+ * table to extract the lifetime in seconds, which is added to start to produce
+ * the end time. */
+
+afs_uint32
+life_to_time(afs_uint32 start, unsigned char life)
+{
+ int realLife;
+
+ if (life == TKTLIFENOEXPIRE)
+ return NEVERDATE;
+ if (life < TKTLIFEMINFIXED)
+ return start + life * 5 * 60;
+ if (life > TKTLIFEMAXFIXED)
+ return start + MAXTKTLIFETIME;
+ realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
+ return start + realLife;
+}
+
+/* time_to_life - takes start and end times for the ticket and returns a
+ * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
+ * lifetimes above 127*5minutes. First, the special case of (end ==
+ * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
+ * those greater than the maximum ticket lifetime are rejected. Then lifetimes
+ * less than the first table entry are handled by rounding the requested
+ * lifetime *up* to the next 5 minute interval. The final step is to search
+ * the table for the smallest entry *greater than or equal* to the requested
+ * entry. The actual code is prepared to handle the case where the table is
+ * unordered but that it an unnecessary frill. */
+
+static unsigned char
+time_to_life(afs_uint32 start, afs_uint32 end)
+{
+ int lifetime = end - start;
+ int best, best_i;
+ int i;
+
+ if (end == NEVERDATE)
+ return TKTLIFENOEXPIRE;
+ if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
+ return 0;
+ if (lifetime < tkt_lifetimes[0])
+ return (lifetime + 5 * 60 - 1) / (5 * 60);
+ best_i = -1;
+ best = MAXKTCTICKETLIFETIME;
+ for (i = 0; i < TKTLIFENUMFIXED; i++)
+ if (tkt_lifetimes[i] >= lifetime) {
+ int diff = tkt_lifetimes[i] - lifetime;
+ if (diff < best) {
+ best = diff;
+ best_i = i;
+ }
+ }
+ if (best_i < 0)
+ return 0;
+ return best_i + TKTLIFEMINFIXED;
+}
+