KFW_initialize(void)
{
static int inited = 0;
+
if ( !inited ) {
- inited = 1;
- LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
- LoadFuncs(KRB4_DLL, k4_fi, &hKrb5, 0, 1, 0, 0);
- LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
- LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
+ char mutexName[MAX_PATH];
+ HANDLE hMutex = NULL;
+
+ sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
+
+ hMutex = CreateMutex( NULL, TRUE, mutexName );
+ if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+ if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
+ return;
+ }
+ }
+ 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(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
#ifdef USE_MS2MIT
- LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
+ LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
#endif /* USE_MS2MIT */
- LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
- LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
- LoadFuncs(AFSTOKENS_DLL, afst_fi, &hAfsTokens, 0, 1, 0, 0);
- LoadFuncs(AFSCONF_DLL, afsc_fi, &hAfsConf, 0, 1, 0, 0);
- LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
- LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
-
- if ( KFW_is_available() ) {
- char rootcell[MAXCELLCHARS+1];
+ LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
+ LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
+ LoadFuncs(AFSTOKENS_DLL, afst_fi, &hAfsTokens, 0, 1, 0, 0);
+ LoadFuncs(AFSCONF_DLL, afsc_fi, &hAfsConf, 0, 1, 0, 0);
+ LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
+ LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
+
+ if ( KFW_is_available() ) {
+ char rootcell[MAXCELLCHARS+1];
#ifdef USE_MS2MIT
- KFW_import_windows_lsa();
+ KFW_import_windows_lsa();
#endif /* USE_MS2MIT */
- KFW_import_ccache_data();
- KFW_AFS_renew_expiring_credentials();
+ KFW_import_ccache_data();
+ KFW_AFS_renew_expiring_tokens();
- /* WIN32 NOTE: no way to get max chars */
- if (!pcm_GetRootCellName(rootcell))
- KFW_AFS_renew_token_for_cell(rootcell);
+ /* WIN32 NOTE: no way to get max chars */
+ if (!pcm_GetRootCellName(rootcell))
+ KFW_AFS_renew_token_for_cell(rootcell);
+ }
}
+ ReleaseMutex(hMutex);
+ CloseHandle(hMutex);
}
}
hSecur32 &&
#endif /* USE_MS2MIT */
hKrb524 &&
- hProfile && hAfsTokens && hAfsConf )
+ hProfile && hAfsTokens && hAfsConf && hLeash && hCCAPI )
return TRUE;
return FALSE;
}
char * ccname = 0;
krb5_error_code code;
+ if (!pkrb5_init_context)
+ return 0;
+
if ( alt_ctx ) {
ctx = alt_ctx;
} else {
char cell[128]="";
int i;
+ if (!pkrb5_init_context)
+ return;
+
if ( !MSLSA_IsKerberosLogon() )
return;
int cell_count=0;
afsconf_cell cellconfig;
+ if (!pkrb5_init_context)
+ return 0;
+
if ( IsDebuggerPresent() ) {
OutputDebugString("KFW_AFS_get_cred for token ");
OutputDebugString(username);
int count;
char ** principals = NULL;
+ if (!pkrb5_init_context)
+ return 0;
+
if ( IsDebuggerPresent() ) {
OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
OutputDebugString(cell);
}
int
-KFW_AFS_renew_expiring_credentials(void)
+KFW_AFS_renew_expiring_tokens(void)
{
krb5_error_code code = 0;
krb5_context ctx = 0;
char local_cell[MAXCELLCHARS+1]="";
afsconf_cell cellconfig;
+ if (!pkrb5_init_context)
+ return 0;
+
if ( pcc_next == NULL ) // nothing to do
return 0;
if ( IsDebuggerPresent() ) {
- OutputDebugString("KFW_AFS_renew_expiring_credentials\n");
+ OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
}
code = pkrb5_init_context(&ctx);
int count;
char ** principals = NULL;
+ if (!pkrb5_init_context)
+ return 0;
+
if ( IsDebuggerPresent() ) {
OutputDebugString("KFW_AFS_renew_token_for_cell:");
OutputDebugString(cell);
if ( count > 0 ) {
krb5_principal princ = 0;
krb5_principal service = 0;
+#ifdef COMMENT
krb5_creds mcreds, creds;
+#endif /* COMMENT */
krb5_ccache cc = 0;
const char * realm = NULL;
afsconf_cell cellconfig;
OutputDebugString("\n");
}
+#ifdef COMMENT
+ /* krb5_cc_remove_cred() is not implemented
+ * for a single cred
+ */
code = pkrb5_build_principal(ctx, &service, strlen(realm),
realm, "afs", cell, NULL);
if (!code) {
pkrb5_free_principal(ctx, creds.server);
}
}
+#endif /* COMMENT */
+
code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime());
if ( IsDebuggerPresent() ) {
char message[256];
krb5_creds my_creds;
krb5_data *realm = 0;
+ if (!pkrb5_init_context)
+ return 0;
+
memset(&my_creds, 0, sizeof(krb5_creds));
if ( alt_ctx ) {
krb5_ccache cc;
krb5_error_code code;
+ if (!pkrb5_init_context)
+ return 0;
+
if (alt_ctx)
{
ctx = alt_ctx;
return(0);
}
+
+#define TKTLIFENUMFIXED 64
+#define TKTLIFEMINFIXED 0x80
+#define TKTLIFEMAXFIXED 0xBF
+#define TKTLIFENOEXPIRE 0xFF
+#define MAXTKTLIFETIME (30*24*3600) /* 30 days */
+#ifndef NEVERDATE
+#define NEVERDATE ((unsigned long)0x7fffffffL)
+#endif
+
+static int no_long_lifetimes = 0;
+typedef unsigned long u_int32_t;
+
+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 */
+
+
+/*
+ * KFW_KRB4_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.
+ */
+static u_int32_t
+KFW_KRB4_life_to_time(u_int32_t start, int life_)
+{
+ unsigned char life = (unsigned char) life_;
+
+ if (no_long_lifetimes) return start + life*5*60;
+
+ if (life == TKTLIFENOEXPIRE) return NEVERDATE;
+ if (life < TKTLIFEMINFIXED) return start + life*5*60;
+ if (life > TKTLIFEMAXFIXED) return start + MAXTKTLIFETIME;
+ return start + tkt_lifetimes[life - TKTLIFEMINFIXED];
+}
+
+/*
+ * KFW_KRB4_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*5 minutes. First, the
+ * special case of (end == NEVERDATE) 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.
+ */
+static int
+KFW_KRB4_time_to_life(u_int32_t start, u_int32_t end)
+{
+ int i;
+ long lifetime = end - start;
+
+ if (no_long_lifetimes) return (lifetime + 5*60 - 1)/(5*60);
+
+ if (end >= NEVERDATE) return TKTLIFENOEXPIRE;
+ if (lifetime > MAXTKTLIFETIME || lifetime <= 0) return 0;
+ if (lifetime < tkt_lifetimes[0]) return (lifetime + 5*60 - 1)/(5*60);
+ for (i=0; i<TKTLIFENUMFIXED; i++) {
+ if (lifetime <= tkt_lifetimes[i]) {
+ return i+TKTLIFEMINFIXED;
+ }
+ }
+ return 0;
+}
+
+
int
KFW_AFS_klog(
krb5_context alt_ctx,
return(-2);
}
+ if (!pkrb5_init_context)
+ return 0;
+
memset(RealmName, '\0', sizeof(RealmName));
memset(CellName, '\0', sizeof(CellName));
memset(ServiceName, '\0', sizeof(ServiceName));
char * cname, *sname;
pkrb5_unparse_name(ctx, increds.client, &cname);
pkrb5_unparse_name(ctx, increds.server, &sname);
- OutputDebugString("Getting credentials for \"");
+ OutputDebugString("Getting tickets for \"");
OutputDebugString(cname);
OutputDebugString("\" and service \"");
OutputDebugString(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 credentials for \"");
+ OutputDebugString("Trying again: getting tickets for \"");
OutputDebugString(cname);
OutputDebugString("\" and service \"");
OutputDebugString(sname);
memset(&atoken, '\0', sizeof(atoken));
atoken.kvno = creds.kvno;
atoken.startTime = creds.issue_date;
- atoken.endTime = creds.issue_date + (creds.lifetime * 300);
+ atoken.endTime = creds.issue_date + KFW_KRB4_life_to_time(0,creds.lifetime);
memcpy(&atoken.sessionKey, creds.session, 8);
atoken.ticketLen = creds.ticket_st.length;
memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
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);
struct ktc_principal aserver;
struct ktc_principal aclient;
struct ktc_token atoken;
- krb5_context ctx;
+ krb5_context ctx = 0;
krb5_timestamp now = 0;
krb5_error_code code;
int serverReachable = 0;
#endif /* USE_FSPROBE */
DWORD CurrentState;
char HostName[64];
+ int use_kfw = KFW_is_available();
CurrentState = 0;
memset(HostName, '\0', sizeof(HostName));
return;
}
- if ( KFW_is_available() ) {
+ if (!pkrb5_init_context)
+ return;
+
+ if ( use_kfw ) {
code = pkrb5_init_context(&ctx);
if ( code ) goto cleanup;
}
rc = pktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
- if ( KFW_is_available() ) {
+ if ( use_kfw ) {
code = pkrb5_timeofday(ctx, &now);
if ( code )
now = 0;
if (!rc && (now < atoken.endTime))
goto cleanup;
+
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d now = %ul endTime = %ul\n",
+ rc, now, atoken.endTime);
+ OutputDebugString(message);
+ }
} else {
SYSTEMTIME stNow;
FILETIME ftNow;
if (!rc && (llNow < llExpires))
goto cleanup;
+
+ if ( IsDebuggerPresent() ) {
+ char message[256];
+ sprintf(message,"KFW_AFS_klog() returns: %d now = %ul endTime = %ul\n",
+ rc, llNow, llExpires);
+ OutputDebugString(message);
+ }
}
#ifdef USE_FSPROBE
serverReachable = cellPing(NULL);
#else
- if ( KFW_is_available() ) {
+ if ( use_kfw ) {
// If we can't use the FSProbe interface we can attempt to forge
// a kinit and if we can back an invalid user error we know the
// kdc is at least reachable
serverReachable = 1;
}
#endif
- if ( !serverReachable )
+ if ( !serverReachable ) {
+ if ( IsDebuggerPresent() )
+ OutputDebugString("Server Unreachable\n");
goto cleanup;
+ }
+
+ if ( IsDebuggerPresent() )
+ OutputDebugString("Server Reachable\n");
- if ( KFW_is_available() ) {
+ if ( use_kfw ) {
#ifdef USE_MS2MIT
KFW_import_windows_lsa();
#endif /* USE_MS2MIT */
- KFW_AFS_renew_expiring_credentials();
+ KFW_AFS_renew_expiring_tokens();
KFW_AFS_renew_token_for_cell(rootcell);
rc = pktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
GlobalFree(rootcell);
#ifndef USE_FSPROBE
+ if (KFW_is_available()) {
if ( pname )
pkrb5_free_unparsed_name(ctx,pname);
if ( principal )
#endif /* USE_FSPROBE */
if (ctx)
pkrb5_free_context(ctx);
+ }
return;
}
if (code == ERROR_INSUFFICIENT_BUFFER) {
pIpAddrTable = malloc(dwSize);
code = GetIpAddrTable(pIpAddrTable, &dwSize, 0);
- for ( index=0; index < pIpAddrTable->dwNumEntries; index++ ) {
- if (pIpAddrTable->table[index].dwAddr != 0)
- validAddrs++;
+ if ( code == NO_ERROR ) {
+ for ( index=0; index < pIpAddrTable->dwNumEntries; index++ ) {
+ if (pIpAddrTable->table[index].dwAddr != 0)
+ validAddrs++;
+ }
}
free(pIpAddrTable);
}
IpAddrChangeMonitor(void * hWnd)
{
#ifdef USE_OVERLAPPED
- HANDLE Handle = INVALID_HANDLE_VALUE;
+ HANDLE Handle = INVALID_HANDLE_VALUE; /* Do Not Close This Handle */
OVERLAPPED Ovlap;
#endif /* USE_OVERLAPPED */
DWORD Result;
DWORD prevNumOfAddrs = GetNumOfIpAddrs();
DWORD NumOfAddrs;
+ char message[256];
if ( !hWnd )
return;
Result = NotifyAddrChange(&Handle,&Ovlap);
if (Result != ERROR_IO_PENDING)
{
- printf("NotifyAddrChange() failed with error %d \n", Result);
+ if ( IsDebuggerPresent() ) {
+ sprintf(message, "NotifyAddrChange() failed with error %d \n", Result);
+ OutputDebugString(message);
+ }
break;
}
- if ((Result = WaitForSingleObject(Handle,INFINITE)) == WAIT_FAILED)
+ if ((Result = WaitForSingleObject(Handle,INFINITE)) != WAIT_OBJECT_0)
{
- printf("WaitForSingleObject() failed with error %d\n",
- GetLastError());
+ if ( IsDebuggerPresent() ) {
+ sprintf(message, "WaitForSingleObject() failed with error %d\n",
+ GetLastError());
+ OutputDebugString(message);
+ }
continue;
}
if (GetOverlappedResult(Handle, &Ovlap,
&DataTransfered, TRUE) == 0)
{
- printf("GetOverlapped result failed %d \n",
- GetLastError());
+ if ( IsDebuggerPresent() ) {
+ sprintf(message, "GetOverlapped result failed %d \n",
+ GetLastError());
+ OutputDebugString(message);
+ }
break;
}
-
#else
Result = NotifyAddrChange(NULL,NULL);
+ if (Result != NO_ERROR)
+ {
+ if ( IsDebuggerPresent() ) {
+ sprintf(message, "NotifyAddrChange() failed with error %d \n", Result);
+ OutputDebugString(message);
+ }
+ break;
+ }
#endif
NumOfAddrs = GetNumOfIpAddrs();
+
+ if ( IsDebuggerPresent() ) {
+ sprintf(message,"IPAddrChangeMonitor() NumOfAddrs: now %d was %d\n",
+ NumOfAddrs, prevNumOfAddrs);
+ OutputDebugString(message);
+ }
+
if ( NumOfAddrs != prevNumOfAddrs ) {
// Give AFS Client Service a chance to notice and die
// Or for network services to startup
}
prevNumOfAddrs = NumOfAddrs;
}
-
-#ifdef USE_OVERLAPPED
- if (Handle != INVALID_HANDLE_VALUE)
- CloseHandle(Handle);
-#endif
}