/*
+ * Copyright (c) 2004, 2005, 2006, 2007, 2008 Secure Endpoints Inc.
* Copyright (c) 2003 SkyRope, LLC
* All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
+ *
+ * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
+ *
+ * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- * - Neither the name of Skyrope, LLC nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
+ * - Neither the name of Skyrope, LLC nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
* specific prior written permission from Skyrope, LLC.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
*
*/
+#undef USE_KRB4
+#ifndef _WIN64
+#define USE_KRB524 1
+#endif
+#define USE_MS2MIT 1
-#define USE_MS2MIT
-#define USE_KRB4
-#include "afskfw-int.h"
-#include "afskfw.h"
+#include <afsconfig.h>
+#include <afs/param.h>
+#include <roken.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>
+#include "cm.h"
+
+#include "afskfw.h"
+#include "afskfw-int.h"
+#include <userenv.h>
+#include "strsafe.h"
+
+#include <Sddl.h>
+#include <Aclapi.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);
+// Krb5 KFW 3.2 functions
+DECL_FUNC_PTR(krb5_get_error_message);
+DECL_FUNC_PTR(krb5_free_error_message);
+
+#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
};
+FUNC_INFO k5_kfw_32_fi[] = {
+ MAKE_FUNC_INFO(krb5_get_error_message),
+ MAKE_FUNC_INFO(krb5_free_error_message),
+ 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),
/* Static Prototypes */
char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
-static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
+static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
void *data, const char *name, const char *banner, int num_prompts,
static int mid_cnt = 0;
static struct textField * mid_tb = NULL;
static HINSTANCE hKrb5 = 0;
+static HINSTANCE hKrb5_kfw_32 = 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;
+#ifdef USE_LEASH
+#define DEFAULT_LIFETIME pLeash_get_default_lifetime()
+#else
+#define DEFAULT_LIFETIME (24 * 60)
+#endif
+
void
KFW_initialize(void)
{
char mutexName[MAX_PATH];
HANDLE hMutex = NULL;
- sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
-
+ StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
+
hMutex = CreateMutex( NULL, TRUE, mutexName );
if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
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(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 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() ) {
- char rootcell[MAXCELLCHARS+1];
+ char rootcell[CELL_MAXNAMELEN+1];
#ifdef USE_MS2MIT
KFW_import_windows_lsa();
#endif /* USE_MS2MIT */
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);
+ if (hKrb5_kfw_32)
+ FreeLibrary(hKrb5_kfw_32);
+}
+
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
+static int IsWow64()
+{
+ static int init = TRUE;
+ static int bIsWow64 = FALSE;
+
+ if (init) {
+ HMODULE hModule;
+ LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
+
+ hModule = GetModuleHandle(TEXT("kernel32"));
+ if (hModule) {
+ fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
+
+ if (NULL != fnIsWow64Process)
+ {
+ if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
+ {
+ // on error, assume FALSE.
+ // in other words, do nothing.
+ }
+ }
+ FreeLibrary(hModule);
+ }
+ init = FALSE;
+ }
+ return bIsWow64;
+}
+
+int
+KFW_accept_dotted_usernames(void)
+{
+ HKEY parmKey;
+ DWORD code, len;
+ DWORD value = 1;
+
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+ 0, (IsWow64()?KEY_WOW64_64KEY: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, (IsWow64()?KEY_WOW64_64KEY: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)
DWORD code, len;
DWORD use524 = 0;
- code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
- if (code != ERROR_SUCCESS)
- code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+ 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
if (code == ERROR_SUCCESS) {
len = sizeof(use524);
code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
(BYTE *) &use524, &len);
- if (code != ERROR_SUCCESS) {
- use524 = 0;
+ RegCloseKey(parmKey);
+ }
+ if (code != ERROR_SUCCESS) {
+ code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
+ 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
+ if (code == ERROR_SUCCESS) {
+ len = sizeof(use524);
+ code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
+ (BYTE *) &use524, &len);
+ RegCloseKey (parmKey);
}
- RegCloseKey (parmKey);
}
-
return use524;
}
-int
+int
KFW_is_available(void)
{
HKEY parmKey;
DWORD code, len;
DWORD enableKFW = 1;
- code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
- if (code != ERROR_SUCCESS)
- code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
- 0, KEY_QUERY_VALUE, &parmKey);
+ code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
+ 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
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, (IsWow64()?KEY_WOW64_64KEY: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;
KFW_initialize();
- if ( hKrb5 && hComErr && hService &&
+ if ( hKrb5 && hComErr && hService &&
#ifdef USE_MS2MIT
- hSecur32 &&
+ hSecur32 &&
#endif /* USE_MS2MIT */
+#ifdef USE_KRB524
hKrb524 &&
- hProfile && hLeash && hCCAPI )
+#endif
+#ifdef USE_LEASH
+ hLeash &&
+#endif
+ hProfile && hCCAPI )
return TRUE;
return FALSE;
}
-int
-KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
- int FreeContextFlag, krb5_context * ctx,
+int
+KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
+ int FreeContextFlag, krb5_context * ctx,
krb5_ccache * cache)
{
char message[256];
const char *errText;
- int krb5Error = ((int)(rc & 255));
-
+ int krb5Error = ((int)(rc & 255));
+
/*
switch (krb5Error)
{
return;
}
*/
-
- errText = perror_message(rc);
- _snprintf(message, sizeof(message),
- "%s\n(Kerberos error %ld)\n\n%s failed",
- errText,
- krb5Error,
+
+ if (pkrb5_get_error_message)
+ errText = pkrb5_get_error_message(ctx, rc);
+ else
+ errText = perror_message(rc);
+ StringCbPrintf(message, sizeof(message),
+ "%s\n(Kerberos error %ld)\n\n%s failed",
+ errText,
+ krb5Error,
FailedFunctionName);
+ if (pkrb5_free_error_message)
+ pkrb5_free_error_message(ctx, (char *)errText);
if ( IsDebuggerPresent() )
OutputDebugString(message);
- MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
- MB_TASKMODAL |
+ MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
+ MB_TASKMODAL |
MB_SETFOREGROUND);
if (FreeContextFlag == 1)
{
{
if (cache && *cache != NULL) {
pkrb5_cc_close(*ctx, *cache);
- *cache = NULL;
- }
-
+ *cache = NULL;
+ }
+
pkrb5_free_context(*ctx);
- *ctx = NULL;
+ *ctx = NULL;
}
}
krb5_principal principal = 0;
char * pname = NULL;
const char * ccname = NULL;
+ const char * cctype = NULL;
+ char * ccfullname = 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;
- // Search the existing list to see if we have a match
+ cctype = pkrb5_cc_get_type(ctx, cc);
+ if (!cctype) goto cleanup;
+
+ ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
+ if (!ccfullname) goto cleanup;
+
+ StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
+
+ // Search the existing list to see if we have a match
if ( next ) {
for ( ; next ; next = next->next ) {
- if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccname) )
+ if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
break;
}
- }
+ }
// If not, match add a new node to the beginning of the list and assign init it
if ( !next ) {
next->next = princ_cc_data;
princ_cc_data = next;
next->principal = _strdup(pname);
- next->ccache_name = _strdup(ccname);
+ next->ccache_name = ccfullname;
+ ccfullname = NULL;
next->from_lsa = lsa;
next->expired = 1;
next->expiration_time = 0;
if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
int valid;
// we found the ticket we are looking for
- // check validity of timestamp
+ // check validity of timestamp
// We add a 5 minutes fudge factor to compensate for potential
// clock skew errors between the KDC and client OS
} else if ( valid ) {
next->expired = 0;
next->expiration_time = creds.times.endtime;
- next->renew = (creds.times.renew_till > creds.times.endtime) &&
+ next->renew = (creds.times.renew_till > creds.times.endtime) &&
(creds.ticket_flags & TKT_FLG_RENEWABLE);
} else {
next->expired = 1;
flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
code = pkrb5_cc_set_flags(ctx, cc, flags);
+ if ( ccfullname)
+ free(ccfullname);
if ( pname )
pkrb5_free_unparsed_name(ctx,pname);
if ( principal )
pkrb5_free_principal(ctx,principal);
-}
+}
int
KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
}
response = _strdup(next->ccache_name);
// MS Kerberos LSA is our best option so use it and quit
- if ( next->from_lsa )
+ if ( next->from_lsa )
break;
}
next = next->next;
return 0;
}
-void
+void
KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
{
struct principal_ccache_data ** next = &princ_cc_data;
return;
while ( (*next) ) {
- if ( !strcmp((*next)->principal,pname) ||
+ if ( !strcmp((*next)->principal,pname) ||
!strcmp((*next)->ccache_name,ccname) ) {
void * temp;
free((*next)->principal);
}
}
-void
+void
KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
{
struct cell_principal_map * next = cell_princ_map;
- // Search the existing list to see if we have a match
+ // Search the existing list to see if we have a match
if ( next ) {
for ( ; next ; next = next->next ) {
if ( !strcmp(next->cell, cell) ) {
}
}
}
- }
+ }
// If not, match add a new node to the beginning of the list and assign init it
if ( !next ) {
}
}
-void
+void
KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
{
struct cell_principal_map ** next = &cell_princ_map;
return;
while ( (*next) ) {
- if ( !strcmp((*next)->principal,pname) ||
+ if ( !strcmp((*next)->principal,pname) ||
!strcmp((*next)->cell,cell) ) {
void * temp;
free((*next)->principal);
}
}
-// Returns (if possible) a principal which has been known in
+// Returns (if possible) a principal which has been known in
// the past to have been used to obtain tokens for the specified
-// cell.
+// cell.
// TODO: Attempt to return one which has not yet expired by checking
// the principal/ccache data
int
int count = 0, i;
struct cell_principal_map * next_map = cell_princ_map;
const char * princ = NULL;
-
+
if ( !pname )
return 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)
if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
!KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
- ccname = (char *)malloc(strlen(pname) + 5);
- sprintf(ccname,"API:%s",pname);
+ size_t len = strlen(pname) + 5;
+ ccname = (char *)malloc(len);
+ StringCbPrintf(ccname, len, "API:%s", pname);
}
code = pkrb5_cc_resolve(ctx, ccname, cc);
} else {
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 * princ_realm;
krb5_error_code code;
- char cell[128]="", realm[128]="";
- int i;
-
- if (!pkrb5_init_context)
- return;
+ char cell[128]="", realm[128]="", *def_realm = 0;
+ unsigned int i;
+ DWORD dwMsLsaImport;
-#ifdef COMMENT
- if ( !MSLSA_IsKerberosLogon() )
+ if (!pkrb5_init_context)
return;
-#endif
code = pkrb5_init_context(&ctx);
if (code) goto cleanup;
code = pkrb5_cc_get_principal(ctx, cc, &princ);
if ( code ) goto cleanup;
+#ifdef USE_LEASH
+ dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
+#else
+ dwMsLsaImport = 1;
+#endif
+ switch ( dwMsLsaImport ) {
+ case 0: /* do not import */
+ goto cleanup;
+ case 1: /* always import */
+ break;
+ case 2: { /* matching realm */
+ char ms_realm[128] = "", *r;
+ unsigned int j;
+
+ for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
+ *r = krb5_princ_realm(ctx, princ)->data[j];
+ }
+ *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;
princ_realm = krb5_princ_realm(ctx, princ);
for ( i=0; i<princ_realm->length; i++ ) {
- realm[i] = princ_realm->data[i];
+ realm[i] = princ_realm->data[i];
cell[i] = tolower(princ_realm->data[i]);
}
- cell[i] = '\0';
- realm[i] = '\0';
+ cell[i] = '\0';
+ realm[i] = '\0';
- code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, DEFAULT_LIFETIME, NULL);
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
OutputDebugString(message);
}
if ( code ) goto cleanup;
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;
OutputDebugString("\n");
}
if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
- && strcmp(pNCi[i]->name,LSA_CCNAME)
+ && strcmp(pNCi[i]->name,LSA_CCNAME)
) {
int found = 0;
for ( j=0; pNCi[j]; j++ ) {
break;
}
}
-
+
code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
if (code) goto loop_cleanup;
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;
}
}
memset(&aserver, '\0', sizeof(aserver));
- strcpy(aserver.name, sname->data);
- strcpy(aserver.cell, cell->data);
+ StringCbCopyN( aserver.name, sizeof(aserver.name),
+ sname->data, sizeof(aserver.name) - 1);
+ StringCbCopyN( aserver.cell, sizeof(aserver.cell),
+ cell->data, sizeof(aserver.cell) - 1);
code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
if (!code) {
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, DEFAULT_LIFETIME, NULL);
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
OutputDebugString(message);
}
}
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;
+ static char reason[1024]="";
+ 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[CELL_MAXNAMELEN+1];
char **cells = NULL;
int cell_count=0;
struct afsconf_cell cellconfig;
char * dot;
-
if (!pkrb5_init_context)
return 0;
OutputDebugString("\n");
}
+ memset(&cellconfig, 0, sizeof(cellconfig));
+
code = pkrb5_init_context(&ctx);
if ( code ) goto cleanup;
code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
if ( code ) goto cleanup;
- realm = strchr(username,'@');
- if ( realm ) {
+ realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
+
+ userrealm = strchr(username,'@');
+ if ( userrealm ) {
pname = strdup(username);
- realm = strchr(pname, '@');
- *realm = '\0';
+ if (!KFW_accept_dotted_usernames()) {
+ userrealm = strchr(pname, '@');
+ *userrealm = '\0';
- /* handle kerberos iv notation */
- while ( dot = strchr(pname,'.') ) {
- *dot = '/';
+ /* handle kerberos iv notation */
+ while ( dot = strchr(pname,'.') ) {
+ *dot = '/';
+ }
+ *userrealm++ = '@';
}
- *realm++ = '@';
} else {
- realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
- pname = malloc(strlen(username) + strlen(realm) + 2);
-
- strcpy(pname, username);
-
- /* handle kerberos iv notation */
- while ( dot = strchr(pname,'.') ) {
- *dot = '/';
+ size_t len = strlen(username) + strlen(realm) + 2;
+ pname = malloc(len);
+ if (pname == NULL) {
+ code = KRB5KRB_ERR_GENERIC;
+ goto cleanup;
}
+ StringCbCopy(pname, len, username);
- strcat(pname,"@");
- strcat(pname,realm);
+ if (!KFW_accept_dotted_usernames()) {
+ /* handle kerberos iv notation */
+ while ( dot = strchr(pname,'.') ) {
+ *dot = '/';
+ }
+ }
+ StringCbCat( pname, len, "@");
+ StringCbCat( pname, len, realm);
}
-
if ( IsDebuggerPresent() ) {
OutputDebugString("Realm: ");
OutputDebugString(realm);
if ( code ) goto cleanup;
if ( lifetime == 0 )
- lifetime = pLeash_get_default_lifetime();
+ lifetime = DEFAULT_LIFETIME;
- if ( password && password[0] ) {
- code = KFW_kinit( ctx, cc, HWND_DESKTOP,
- pname,
+ code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
+ OutputDebugString(message);
+ }
+
+ if (code && password && password[0] ) {
+ code = KFW_kinit( ctx, cc, HWND_DESKTOP,
+ pname,
password,
lifetime,
+#ifndef USE_LEASH
+ 0, /* 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());
+ pLeash_get_default_publicip()
+#endif /* USE_LEASH */
+ );
+
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"KFW_kinit() returns: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
OutputDebugString(message);
}
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);
+ StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
OutputDebugString(message);
}
if ( code ) goto cleanup;
KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
- // Attempt to obtain new tokens for other cells supported by the same
+ // Attempt to obtain new tokens for other cells supported by the same
// principal
cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
if ( cell_count > 1 ) {
if ( strcmp(cells[cell_count],cell) ) {
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"found another cell for the same principal: %s\n",cell);
+ StringCbPrintf(message, sizeof(message),
+ "found another cell for the same principal: %s\n", cell);
OutputDebugString(message);
}
+
+ if (cellconfig.linkedCell) {
+ free(cellconfig.linkedCell);
+ cellconfig.linkedCell = NULL;
+ }
code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
if ( code ) continue;
-
+
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);
+ StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
OutputDebugString(message);
}
}
free(pname);
if ( cc )
pkrb5_cc_close(ctx, cc);
+ if ( cellconfig.linkedCell )
+ free(cellconfig.linkedCell);
if ( code && reasonP ) {
- *reasonP = (char *)perror_message(code);
+ if (pkrb5_get_error_message) {
+ char *msg = pkrb5_get_error_message(ctx, code);
+ StringCbCopyN( reason, sizeof(reason),
+ msg, sizeof(reason) - 1);
+ *reasonP = reason;
+ pkrb5_free_error_message(ctx, msg);
+ } else {
+ *reasonP = perror_message(code);
+ }
}
return(code);
}
-int
+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;
char ** cells=NULL;
const char * realm = NULL;
- char local_cell[MAXCELLCHARS+1]="";
+ char local_cell[CELL_MAXNAMELEN+1]="";
struct afsconf_cell cellconfig;
if (!pkrb5_init_context)
OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
}
+ memset(&cellconfig, 0, sizeof(cellconfig));
+
code = pkrb5_init_context(&ctx);
if (code) goto cleanup;
code = pkrb5_timeofday(ctx, &now);
- if (code) goto cleanup;
+ if (code) goto cleanup;
for ( ; pcc_next ; pcc_next = pcc_next->next ) {
- if ( pcc_next->expired )
+ if ( pcc_next->expired )
continue;
if ( now >= (pcc_next->expiration_time) ) {
if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
- if ( code )
+ if ( code )
goto loop_cleanup;
code = KFW_renew(ctx,cc);
#ifdef USE_MS2MIT
KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
if (code) goto loop_cleanup;
- // Attempt to obtain new tokens for other cells supported by the same
+ // Attempt to obtain new tokens for other cells supported by the same
// principal
cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
if ( cell_count > 0 ) {
OutputDebugString(cells[cell_count]);
OutputDebugString("\n");
}
+ if (cellconfig.linkedCell) {
+ free(cellconfig.linkedCell);
+ cellconfig.linkedCell = NULL;
+ }
code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
if ( code ) continue;
realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
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);
+ StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
OutputDebugString(message);
}
free(cells[cell_count]);
pkrb5_cc_close(ctx,cc);
if ( ctx )
pkrb5_free_context(ctx);
+ if (cellconfig.linkedCell)
+ free(cellconfig.linkedCell);
return 0;
}
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;
krb5_ccache cc = 0;
const char * realm = NULL;
struct afsconf_cell cellconfig;
- char local_cell[MAXCELLCHARS+1];
+ char local_cell[CELL_MAXNAMELEN+1];
+
+ memset(&cellconfig, 0, sizeof(cellconfig));
while ( count-- ) {
code = pkrb5_parse_name(ctx, principals[count], &princ);
code = KFW_get_ccache(ctx, princ, &cc);
if (code) goto loop_cleanup;
+ if (cellconfig.linkedCell) {
+ free(cellconfig.linkedCell);
+ cellconfig.linkedCell = NULL;
+ }
code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
if ( code ) goto loop_cleanup;
}
#ifdef COMMENT
- /* krb5_cc_remove_cred() is not implemented
- * for a single cred
+ /* krb5_cc_remove_cred() is not implemented
+ * for a single cred
*/
code = pkrb5_build_principal(ctx, &service, strlen(realm),
realm, "afs", cell, NULL);
}
#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);
+ StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
OutputDebugString(message);
}
pkrb5_free_principal(ctx, service);
princ = 0;
}
+ if (cellconfig.linkedCell) {
+ free(cellconfig.linkedCell);
+ cellconfig.linkedCell = NULL;
+ }
KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
free(principals[count]);
}
free(principals);
} else
- code = -1; // we did not renew the tokens
+ 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;
KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
realm->length,realm->data,
0);
- if ( code )
+ if ( code )
goto cleanup;
if ( IsDebuggerPresent() ) {
if (code) {
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
OutputDebugString(message);
}
goto cleanup;
if (code) {
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
OutputDebugString(message);
}
goto cleanup;
if (code) {
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
OutputDebugString(message);
}
goto cleanup;
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;
if ( alt_cc ) {
cc = alt_cc;
} else {
- code = pkrb5_cc_default(ctx, &cc);
+ code = pkrb5_cc_default(ctx, &cc);
if (code) goto cleanup;
}
code = pkrb5_parse_name(ctx, principal_name, &me);
- if (code)
- goto cleanup;
+ if (code)
+ goto cleanup;
code = pkrb5_unparse_name(ctx, me, &name);
- if (code)
- goto cleanup;
+ if (code)
+ goto cleanup;
if (lifetime == 0)
- lifetime = pLeash_get_default_lifetime();
- else
- lifetime *= 5*60;
+ lifetime = DEFAULT_LIFETIME;
+ 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
netIPAddr = htonl(publicIP);
memcpy(addrs[i]->contents,&netIPAddr,4);
-
+
pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
}
}
- code = pkrb5_get_init_creds_password(ctx,
- &my_creds,
+ code = pkrb5_get_init_creds_password(ctx,
+ &my_creds,
me,
password, // password
KRB5_prompter, // prompter
0, // start time
0, // service name
&options);
- if (code)
- goto cleanup;
+ if (code)
+ goto cleanup;
code = pkrb5_cc_initialize(ctx, cc, me);
- if (code)
- goto cleanup;
+ if (code)
+ goto cleanup;
code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
- if (code)
- goto cleanup;
+ if (code)
+ 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)
if ( alt_cc ) {
cc = alt_cc;
} else {
- code = pkrb5_cc_default(ctx, &cc);
+ code = pkrb5_cc_default(ctx, &cc);
if (code) goto cleanup;
}
}
//
-// MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
-// cache. It validates whether or not it is reasonable to assume that if we
-// attempted to retrieve valid tickets we could do so. Microsoft does not
+// MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
+// cache. It validates whether or not it is reasonable to assume that if we
+// attempted to retrieve valid tickets we could do so. Microsoft does not
// automatically renew expired tickets. Therefore, the cache could contain
-// expired or invalid tickets. Microsoft also caches the user's password
+// expired or invalid tickets. Microsoft also caches the user's password
// and will use it to retrieve new TGTs if the cache is empty and tickets
// are requested.
usLength = (pSessionData->AuthenticationPackage).Length;
if (usLength < 256)
{
- lstrcpynW (buffer, usBuffer, usLength);
- lstrcatW (buffer,L"");
+ StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
+ usBuffer, usLength);
if ( !lstrcmpW(L"Kerberos",buffer) )
Success = TRUE;
}
}
#endif /* USE_MS2MIT */
-static BOOL CALLBACK
+static BOOL CALLBACK
MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
{
int i;
for ( i=0; i < mid_cnt ; i++ ) {
if (mid_tb[i].echo == 0)
SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
- else if (mid_tb[i].echo == 2)
+ else if (mid_tb[i].echo == 2)
SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
}
return TRUE;
return FALSE;
}
-static LPWORD
+static LPWORD
lpwAlign( LPWORD lpIn )
{
- ULONG ul;
+ ULONG_PTR ul;
- ul = (ULONG) lpIn;
+ ul = (ULONG_PTR) lpIn;
ul += 3;
ul >>=2;
ul <<=2;
*/
static LRESULT
-MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
- char * ptext[], int numlines, int width,
+MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
+ char * ptext[], int numlines, int width,
int tb_cnt, struct textField * tb)
{
HGLOBAL hgbl;
hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
if (!hgbl)
return -1;
-
+
mid_cnt = tb_cnt;
mid_tb = tb;
lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
-
+
// Define a dialog box.
-
+
lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
- | DS_MODALFRAME | WS_CAPTION | DS_CENTER
+ | DS_MODALFRAME | WS_CAPTION | DS_CENTER
| DS_SETFOREGROUND | DS_3DLOOK
| DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
- lpdt->x = 10;
+ lpdt->x = 10;
lpdt->y = 10;
- lpdt->cx = 20 + width * 4;
+ lpdt->cx = 20 + width * 4;
lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
lpw = (LPWORD) (lpdt + 1);
lpw += nchar;
*lpw++ = 8; // font size (points)
lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
+ nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
-1, lpwsz, 128);
lpw += nchar;
lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
lpdit->dwExtendedStyle = 0;
- lpdit->x = (lpdt->cx - 14)/4 - 20;
+ lpdit->x = (lpdt->cx - 14)/4 - 20;
lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
- lpdit->cx = 40;
+ lpdit->cx = 40;
lpdit->cy = 14;
lpdit->id = IDOK; // OK button identifier
lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
lpdit->dwExtendedStyle = 0;
- lpdit->x = (lpdt->cx - 14)*3/4 - 20;
+ lpdit->x = (lpdt->cx - 14)*3/4 - 20;
lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
- lpdit->cx = 40;
+ lpdit->cx = 40;
lpdit->cy = 14;
lpdit->id = IDCANCEL; // CANCEL button identifier
lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
lpdit->dwExtendedStyle = 0;
- lpdit->x = 10;
+ 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
*lpw++ = 0x0082; // static class
lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
+ nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
-1, lpwsz, 2*width);
lpw += nchar;
*lpw++ = 0; // no creation data
}
-
+
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++) {
lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
lpdit->dwExtendedStyle = 0;
- lpdit->x = 10;
+ lpdit->x = 10;
lpdit->y = 10 + (numlines + i + 1) * 14;
- lpdit->cx = pwid * 4;
+ lpdit->cx = pwid * 4;
lpdit->cy = 14;
lpdit->id = ID_TEXT + numlines + i; // text identifier
*lpw++ = 0x0082; // static class
lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
+ nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
-1, lpwsz, 128);
lpw += nchar;
*lpw++ = 0; // no creation data
lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
lpdit->dwExtendedStyle = 0;
- lpdit->x = 10 + (pwid + 1) * 4;
+ lpdit->x = 10 + (pwid + 1) * 4;
lpdit->y = 10 + (numlines + i + 1) * 14;
- lpdit->cx = (width - (pwid + 1)) * 4;
+ lpdit->cx = (width - (pwid + 1)) * 4;
lpdit->cy = 14;
lpdit->id = ID_MID_TEXT + i; // identifier
*lpw++ = 0x0081; // edit class
lpwsz = (LPWSTR) lpw;
- nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
+ nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
-1, lpwsz, 128);
lpw += nchar;
*lpw++ = 0; // no creation data
}
- GlobalUnlock(hgbl);
- ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
- hwndOwner, (DLGPROC) MultiInputDialogProc);
- GlobalFree(hgbl);
+ GlobalUnlock(hgbl);
+ ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
+ hwndOwner, (DLGPROC) MultiInputDialogProc);
+ GlobalFree(hgbl);
switch ( ret ) {
case 0: /* Timeout */
return 0;
default: {
char buf[256];
- sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
+ StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
MessageBox(hwndOwner,
buf,
"GetLastError()",
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;
char * plines[16], *p = preface ? preface : "";
int i;
- for ( i=0; i<16; i++ )
+ for ( i=0; i<16; i++ )
plines[i] = NULL;
while (*p && numlines < 16) {
p++;
} else if ( *p == '\n' ) {
*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 ) {
tb[i].label = prompts[i].prompt;
tb[i].def = NULL;
tb[i].echo = (prompts[i].hidden ? 2 : 1);
- }
+ }
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;
}
#define ALLOW_REGISTER 1
static int
-ViceIDToUsername(char *username,
- char *realm_of_user,
+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_principal *aclient,
+ struct ktc_principal *aserver,
struct ktc_token *atoken)
{
- static char lastcell[MAXCELLCHARS+1] = { 0 };
- static char confname[512] = { 0 };
+ static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
+ static char confdir[512] = { 0 };
+#ifdef AFS_ID_TO_NAME
char username_copy[BUFSIZ];
- long viceId; /* AFS uid of user */
+#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';
- }
+ if (confdir[0] == '\0')
+ cm_GetConfigDir(confdir, sizeof(confdir));
- /*
- * Talk about DUMB! It turns out that there is a bug in
- * pr_Initialize -- even if you give a different cell name
- * to it, it still uses a connection to a previous AFS server
- * if one exists. The way to fix this is to change the
- * _filename_ argument to pr_Initialize - that forces it to
- * re-initialize the connection. We do this by adding and
- * removing a "/" on the end of the configuration directory name.
- */
+ StringCbCopyN( lastcell, sizeof(lastcell),
+ aserver->cell, sizeof(lastcell) - 1);
- if (lastcell[0] != '\0' && (strcmp(lastcell, aserver->cell) != 0)) {
- int i = strlen(confname);
- if (confname[i - 1] == '/') {
- confname[i - 1] = '\0';
- } else {
- confname[i] = '/';
- confname[i + 1] = '\0';
- }
+ if (!pr_Initialize (0, confdir, aserver->cell)) {
+ char sname[PR_MAXNAMELEN];
+ StringCbCopyN( sname, sizeof(sname),
+ username, sizeof(sname) - 1);
+ status = pr_SNameToId (sname, &viceId);
+ pr_End();
}
- strcpy(lastcell, aserver->cell);
-
- if (!pr_Initialize (0, confname, aserver->cell))
- status = pr_SNameToId (username, &viceId);
-
/*
* This is a crock, but it is Transarc's crock, so
* we have to play along in order to get the
#endif /* ALLOW_REGISTER */
{
#ifdef AFS_ID_TO_NAME
- strncpy(username_copy, username, BUFSIZ);
+ StringCbCopyN( username_copy, sizeof(username_copy),
+ username, sizeof(username_copy) - 1);
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);
+ StringCbCopyN( aclient->name, sizeof(aclient->name),
+ username, sizeof(aclient->name) - 1);
+ aclient->instance[0] = '\0';
+ StringCbCopyN( aclient->cell, sizeof(aclient->cell),
+ realm_of_user, sizeof(aclient->cell) - 1);
if (status = ktc_SetToken(aserver, atoken, aclient, 0))
return status;
-
- /*
- * In case you're wondering, we don't need to change the
- * filename here because we're still connecting to the
- * same cell -- we're just using a different authentication
- * level
- */
-
- if (status = pr_Initialize(1L, confname, aserver->cell, 0))
- return status;
- if (status = pr_CreateUser(username, &id))
+ if (status = pr_Initialize(1L, confdir, 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);
+ StringCbCopyN( username_copy, sizeof(username_copy),
+ username, sizeof(username_copy) - 1);
snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
#endif /* AFS_ID_TO_NAME */
}
}
+static void
+copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
+ krb5_error_code code;
+ krb5_ticket *ticket;
+ size_t len;
+
+ code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
+ if (code == 0) {
+ len = krb5_princ_realm(context, ticket->server)->length;
+ if (len > destlen - 1)
+ len = destlen - 1;
+
+ StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
+
+ pkrb5_free_ticket(context, ticket);
+ }
+}
+
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 */
char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
- char local_cell[MAXCELLCHARS+1];
- char Dmycell[MAXCELLCHARS+1];
+ char local_cell[CELL_MAXNAMELEN+1];
+ char Dmycell[CELL_MAXNAMELEN+1];
struct ktc_token atoken;
struct ktc_token btoken;
struct afsconf_cell ak_cellconfig; /* General information about the cell */
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;
- int i, retry = 0;
+ krb5_principal client_principal = NULL;
+ krb5_data * k5data = NULL;
+ unsigned int i, retry = 0;
CurrentState = 0;
memset(HostName, '\0', sizeof(HostName));
if (!pkrb5_init_context)
return 0;
+ memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
memset(RealmName, '\0', sizeof(RealmName));
memset(CellName, '\0', sizeof(CellName));
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])
+ StringCbCopyN( Dmycell, sizeof(Dmycell),
+ cell, sizeof(Dmycell) - 1);
+ 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))
if (code) goto skip_krb5_init;
}
- memset((char *)&increds, 0, sizeof(increds));
+ memset(&increds, 0, sizeof(increds));
code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
- if (code) {
- if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
+ if (code) {
+ if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
{
OutputDebugString("Principal Not Found for ccache\n");
}
goto skip_krb5_init;
}
- i = krb5_princ_realm(ctx, client_principal)->length;
- if (i > REALM_SZ-1)
- i = REALM_SZ-1;
- strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
- realm_of_user[i] = 0;
- try_krb5 = 1;
- skip_krb5_init:
-#ifdef USE_KRB4
- if ( !try_krb5 || !realm_of_user[0] ) {
- if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
- {
+ 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;
+ StringCbCopyN( realm_of_user, sizeof(realm_of_user),
+ krb5_princ_realm(ctx, client_principal)->data, i);
+ try_krb5 = 1;
+
+ skip_krb5_init:
+#ifdef USE_KRB4
+ if ( !try_krb5 || !realm_of_user[0] ) {
+ if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
+ {
goto cleanup;
- }
+ }
}
#else
- goto cleanup;
+ if (!try_krb5)
+ goto cleanup;
#endif
- strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
+ StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
+ afs_realm_of_cell(ctx, &ak_cellconfig),
+ sizeof(realm_of_cell) - 1);
if (strlen(service) == 0)
- strcpy(ServiceName, "afs");
+ StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
else
- strcpy(ServiceName, service);
+ StringCbCopyN( ServiceName, sizeof(ServiceName),
+ service, sizeof(ServiceName) - 1);
if (strlen(cell) == 0)
- strcpy(CellName, local_cell);
+ StringCbCopyN( CellName, sizeof(CellName),
+ local_cell, sizeof(CellName) - 1);
else
- strcpy(CellName, cell);
+ StringCbCopyN( CellName, sizeof(CellName),
+ cell, sizeof(CellName) - 1);
+ /* This is for Kerberos v4 only */
if (strlen(realm) == 0)
- strcpy(RealmName, realm_of_cell);
+ StringCbCopyN( RealmName, sizeof(RealmName),
+ realm_of_cell, sizeof(RealmName) - 1);
else
- strcpy(RealmName, realm);
+ StringCbCopyN( RealmName, sizeof(RealmName),
+ realm, sizeof(RealmName) - 1);
memset(&creds, '\0', sizeof(creds));
if ( try_krb5 ) {
int len;
+ code = KRB5KRB_ERR_GENERIC;
- /* First try service/cell@REALM */
- if (code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
- RealmName,
- ServiceName,
- CellName,
- 0))
- {
- goto cleanup;
- }
increds.client = client_principal;
increds.times.endtime = 0;
/* Ask for DES since that is what V4 understands */
increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
-
- if ( IsDebuggerPresent() ) {
- char * cname, *sname;
- pkrb5_unparse_name(ctx, increds.client, &cname);
- pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("Getting tickets for \"");
- OutputDebugString(cname);
- OutputDebugString("\" and service \"");
- OutputDebugString(sname);
- OutputDebugString("\"\n");
- pkrb5_free_unparsed_name(ctx,cname);
- pkrb5_free_unparsed_name(ctx,sname);
- }
-
- 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) {
- /* Or service@REALM */
- pkrb5_free_principal(ctx,increds.server);
+ /* If there was a specific realm we are supposed to try
+ * then use it
+ */
+ if (strlen(realm) != 0) {
+ /* service/cell@REALM */
increds.server = 0;
code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
- RealmName,
- ServiceName,
- 0);
-
+ (int)strlen(realm),
+ realm,
+ ServiceName,
+ CellName,
+ 0);
if ( IsDebuggerPresent() ) {
char * cname, *sname;
pkrb5_unparse_name(ctx, increds.client, &cname);
pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
- OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString("Getting tickets for \"");
OutputDebugString(cname);
OutputDebugString("\" and service \"");
OutputDebugString(sname);
if (!code)
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) &&
- 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),
- RealmName,
- ServiceName,
- CellName,
- 0);
+ if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+ 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,
+ (int)strlen(realm),
+ realm,
+ ServiceName,
+ 0);
+
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+ OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ }
+
+ if (!code)
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ }
+
+ if (code == 0) {
+ /* we have a local realm for the cell */
+ StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
+ realm, sizeof(realm_of_cell) - 1);
+ }
+ } else {
+ /* Otherwise, first try service/cell@CLIENT_REALM */
+ if (code = pkrb5_build_principal(ctx, &increds.server,
+ (int)strlen(realm_of_user),
+ realm_of_user,
+ ServiceName,
+ CellName,
+ 0))
+ {
+ goto cleanup;
+ }
if ( IsDebuggerPresent() ) {
char * cname, *sname;
pkrb5_unparse_name(ctx, increds.client, &cname);
pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
- OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString("Getting tickets for \"");
OutputDebugString(cname);
OutputDebugString("\" and service \"");
OutputDebugString(sname);
pkrb5_free_unparsed_name(ctx,sname);
}
- if (!code)
- code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ if (code == 0) {
+ /* The client's realm is a local realm for the cell.
+ * Save it so that later the pts registration will not
+ * be performed.
+ */
+ StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
+ realm_of_user, sizeof(realm_of_cell) - 1);
+ }
-
- if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5_ERR_HOST_REALM_UNKNOWN ||
code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
- code == KRB5KRB_AP_ERR_MSG_TYPE) {
- /* Or service@REALM_OF_CELL */
+ code == KRB5KRB_AP_ERR_MSG_TYPE) &&
+ strcmp(realm_of_user, realm_of_cell)) {
+ /* Then service/cell@CELL_REALM */
+ pkrb5_free_principal(ctx,increds.server);
+ increds.server = 0;
+ code = pkrb5_build_principal(ctx, &increds.server,
+ (int)strlen(realm_of_cell),
+ realm_of_cell,
+ ServiceName,
+ CellName,
+ 0);
+ if ( IsDebuggerPresent() ) {
+ char * cname, *sname;
+ pkrb5_unparse_name(ctx, increds.client, &cname);
+ pkrb5_unparse_name(ctx, increds.server, &sname);
+ OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
+ OutputDebugString("Trying again: getting tickets for \"");
+ OutputDebugString(cname);
+ OutputDebugString("\" and service \"");
+ OutputDebugString(sname);
+ OutputDebugString("\"\n");
+ pkrb5_free_unparsed_name(ctx,cname);
+ pkrb5_free_unparsed_name(ctx,sname);
+ }
+
+ if (!code)
+ code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+
+ if (!code && !strlen(realm_of_cell))
+ copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
+ }
+
+ if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
+ code == KRB5_ERR_HOST_REALM_UNKNOWN ||
+ code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
+ code == KRB5KRB_AP_ERR_MSG_TYPE) {
+ /* Finally service@CELL_REALM */
pkrb5_free_principal(ctx,increds.server);
increds.server = 0;
code = pkrb5_build_principal(ctx, &increds.server,
- strlen(RealmName),
- RealmName,
+ (int)strlen(realm_of_cell),
+ realm_of_cell,
ServiceName,
0);
if (!code)
code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
+ if (!code && !strlen(realm_of_cell))
+ copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
}
}
if (code) {
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"krb5_get_credentials returns: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
OutputDebugString(message);
}
try_krb5 = 0;
}
/* This code inserts the entire K5 ticket into the token
- * No need to perform a krb524 translation which is
+ * No need to perform a krb524 translation which is
* commented out in the code below
*/
if (KFW_use_krb524() ||
goto try_krb524d;
memset(&aserver, '\0', sizeof(aserver));
- strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
- strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
+ StringCbCopyN( aserver.name, sizeof(aserver.name),
+ ServiceName, sizeof(aserver.name) - 1);
+ StringCbCopyN( aserver.cell, sizeof(aserver.cell),
+ CellName, sizeof(aserver.cell) - 1);
memset(&atoken, '\0', sizeof(atoken));
atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
retry++;
goto retry_gettoken5;
}
- goto try_krb524d;
+ goto cleanup;
}
if (atoken.kvno == btoken.kvno &&
atoken.ticketLen == btoken.ticketLen &&
!memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
- !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
+ !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
{
/* Success - Nothing to do */
goto cleanup;
// * This structure was first set by the ktc_GetToken call when
// * we were comparing whether identical tokens already existed.
- len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
- strncpy(aclient.name, k5creds->client->data[0].data, len);
- aclient.name[len] = '\0';
+ len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
+ StringCbCopyN( aclient.name, sizeof(aclient.name),
+ k5creds->client->data[0].data, len);
if ( k5creds->client->length > 1 ) {
- char * p;
- strcat(aclient.name, ".");
- p = aclient.name + strlen(aclient.name);
- len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
- strncpy(p, k5creds->client->data[1].data, len);
- p[len] = '\0';
+ StringCbCat( aclient.name, sizeof(aclient.name), ".");
+ len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
+ StringCbCatN( aclient.name, sizeof(aclient.name),
+ k5creds->client->data[1].data, len);
}
aclient.instance[0] = '\0';
- strcpy(aclient.cell, realm_of_cell);
+ StringCbCopyN( aclient.cell, sizeof(aclient.cell),
+ realm_of_cell, sizeof(aclient.cell) - 1);
- len = min(k5creds->client->realm.length,strlen(realm_of_cell));
- if ( 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);
- strncpy(p, k5creds->client->realm.data, len);
- p[len] = '\0';
+ 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) */ ) {
+ StringCbCat( aclient.name, sizeof(aclient.name), "@");
+ len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
+ StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
}
- ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
- &aclient, &aserver, &atoken);
+ 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, sizeof(aclient.smbname));
- aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
+ StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
+ smbname, sizeof(aclient.smbname) - 1);
} else {
aclient.smbname[0] = '\0';
}
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
+ * convert using the krb524d running with the KDC
*/
code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
pkrb5_free_creds(ctx, k5creds);
if (code) {
if ( IsDebuggerPresent() ) {
char message[256];
- sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
+ StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
OutputDebugString(message);
}
try_krb5 = 0;
goto use_krb4;
}
+#endif /* USE_KRB524 */
} else {
use_krb4:
#ifdef USE_KRB4
}
memset(&aserver, '\0', sizeof(aserver));
- strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
- strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
+ StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
+ StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
memset(&atoken, '\0', sizeof(atoken));
atoken.kvno = creds.kvno;
if (atoken.kvno == btoken.kvno &&
atoken.ticketLen == btoken.ticketLen &&
!memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
- !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
+ !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
{
goto cleanup;
}
// * This structure was first set by the ktc_GetToken call when
// * we were comparing whether identical tokens already existed.
- strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
+ StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
if (creds.pinst[0])
{
strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
}
- strcpy(aclient.instance, "");
+ aclient.instance[0] = '\0';
- 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);
+ StringCbCopyN( aclient.cell, sizeof(aclient.cell),
+ CellName, sizeof(aclient.cell) - 1);
- ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
- &aclient, &aserver, &atoken);
+ 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, sizeof(aclient.smbname));
- aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
+ StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
+ smbname, sizeof(aclient.smbname) - 1);
} else {
aclient.smbname[0] = '\0';
}
pkrb5_cc_close(ctx, cc);
if (ctx && (ctx != alt_ctx))
pkrb5_free_context(ctx);
+ if (ak_cellconfig.linkedCell)
+ free(ak_cellconfig.linkedCell);
- return(rc? rc : code);
+ return(rc? rc : code);
}
/**************************************/
r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
if ( !r && realmlist && realmlist[0] ) {
- strcpy(krbrlm, realmlist[0]);
+ StringCbCopyN( krbrlm, sizeof(krbrlm),
+ realmlist[0], sizeof(krbrlm) - 1);
pkrb5_free_host_realm(ctx, realmlist);
}
/**************************************/
/* KFW_AFS_get_cellconfig(): */
/**************************************/
-int
+int
KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
{
int rc;
- char newcell[MAXCELLCHARS+1];
+ char newcell[CELL_MAXNAMELEN+1];
+ char linkedcell[CELL_MAXNAMELEN+1]="";
local_cell[0] = (char)0;
memset(cellconfig, 0, sizeof(*cellconfig));
if (strlen(cell) == 0)
strcpy(cell, local_cell);
- /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
- strcpy(cellconfig->name, cell);
-
- rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
-#ifdef AFS_AFSDB_ENV
+ rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
+ if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
+ rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
if (rc != 0) {
int ttl;
rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
}
-#endif
+
+ if (rc == 0) {
+ StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
+ newcell, sizeof(cellconfig->name) - 1);
+ if (linkedcell[0])
+ cellconfig->linkedCell = strdup(linkedcell);
+ }
return rc;
}
/**************************************/
/* get_cellconfig_callback(): */
/**************************************/
-static long
-get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
+static long
+get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
{
struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
cc->hostAddr[cc->numServers] = *addrp;
- strcpy(cc->hostName[cc->numServers], namep);
+ StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
+ namep, sizeof(cc->hostName[cc->numServers]) - 1);
cc->numServers++;
return(0);
}
KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
{
char message[256];
- const char *errText;
+ const char *errText;
- // Using AFS defines as error messages for now, until Transarc
- // gets back to me with "string" translations of each of these
- // const. defines.
+ // Using AFS defines as error messages for now, until Transarc
+ // gets back to me with "string" translations of each of these
+ // const. defines.
if (rc == KTC_ERROR)
errText = "KTC_ERROR";
else if (rc == KTC_TOOBIG)
else
errText = "Unknown error!";
- sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
+ StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
if ( IsDebuggerPresent() ) {
OutputDebugString(message);
return;
}
-static DWORD
+static DWORD
GetServiceStatus(
- LPSTR lpszMachineName,
+ LPSTR lpszMachineName,
LPSTR lpszServiceName,
- DWORD *lpdwCurrentState)
-{
- DWORD hr = NOERROR;
- SC_HANDLE schSCManager = NULL;
- SC_HANDLE schService = NULL;
- DWORD fdwDesiredAccess = 0;
- SERVICE_STATUS ssServiceStatus = {0};
- BOOL fRet = FALSE;
-
- *lpdwCurrentState = 0;
-
- fdwDesiredAccess = GENERIC_READ;
-
- schSCManager = OpenSCManager(lpszMachineName,
+ DWORD *lpdwCurrentState)
+{
+ DWORD hr = NOERROR;
+ SC_HANDLE schSCManager = NULL;
+ SC_HANDLE schService = NULL;
+ DWORD fdwDesiredAccess = 0;
+ SERVICE_STATUS ssServiceStatus = {0};
+ BOOL fRet = FALSE;
+
+ *lpdwCurrentState = 0;
+
+ fdwDesiredAccess = GENERIC_READ;
+
+ schSCManager = OpenSCManager(lpszMachineName,
NULL,
- fdwDesiredAccess);
-
- if(schSCManager == NULL)
- {
+ fdwDesiredAccess);
+
+ if(schSCManager == NULL)
+ {
hr = GetLastError();
- goto cleanup;
- }
-
+ goto cleanup;
+ }
+
schService = OpenService(schSCManager,
lpszServiceName,
- fdwDesiredAccess);
-
- if(schService == NULL)
- {
+ fdwDesiredAccess);
+
+ if(schService == NULL)
+ {
hr = GetLastError();
- goto cleanup;
- }
-
+ goto cleanup;
+ }
+
fRet = QueryServiceStatus(schService,
- &ssServiceStatus);
-
- if(fRet == FALSE)
- {
- hr = GetLastError();
- goto cleanup;
- }
-
- *lpdwCurrentState = ssServiceStatus.dwCurrentState;
-
-cleanup:
-
- CloseServiceHandle(schService);
- CloseServiceHandle(schSCManager);
-
- return(hr);
-}
+ &ssServiceStatus);
+
+ if(fRet == FALSE)
+ {
+ hr = GetLastError();
+ goto cleanup;
+ }
+
+ *lpdwCurrentState = ssServiceStatus.dwCurrentState;
+
+cleanup:
+
+ CloseServiceHandle(schService);
+ CloseServiceHandle(schSCManager);
+
+ return(hr);
+}
void
UnloadFuncs(
- FUNC_INFO fi[],
+ FUNC_INFO fi[],
HINSTANCE h
)
{
int
LoadFuncs(
- const char* dll_name,
- FUNC_INFO fi[],
+ const char* dll_name,
+ FUNC_INFO fi[],
HINSTANCE* ph, // [out, optional] - DLL handle
int* pindex, // [out, optional] - index of last func loaded (-1 if none)
int cleanup, // cleanup function pointers and unload on error
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(ctx, cellconfig); // do not free
- code = pkrb5_build_principal(ctx, &principal, strlen(realm),
+ code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
realm, PROBE_USERNAME, NULL, NULL);
if ( code ) goto cleanup;
}
password[PROBE_PASSWORD_LEN] = '\0';
- code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
- pname,
+ code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
+ pname,
password,
5,
0,
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 ) {
+ StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
+ 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;
+
+ StringCbCat( filename, sizeof(filename), "\\");
+ StringCbCat( filename, sizeof(filename), szLogonId);
+
+ StringCbCat( cachename, sizeof(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;
+
+ StringCbCat( cachename, sizeof(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;
+}
+