diff options
Diffstat (limited to 'src/windows/leashdll')
27 files changed, 10295 insertions, 0 deletions
diff --git a/src/windows/leashdll/AFSroutines.c b/src/windows/leashdll/AFSroutines.c new file mode 100644 index 000000000000..f04ab297920a --- /dev/null +++ b/src/windows/leashdll/AFSroutines.c @@ -0,0 +1,833 @@ +//* Module name: AFSroutines.c + +#include <windows.h> +#include <winsock2.h> +#include <stdio.h> +#include <time.h> + +/* Private Include files */ +#include <conf.h> +#include <leasherr.h> +#include "leashdll.h" +#include <leashwin.h> + +#ifndef NO_AFS +#include <afs/stds.h> +#include <afs/auth.h> +#include <afs/krb.h> +#include <afs/cellconfig.h> +#endif +#include "leash-int.h" + +#define MAXCELLCHARS 64 +#define MAXHOSTCHARS 64 +#define MAXHOSTSPERCELL 8 +#define TRANSARCAFSDAEMON "TransarcAFSDaemon" +typedef struct { + char name[MAXCELLCHARS]; + short numServers; + short flags; + struct sockaddr_in hostAddr[MAXHOSTSPERCELL]; + char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS]; + char *linkedCell; +} afsconf_cell; + +DWORD AfsOnLine = 1; +extern DWORD AfsAvailable; + +int not_an_API_LeashAFSGetToken(TICKETINFO * ticketinfo, TicketList** ticketList, char * kprinc); +DWORD GetServiceStatus(LPSTR lpszMachineName, LPSTR lpszServiceName, DWORD *lpdwCurrentState); +BOOL SetAfsStatus(DWORD AfsStatus); +BOOL GetAfsStatus(DWORD *AfsStatus); +void Leash_afs_error(LONG rc, LPCSTR FailedFunctionName); + +static char *afs_realm_of_cell(afsconf_cell *); +static long get_cellconfig_callback(void *, struct sockaddr_in *, char *); +static int get_cellconfig(char *, afsconf_cell *, char *); + +/**************************************/ +/* LeashAFSdestroyToken(): */ +/**************************************/ +int +Leash_afs_unlog( + void + ) +{ +#ifdef NO_AFS + return(0); +#else + long rc; + char HostName[64]; + DWORD CurrentState; + + if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine) + return(0); + + CurrentState = 0; + memset(HostName, '\0', sizeof(HostName)); + gethostname(HostName, sizeof(HostName)); + if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) + return(0); + if (CurrentState != SERVICE_RUNNING) + return(0); + + rc = ktc_ForgetAllTokens(); + + return(0); +#endif +} + + +int +not_an_API_LeashAFSGetToken( + TICKETINFO * ticketinfo, + TicketList** ticketList, + char * kerberosPrincipal + ) +{ +#ifdef NO_AFS + return(0); +#else + struct ktc_principal aserver; + struct ktc_principal aclient; + struct ktc_token atoken; + int EndMonth; + int EndDay; + int cellNum; + int BreakAtEnd; + char UserName[64]; + char CellName[64]; + char ServiceName[64]; + char InstanceName[64]; + char EndTime[16]; + char Buffer[256]; + char Months[12][4] = {"Jan\0", "Feb\0", "Mar\0", "Apr\0", "May\0", "Jun\0", "Jul\0", "Aug\0", "Sep\0", "Oct\0", "Nov\0", "Dec\0"}; + char TokenStatus[16]; + time_t CurrentTime; + struct tm *newtime; + DWORD CurrentState; + DWORD rc; + char HostName[64]; + + + TicketList* list = NULL; + if ( ticketinfo ) { + ticketinfo->btickets = NO_TICKETS; + ticketinfo->principal[0] = '\0'; + } + if ( !kerberosPrincipal ) + kerberosPrincipal = ""; + + if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine) + return(0); + + CurrentState = 0; + memset(HostName, '\0', sizeof(HostName)); + gethostname(HostName, sizeof(HostName)); + if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) + return(0); + if (CurrentState != SERVICE_RUNNING) + return(0); + + BreakAtEnd = 0; + cellNum = 0; + while (1) + { + if (rc = ktc_ListTokens(cellNum, &cellNum, &aserver)) + { + if (rc != KTC_NOENT) + return(0); + + if (BreakAtEnd == 1) + break; + } + BreakAtEnd = 1; + memset(&atoken, '\0', sizeof(atoken)); + if (rc = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient)) + { + if (rc == KTC_ERROR) + return(0); + + continue; + } + + if (!list) + { + list = (TicketList*) calloc(1, sizeof(TicketList)); + (*ticketList) = list; + } + else + { + list->next = (struct TicketList*) calloc(1, sizeof(TicketList)); + list = (TicketList*) list->next; + } + + CurrentTime = time(NULL); + + newtime = localtime(&atoken.endTime); + + memset(UserName, '\0', sizeof(UserName)); + strcpy(UserName, aclient.name); + + memset(CellName, '\0', sizeof(CellName)); + strcpy(CellName, aclient.cell); + + memset(InstanceName, '\0', sizeof(InstanceName)); + strcpy(InstanceName, aclient.instance); + + memset(ServiceName, '\0', sizeof(ServiceName)); + strcpy(ServiceName, aserver.name); + + memset(TokenStatus, '\0', sizeof(TokenStatus)); + + EndDay = newtime->tm_mday; + + EndMonth = newtime->tm_mon + 1;; + + sprintf(EndTime, "%02d:%02d:%02d", newtime->tm_hour, newtime->tm_min, newtime->tm_sec); + + sprintf(Buffer," %s %02d %s %s%s%s@%s %s", + Months[EndMonth - 1], EndDay, EndTime, + UserName, + InstanceName[0] ? "." : "", + InstanceName, + CellName, + TokenStatus); + + list->theTicket = (char*) calloc(1, sizeof(Buffer)); + if (!list->theTicket) + { +#ifdef USE_MESSAGE_BOX + MessageBox(NULL, "Memory Error", "Error", MB_OK); +#endif /* USE_MESSAGE_BOX */ + return ENOMEM; + } + + strcpy(list->theTicket, Buffer); + list->name = strdup(aclient.name); + list->inst = aclient.instance[0] ? strdup(aclient.instance) : NULL; + list->realm = strdup(aclient.cell); + list->encTypes = NULL; + list->addrCount = 0; + list->addrList = NULL; + + if ( ticketinfo ) { + sprintf(Buffer,"%s@%s",UserName,CellName); + if (!ticketinfo->principal[0] || !stricmp(Buffer,kerberosPrincipal)) { + strcpy(ticketinfo->principal, Buffer); + ticketinfo->issue_date = 0; + ticketinfo->lifetime = atoken.endTime; + ticketinfo->renew_till = 0; + + _tzset(); + if ( ticketinfo->lifetime - time(0) <= 0L ) + ticketinfo->btickets = EXPD_TICKETS; + else + ticketinfo->btickets = GOOD_TICKETS; + } + } + } + return(0); +#endif +} + +static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client"; + +static int +use_krb524(void) +{ + HKEY parmKey; + DWORD code, len; + DWORD use524 = 0; + + code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName, + 0, KEY_QUERY_VALUE, &parmKey); + if (code == ERROR_SUCCESS) { + len = sizeof(use524); + code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, + (BYTE *) &use524, &len); + RegCloseKey(parmKey); + } + if (code != ERROR_SUCCESS) { + code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName, + 0, KEY_QUERY_VALUE, &parmKey); + if (code == ERROR_SUCCESS) { + len = sizeof(use524); + code = RegQueryValueEx(parmKey, "Use524", NULL, NULL, + (BYTE *) &use524, &len); + RegCloseKey (parmKey); + } + } + return use524; +} + + + +int +Leash_afs_klog( + char *service, + char *cell, + char *realm, + int LifeTime + ) +{ +/////#ifdef NO_AFS +#if defined(NO_AFS) || defined(NO_KRB4) + return(0); +#else + long rc; +////This is defined in krb.h: + CREDENTIALS creds; + KTEXT_ST ticket; + 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]; + struct ktc_token atoken; + struct ktc_token btoken; + afsconf_cell ak_cellconfig; /* General information about the cell */ + char RealmName[128]; + char CellName[128]; + char ServiceName[128]; + DWORD CurrentState; + char HostName[64]; + BOOL try_krb5 = 0; + int retry = 0; + int len; +#ifndef NO_KRB5 + krb5_context context = 0; + krb5_ccache _krb425_ccache = 0; + krb5_creds increds; + krb5_creds * k5creds = 0; + krb5_error_code r; + krb5_principal client_principal = 0; + krb5_flags flags = 0; +#endif /* NO_KRB5 */ + + if (!AfsAvailable || GetAfsStatus(&AfsOnLine) && !AfsOnLine) + return(0); + + if ( !realm ) realm = ""; + if ( !cell ) cell = ""; + if ( !service ) service = ""; + + CurrentState = 0; + memset(HostName, '\0', sizeof(HostName)); + gethostname(HostName, sizeof(HostName)); + if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) + return(0); + if (CurrentState != SERVICE_RUNNING) + return(0); + + 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)); + memset(Dmycell, '\0', sizeof(Dmycell)); + + // NULL or empty cell returns information on local cell + if (cell && cell[0]) + strcpy(Dmycell, cell); + rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell); + if (rc && cell && cell[0]) { + memset(Dmycell, '\0', sizeof(Dmycell)); + rc = get_cellconfig(Dmycell, &ak_cellconfig, local_cell); + } + if (rc) + return(rc); + +#ifndef NO_KRB5 + if (!(r = Leash_krb5_initialize(&context, &_krb425_ccache))) { + int i; + + memset((char *)&increds, 0, sizeof(increds)); + + (*pkrb5_cc_get_principal)(context, _krb425_ccache, &client_principal); + i = krb5_princ_realm(context, client_principal)->length; + if (i > REALM_SZ-1) + i = REALM_SZ-1; + strncpy(realm_of_user,krb5_princ_realm(context, client_principal)->data,i); + realm_of_user[i] = 0; + try_krb5 = 1; + } +#endif /* NO_KRB5 */ + +#ifndef NO_KRB4 + if ( !try_krb5 || !realm_of_user[0] ) { + if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS) + { + return(rc); + } + } +#endif + strcpy(realm_of_cell, afs_realm_of_cell(&ak_cellconfig)); + + if (strlen(service) == 0) + strcpy(ServiceName, "afs"); + else + strcpy(ServiceName, service); + + if (strlen(cell) == 0) + strcpy(CellName, local_cell); + else + strcpy(CellName, cell); + + if (strlen(realm) == 0) + strcpy(RealmName, realm_of_cell); + else + strcpy(RealmName, realm); + + memset(&creds, '\0', sizeof(creds)); + +#ifndef NO_KRB5 + if ( try_krb5 ) { + /* First try Service/Cell@REALM */ + if (r = (*pkrb5_build_principal)(context, &increds.server, + strlen(RealmName), + RealmName, + ServiceName, + CellName, + 0)) + { + try_krb5 = 0; + goto use_krb4; + } + + increds.client = client_principal; + increds.times.endtime = 0; + /* Ask for DES since that is what V4 understands */ + increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + +#ifdef KRB5_TC_NOTICKET + flags = 0; + r = pkrb5_cc_set_flags(context, _krb425_ccache, flags); +#endif + if (r == 0) + r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds); + if (r == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || + r == KRB5KRB_ERR_GENERIC /* Heimdal */) { + /* Next try Service@REALM */ + pkrb5_free_principal(context, increds.server); + r = pkrb5_build_principal(context, &increds.server, + strlen(RealmName), + RealmName, + ServiceName, + 0); + if (r == 0) + r = pkrb5_get_credentials(context, 0, _krb425_ccache, &increds, &k5creds); + } + + pkrb5_free_principal(context, increds.server); + pkrb5_free_principal(context, client_principal); +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; + pkrb5_cc_set_flags(context, _krb425_ccache, flags); +#endif + (void) pkrb5_cc_close(context, _krb425_ccache); + _krb425_ccache = 0; + + if (r || k5creds == 0) { + pkrb5_free_context(context); + try_krb5 = 0; + goto use_krb4; + } + + /* This code inserts the entire K5 ticket into the token + * No need to perform a krb524 translation which is + * commented out in the code below + */ + if ( use_krb524() || k5creds->ticket.length > MAXKTCTICKETLEN ) + goto try_krb524d; + + memset(&aserver, '\0', sizeof(aserver)); + strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1); + strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1); + + memset(&atoken, '\0', sizeof(atoken)); + atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; + atoken.startTime = k5creds->times.starttime; + atoken.endTime = k5creds->times.endtime; + memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length); + atoken.ticketLen = k5creds->ticket.length; + memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen); + + retry_gettoken5: + rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient); + if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) { + if ( rc == KTC_NOCM && retry < 20 ) { + Sleep(500); + retry++; + goto retry_gettoken5; + } + goto try_krb524d; + } + + if (atoken.kvno == btoken.kvno && + atoken.ticketLen == btoken.ticketLen && + !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) && + !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) + { + /* Success */ + pkrb5_free_creds(context, k5creds); + pkrb5_free_context(context); + return(0); + } + + // * Reset the "aclient" structure before we call ktc_SetToken. + // * 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'; + + 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'; + } + aclient.instance[0] = '\0'; + + strcpy(aclient.cell, realm_of_cell); + + len = min(k5creds->client->realm.length,strlen(realm_of_cell)); + if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) { + 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'; + } + + rc = ktc_SetToken(&aserver, &atoken, &aclient, 0); + if (!rc) { + /* Success */ + pkrb5_free_creds(context, k5creds); + pkrb5_free_context(context); + return(0); + } + + try_krb524d: + /* This requires krb524d to be running with the KDC */ + r = pkrb524_convert_creds_kdc(context, k5creds, &creds); + pkrb5_free_creds(context, k5creds); + pkrb5_free_context(context); + if (r) { + try_krb5 = 0; + goto use_krb4; + } + rc = KSUCCESS; + } else +#endif /* NO_KRB5 */ + { + use_krb4: + rc = KFAILURE; + } + if (rc != KSUCCESS) + { + return(rc); + } + + memset(&aserver, '\0', sizeof(aserver)); + strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1); + strncpy(aserver.cell, CellName, MAXKTCNAMELEN - 1); + + memset(&atoken, '\0', sizeof(atoken)); + atoken.kvno = creds.kvno; + atoken.startTime = creds.issue_date; + atoken.endTime = (*pkrb_life_to_time)(creds.issue_date,creds.lifetime); + memcpy(&atoken.sessionKey, creds.session, 8); + atoken.ticketLen = creds.ticket_st.length; + memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen); + + if (!(rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient)) && + atoken.kvno == btoken.kvno && + atoken.ticketLen == btoken.ticketLen && + !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) && + !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen)) + { + return(0); + } + + // * Reset the "aclient" structure before we call ktc_SetToken. + // * 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); + aclient.name[MAXKTCNAMELEN - 1] = '\0'; + if (creds.pinst[0]) + { + strncat(aclient.name, ".", MAXKTCNAMELEN - 1 - strlen(aclient.name)); + aclient.name[MAXKTCNAMELEN - 1] = '\0'; + strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1 - strlen(aclient.name)); + aclient.name[MAXKTCNAMELEN - 1] = '\0'; + } + strcpy(aclient.instance, ""); + + if ( strcmp(realm_of_cell, creds.realm) ) + { + strncat(aclient.name, "@", MAXKTCNAMELEN - 1 - strlen(aclient.name)); + aclient.name[MAXKTCNAMELEN - 1] = '\0'; + strncat(aclient.name, creds.realm, MAXKTCNAMELEN - 1 - strlen(aclient.name)); + aclient.name[MAXKTCNAMELEN - 1] = '\0'; + } + aclient.name[MAXKTCNAMELEN-1] = '\0'; + + strcpy(aclient.cell, CellName); + + // * NOTE: On WIN32, the order of SetToken params changed... + // * to ktc_SetToken(&aserver, &aclient, &atoken, 0) + // * from ktc_SetToken(&aserver, &atoken, &aclient, 0) on Unix... + // * The afscompat ktc_SetToken provides the Unix order + + if (rc = ktc_SetToken(&aserver, &atoken, &aclient, 0)) + { + Leash_afs_error(rc, "ktc_SetToken()"); + return(rc); + } + + return(0); +#endif +} + +/**************************************/ +/* afs_realm_of_cell(): */ +/**************************************/ +static char *afs_realm_of_cell(afsconf_cell *cellconfig) +{ +#ifdef NO_AFS + return(0); +#else + char krbhst[MAX_HSTNM]=""; + static char krbrlm[REALM_SZ+1]=""; +#ifndef NO_KRB5 + krb5_context ctx = 0; + char ** realmlist=NULL; + krb5_error_code r; +#endif /* NO_KRB5 */ + + if (!cellconfig) + return 0; + +#ifndef NO_KRB5 + if ( pkrb5_init_context ) { + r = pkrb5_init_context(&ctx); + if ( !r ) + r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist); + if ( !r && realmlist && realmlist[0] ) { + strcpy(krbrlm, realmlist[0]); + pkrb5_free_host_realm(ctx, realmlist); + } + if (ctx) + pkrb5_free_context(ctx); + } +#endif /* NO_KRB5 */ + + if ( !krbrlm[0] ) + { + char *s = krbrlm; + char *t = cellconfig->name; + int c; + + while (c = *t++) + { + if (islower(c)) c=toupper(c); + *s++ = c; + } + *s++ = 0; + } + return(krbrlm); +#endif +} + +/**************************************/ +/* get_cellconfig(): */ +/**************************************/ +static int get_cellconfig(char *cell, afsconf_cell *cellconfig, char *local_cell) +{ +#ifdef NO_AFS + return(0); +#else + int rc; + + local_cell[0] = (char)0; + memset(cellconfig, 0, sizeof(*cellconfig)); + + /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */ + if (rc = cm_GetRootCellName(local_cell)) + { + return(rc); + } + + if (strlen(cell) == 0) + strcpy(cell, local_cell); + + /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */ + strcpy(cellconfig->name, cell); + + return cm_SearchCell(cell, get_cellconfig_callback, NULL, (void*)cellconfig); +#endif +} + +/**************************************/ +/* get_cellconfig_callback(): */ +/**************************************/ +static long get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep) +{ +#ifdef NO_AFS + return(0); +#else + afsconf_cell *cc = (afsconf_cell *)cellconfig; + + cc->hostAddr[cc->numServers] = *addrp; + strcpy(cc->hostName[cc->numServers], namep); + cc->numServers++; + return(0); +#endif +} + + +/**************************************/ +/* Leash_afs_error(): */ +/**************************************/ +void +Leash_afs_error(LONG rc, LPCSTR FailedFunctionName) +{ +#ifdef NO_AFS + return; +#else +#ifdef USE_MESSAGE_BOX + char message[256]; + 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. + if (rc == KTC_ERROR) + errText = "KTC_ERROR"; + else if (rc == KTC_TOOBIG) + errText = "KTC_TOOBIG"; + else if (rc == KTC_INVAL) + errText = "KTC_INVAL"; + else if (rc == KTC_NOENT) + errText = "KTC_NOENT"; + else if (rc == KTC_PIOCTLFAIL) + errText = "KTC_PIOCTLFAIL"; + else if (rc == KTC_NOPIOCTL) + errText = "KTC_NOPIOCTL"; + else if (rc == KTC_NOCELL) + errText = "KTC_NOCELL"; + else if (rc == KTC_NOCM) + errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!"; + else + errText = "Unknown error!"; + + sprintf(message, "%s\n(%s failed)", errText, FailedFunctionName); + MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND); +#endif /* USE_MESSAGE_BOX */ + return; + +#endif +} + +DWORD GetServiceStatus( + LPSTR lpszMachineName, + LPSTR lpszServiceName, + DWORD *lpdwCurrentState) +{ +#ifdef NO_AFS + return(NOERROR); +#else + DWORD hr = NOERROR; + SC_HANDLE schSCManager = NULL; + SC_HANDLE schService = NULL; + DWORD fdwDesiredAccess = 0; + SERVICE_STATUS ssServiceStatus = {0}; + BOOL fRet = FALSE; + + if ((pOpenSCManagerA == NULL) || + (pOpenServiceA == NULL) || + (pQueryServiceStatus == NULL) || + (pCloseServiceHandle == NULL)) + { + *lpdwCurrentState = SERVICE_RUNNING; + return(NOERROR); + } + + *lpdwCurrentState = 0; + + fdwDesiredAccess = GENERIC_READ; + + schSCManager = (*pOpenSCManagerA)(lpszMachineName, + NULL, + fdwDesiredAccess); + + if(schSCManager == NULL) + { + hr = GetLastError(); + goto cleanup; + } + + schService = (*pOpenServiceA)(schSCManager, + lpszServiceName, + fdwDesiredAccess); + + if(schService == NULL) + { + hr = GetLastError(); + goto cleanup; + } + + fRet = (*pQueryServiceStatus)(schService, + &ssServiceStatus); + + if(fRet == FALSE) + { + hr = GetLastError(); + goto cleanup; + } + + *lpdwCurrentState = ssServiceStatus.dwCurrentState; + +cleanup: + + (*pCloseServiceHandle)(schService); + (*pCloseServiceHandle)(schSCManager); + + return(hr); +#endif +} + +BOOL +SetAfsStatus( + DWORD AfsStatus + ) +{ +#ifdef NO_AFS + return(TRUE); +#else + return write_registry_setting(LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS, + REG_DWORD, &AfsStatus, + sizeof(AfsStatus)) ? FALSE : TRUE; +#endif +} + +BOOL +GetAfsStatus( + DWORD *AfsStatus + ) +{ +#ifdef NO_AFS + return(TRUE); +#else + return read_registry_setting(LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS, + AfsStatus, sizeof(DWORD)) ? FALSE : TRUE; +#endif +} diff --git a/src/windows/leashdll/Makefile.in b/src/windows/leashdll/Makefile.in new file mode 100644 index 000000000000..16e2b6d93a1f --- /dev/null +++ b/src/windows/leashdll/Makefile.in @@ -0,0 +1,84 @@ +BUILDTOP=..\.. + +##FIX ME: Enable proper compilation with AFS +NO_AFS=1 + +!ifndef NO_AFS +###AFS_BASE= +AFS_INCLUDES=-I$(AFS_BASE)\Include +AFS_LIB=$(AFS_BASE)\lib +AFS_LIBS=$(AFS_LIB)\afsauthent.lib +!else +AFS_INCLUDES= +AFS_LIBS= +!endif + +DLL_NAME=leashw32 + +# Use 64-bit DLL_NAME and DEF_FILE on 64-bit platforms +!if ("$(CPU)" == "IA64") || ("$(CPU)" == "AMD64") || ("$(CPU)" == "ALPHA64") +DLL_NAME=leashw64 +!endif + +DEF_FILE=leashw32.def + +OBJS= $(OUTPRE)AFSroutines.$(OBJEXT) \ + $(OUTPRE)krb5routines.$(OBJEXT) \ + $(OUTPRE)leashdll.$(OBJEXT) \ + $(OUTPRE)leasherr.$(OBJEXT) \ + $(OUTPRE)lsh_pwd.$(OBJEXT) \ + $(OUTPRE)lshcallb.$(OBJEXT) \ + $(OUTPRE)lshfunc.$(OBJEXT) \ + $(OUTPRE)lshutil.$(OBJEXT) \ + $(OUTPRE)timesync.$(OBJEXT) \ + $(OUTPRE)winerr.$(OBJEXT) \ + $(OUTPRE)winutil.$(OBJEXT) \ + $(OUTPRE)registry.$(OBJEXT) + +#TODO: Fix resource compilation +RESFILE = $(OUTPRE)lsh_pwd.res +XOBJS = $(RESFILE) + +RCFLAGS = -I$(BUILDTOP)\include -I$(BUILDTOP) -DLEASHDLL_LIB + +###From another project inside K 1.9: +###VERSIONRC = $(BUILDTOP)\windows\version.rc +###RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + + +# Set NODEBUG if building release instead of debug + +LOCALINCLUDES = -I$(BUILDTOP)\include -I$(BUILDTOP)\windows\include -I.\include\krb4 $(AFS_INCLUDES) + +WINLIBS = kernel32.lib advapi32.lib user32.lib gdi32.lib Version.lib \ + ws2_32.lib dnsapi.lib $(BUILDTOP)\ccapi\lib\win\srctmp\$(CCLIB).lib $(AFS_LIBS) + +WINDLLFLAGS = /nologo /dll /incremental:no /release $(LOPTS) + + +DEFINES = -DWINSOCK -DWIN32 -DWINDOWS -DNO_KRB4 -DUSE_MESSAGE_BOX +!ifdef NODEBUG +DEFINES = $(DEFINES) +!else +DEFINES = $(DEFINES) -DDBG +!endif + +!ifdef NO_AFS +DEFINES = $(DEFINES) -DNO_AFS +!endif + +all-windows: +all-windows: $(OUTPRE)$(DLL_NAME).dll + +clean-windows:: + $(RM) $(OUTPRE)$(DLL_NAME).dll + +$(OUTPRE)$(DLL_NAME).dll: $(DEF_FILE) $(OBJS) $(XOBJS) + link $(WINDLLFLAGS) -def:$(DEF_FILE) -out:$*.dll \ + $(OBJS) $(XOBJS) $(WINLIBS) ../lib/$(OUTPRE)libwin.lib $(SCLIB) + $(_VC_MANIFEST_EMBED_DLL) + +#TODO: Add dependencies on include files here + +$(RESFILE): lsh_pwd.rc ../version.rc ../kerberos.ver + diff --git a/src/windows/leashdll/include/krb4/conf-pc.h b/src/windows/leashdll/include/krb4/conf-pc.h new file mode 100644 index 000000000000..65a8779caf7f --- /dev/null +++ b/src/windows/leashdll/include/krb4/conf-pc.h @@ -0,0 +1,108 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * Machine-type definitions: IBM PC 8086 + */ + +#if defined(_WIN32) && !defined(WIN32) +#define WIN32 +#endif + +#if ( defined(WIN16) || defined(WIN32) || defined(_WINDOWS)) && !defined(WINDOWS) +#define WINDOWS +#endif + +#if defined(__OS2__) && !defined(OS2) +#define OS2 +#endif + +#ifdef WIN16 +#define BITS16 +#else +#ifdef MSDOS +#define BITS16 +#else +#define BITS32 +#endif +#endif +#define LSBFIRST + +#define index(s,c) strchr(s,c) /* PC version of index */ +#define rindex(s,c) strrchr(s,c) +#if !defined(OS2) && !defined(LWP) /* utils.h under OS/2 */ +#define bcmp(s1,s2,n) memcmp((s1),(s2),(n)) +#define bcopy(a,b,c) memcpy( (b), (a), (c) ) +#define bzero(a,b) memset( (a), 0, (b) ) +#endif + +typedef unsigned char u_char; +typedef unsigned long u_long; +typedef unsigned short u_short; +typedef unsigned int u_int; +#define NO_UIDGID_T + +#if !defined(WINDOWS) && !defined(DWORD) +typedef long DWORD; +#endif + +#if defined(PC)&&!defined(WINDOWS) +#ifndef LPSTR +typedef char *LPSTR; +typedef char *LPBYTE; +typedef char *CHARPTR; +typedef char *LPINT; +typedef unsigned int WORD; +#endif +#define LONG long +#define FAR +#define PASCAL +#define EXPORT +#endif + +#ifdef OS2 +#include <utils.h> +#define lstrcpy strcpy +#define lstrlen strlen +#define lstrcmp strcmp +#define lstrcpyn strncpy +#endif + +#ifdef WIN32 +#define _export +#endif + +#if defined(BITS32) +#define far +#define near +#endif + +#ifdef WINDOWS +#include <windows.h> +#endif + +#ifdef WIN32 +#include <windowsx.h> +#endif + +#ifdef WIN16 +#pragma message ( "WIN16 in " __FILE__ ) +#include <time.h> +#include <process.h> +#ifndef KRB_INT32 +#define KRB_INT32 long +#endif +#ifndef KRB_UINT32 +#define KRB_UINT32 unsigned KRB_INT32 +#endif +#endif + + +#define RANDOM_KRB_INT32_1 ((KRB_INT32) time(NULL)) +#define RANDOM_KRB_INT32_2 ((KRB_INT32) getpid()) +#define TIME_GMT_UNIXSEC unix_time_gmt_unixsec((unsigned KRB_INT32 *)0); +#ifndef MAXPATHLEN +#define MAXPATHLEN _MAX_PATH +#endif diff --git a/src/windows/leashdll/include/krb4/conf.h b/src/windows/leashdll/include/krb4/conf.h new file mode 100644 index 000000000000..2e2a84cd6e42 --- /dev/null +++ b/src/windows/leashdll/include/krb4/conf.h @@ -0,0 +1,74 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * Configuration info for operating system, hardware description, + * language implementation, C library, etc. + * + * This file should be included in (almost) every file in the Kerberos + * sources, and probably should *not* be needed outside of those + * sources. (How do we deal with /usr/include/des.h and + * /usr/include/krb.h?) + */ + +#ifndef _CONF_H_ +#define _CONF_H_ + +#include "osconf.h" + +#ifdef SHORTNAMES +#include "names.h" +#endif + +/* + * Language implementation-specific definitions + */ + +/* special cases */ +#ifdef __HIGHC__ +/* broken implementation of ANSI C */ +#undef __STDC__ +#endif + +#if !defined(__STDC__) && !defined(PC) +#define const +#define volatile +#define signed +typedef char *pointer; /* pointer to generic data */ +#ifndef PROTOTYPE +#define PROTOTYPE(p) () +#endif +#else +typedef void *pointer; +#ifndef PROTOTYPE +#define PROTOTYPE(p) p +#endif +#endif + +/* Does your compiler understand "void"? */ +#ifdef notdef +#define void int +#endif + +/* + * A few checks to see that necessary definitions are included. + */ + +#ifndef MSBFIRST +#ifndef LSBFIRST +#error byte order not defined +#endif +#endif + +/* machine size */ +#ifndef BITS16 +#ifndef BITS32 +#error number of bits? +#endif +#endif + +/* end of checks */ + +#endif /* _CONF_H_ */ diff --git a/src/windows/leashdll/include/krb4/osconf.h b/src/windows/leashdll/include/krb4/osconf.h new file mode 100644 index 000000000000..340421e86855 --- /dev/null +++ b/src/windows/leashdll/include/krb4/osconf.h @@ -0,0 +1,59 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * Athena configuration. + */ + +#ifndef _OSCONF_H_ +#define _OSCONF_H_ + +#ifndef PC +#if defined(IBMPC) || defined(__MSDOS__) || defined(OS2) || defined(_MSDOS) || defined(_WIN32) +#define PC +#endif +#endif + +#ifdef tahoe +#include "conf-bsdtahoe.h" +#else /* !tahoe */ +#ifdef vax +#include "conf-bsdvax.h" +#else /* !vax */ +#if defined(mips) && defined(ultrix) +#include "conf-ultmips2.h" +#else /* !Ultrix MIPS-2 */ +#ifdef ibm032 +#include "conf-bsdibm032.h" +#else /* !ibm032 */ +#ifdef apollo +#include "conf-bsdapollo.h" +#else /* !apollo */ +#ifdef sun +#ifdef sparc +#include "conf-bsdsparc.h" +#else /* sun but not sparc */ +#ifdef i386 +#include "conf-bsd386i.h" +#else /* sun but not (sparc or 386i) */ +#include "conf-bsdm68k.h" +#endif /* i386 */ +#endif /* sparc */ +#else /* !sun */ +#ifdef pyr +#include "conf-pyr.h" +#else +#if defined(PC) || defined(__MSDOS__) || defined(OS2) || defined(_MSDOS) || defined(_WIN32) +#include "conf-pc.h" +#endif /* PC */ +#endif /* pyr */ +#endif /* sun */ +#endif /* apollo */ +#endif /* ibm032 */ +#endif /* mips */ +#endif /* vax */ +#endif /* tahoe */ + +#endif /* _OSCONF_H_ */ diff --git a/src/windows/leashdll/krb5routines.c b/src/windows/leashdll/krb5routines.c new file mode 100644 index 000000000000..3911720aeaee --- /dev/null +++ b/src/windows/leashdll/krb5routines.c @@ -0,0 +1,1066 @@ +// Module name: krb5routines.c + +#include <windows.h> +#define SECURITY_WIN32 +#include <security.h> + +/* _WIN32_WINNT must be 0x0501 or greater to pull in definition of + * all required LSA data types when the Vista SDK NtSecAPI.h is used. + */ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#else +#if _WIN32_WINNT < 0x0501 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#endif +#include <ntsecapi.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <assert.h> + +#include <winsock2.h> + +/* Private Include files */ +#include "leashdll.h" +#include <leashwin.h> +#include "leash-int.h" + +#define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */ + +char *GetTicketFlag(krb5_creds *cred) +{ + static char buf[32]; + int i = 0; + + buf[i++] = ' '; + buf[i++] = '('; + + if (cred->ticket_flags & TKT_FLG_FORWARDABLE) + buf[i++] = 'F'; + + if (cred->ticket_flags & TKT_FLG_FORWARDED) + buf[i++] = 'f'; + + if (cred->ticket_flags & TKT_FLG_PROXIABLE) + buf[i++] = 'P'; + + if (cred->ticket_flags & TKT_FLG_PROXY) + buf[i++] = 'p'; + + if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE) + buf[i++] = 'D'; + + if (cred->ticket_flags & TKT_FLG_POSTDATED) + buf[i++] = 'd'; + + if (cred->ticket_flags & TKT_FLG_INVALID) + buf[i++] = 'i'; + + if (cred->ticket_flags & TKT_FLG_RENEWABLE) + buf[i++] = 'R'; + + if (cred->ticket_flags & TKT_FLG_INITIAL) + buf[i++] = 'I'; + + if (cred->ticket_flags & TKT_FLG_HW_AUTH) + buf[i++] = 'H'; + + if (cred->ticket_flags & TKT_FLG_PRE_AUTH) + buf[i++] = 'A'; + + buf[i++] = ')'; + buf[i] = '\0'; + + if (i <= 3) + buf[0] = '\0'; + + return buf; +} + +long +Leash_convert524( + krb5_context alt_ctx + ) +{ +#if defined(NO_KRB5) || defined(NO_KRB4) + return(0); +#else + krb5_context ctx = 0; + krb5_error_code code = 0; + int icode = 0; + krb5_principal me = 0; + krb5_principal server = 0; + krb5_creds *v5creds = 0; + krb5_creds increds; + krb5_ccache cc = 0; + CREDENTIALS * v4creds = NULL; + static int init_ets = 1; + + if (!pkrb5_init_context || + !pkrb_in_tkt || + !pkrb524_init_ets || + !pkrb524_convert_creds_kdc) + return 0; + + v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS)); + memset((char *) v4creds, 0, sizeof(CREDENTIALS)); + + memset((char *) &increds, 0, sizeof(increds)); + /* + From this point on, we can goto cleanup because increds is + initialized. + */ + + if (alt_ctx) + { + ctx = alt_ctx; + } + else + { + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + } + + code = pkrb5_cc_default(ctx, &cc); + if (code) goto cleanup; + + if ( init_ets ) { + pkrb524_init_ets(ctx); + init_ets = 0; + } + + if (code = pkrb5_cc_get_principal(ctx, cc, &me)) + goto cleanup; + + if ((code = pkrb5_build_principal(ctx, + &server, + krb5_princ_realm(ctx, me)->length, + krb5_princ_realm(ctx, me)->data, + "krbtgt", + krb5_princ_realm(ctx, me)->data, + NULL))) { + goto cleanup; + } + + increds.client = me; + increds.server = server; + increds.times.endtime = 0; + increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; + if ((code = pkrb5_get_credentials(ctx, 0, + cc, + &increds, + &v5creds))) { + goto cleanup; + } + + if ((icode = pkrb524_convert_creds_kdc(ctx, + v5creds, + v4creds))) { + goto cleanup; + } + + /* initialize ticket cache */ + if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm) + != KSUCCESS)) { + goto cleanup; + } + /* stash ticket, session key, etc. for future use */ + if ((icode = pkrb_save_credentials(v4creds->service, + v4creds->instance, + v4creds->realm, + v4creds->session, + v4creds->lifetime, + v4creds->kvno, + &(v4creds->ticket_st), + v4creds->issue_date))) { + goto cleanup; + } + + cleanup: + memset(v4creds, 0, sizeof(v4creds)); + free(v4creds); + + if (v5creds) { + pkrb5_free_creds(ctx, v5creds); + } + if (increds.client == me) + me = 0; + if (increds.server == server) + server = 0; + pkrb5_free_cred_contents(ctx, &increds); + if (server) { + pkrb5_free_principal(ctx, server); + } + if (me) { + pkrb5_free_principal(ctx, me); + } + pkrb5_cc_close(ctx, cc); + + if (ctx && (ctx != alt_ctx)) { + pkrb5_free_context(ctx); + } + return !(code || icode); +#endif /* NO_KRB5 */ +} + + +int +LeashKRB5_renew(void) +{ +#ifdef NO_KRB5 + return(0); +#else + 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; + + if ( !pkrb5_init_context ) + goto cleanup; + + memset(&my_creds, 0, sizeof(krb5_creds)); + + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + + code = pkrb5_cc_default(ctx, &cc); + if (code) goto cleanup; + + code = pkrb5_cc_get_principal(ctx, cc, &me); + if (code) goto cleanup; + + realm = krb5_princ_realm(ctx, me); + + code = pkrb5_build_principal_ext(ctx, &server, + realm->length,realm->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + realm->length,realm->data, + 0); + if ( code ) goto cleanup; + + my_creds.client = me; + my_creds.server = server; + +#ifdef KRB5_TC_NOTICKET + pkrb5_cc_set_flags(ctx, cc, 0); +#endif + code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL); +#ifdef KRB5_TC_NOTICKET + pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET); +#endif + if (code) { + if ( code != KRB5KDC_ERR_ETYPE_NOSUPP || + code != KRB5_KDC_UNREACH) + Leash_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc); + goto cleanup; + } + + code = pkrb5_cc_initialize(ctx, cc, me); + if (code) goto cleanup; + + code = pkrb5_cc_store_cred(ctx, cc, &my_creds); + if (code) goto cleanup; + + cleanup: + if (my_creds.client == me) + my_creds.client = 0; + if (my_creds.server == server) + my_creds.server = 0; + pkrb5_free_cred_contents(ctx, &my_creds); + if (me) + pkrb5_free_principal(ctx, me); + if (server) + pkrb5_free_principal(ctx, server); + if (cc) + pkrb5_cc_close(ctx, cc); + if (ctx) + pkrb5_free_context(ctx); + return(code); +#endif /* NO_KRB5 */ +} + +#ifndef NO_KRB5 +static krb5_error_code KRB5_CALLCONV +leash_krb5_prompter( krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]); +#endif /* NO_KRB5 */ + +int +Leash_krb5_kinit( +krb5_context alt_ctx, +HWND hParent, +char *principal_name, +char *password, +krb5_deltat lifetime, +DWORD forwardable, +DWORD proxiable, +krb5_deltat renew_life, +DWORD addressless, +DWORD publicIP +) +{ +#ifdef NO_KRB5 + return(0); +#else + krb5_error_code code = 0; + krb5_context ctx = 0; + krb5_ccache cc = 0, defcache = 0; + krb5_principal me = 0; + char* name = 0; + krb5_creds my_creds; + krb5_get_init_creds_opt * options = NULL; + krb5_address ** addrs = NULL; + int i = 0, addr_count = 0; + int cc_new = 0; + const char * deftype = NULL; + + if (!pkrb5_init_context) + return 0; + + memset(&my_creds, 0, sizeof(my_creds)); + + if (alt_ctx) + { + ctx = alt_ctx; + } + else + { + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + } + + code = pkrb5_get_init_creds_opt_alloc(ctx, &options); + if (code) goto cleanup; + + code = pkrb5_cc_default(ctx, &defcache); + if (code) goto cleanup; + + code = pkrb5_parse_name(ctx, principal_name, &me); + if (code) goto cleanup; + + deftype = pkrb5_cc_get_type(ctx, defcache); + if (me != NULL && pkrb5_cc_support_switch(ctx, deftype)) { + /* Use an existing cache for the specified principal if we can. */ + code = pkrb5_cc_cache_match(ctx, me, &cc); + if (code != 0 && code != KRB5_CC_NOTFOUND) + goto cleanup; + if (code == KRB5_CC_NOTFOUND) { + code = pkrb5_cc_new_unique(ctx, deftype, NULL, &cc); + if (code) + goto cleanup; + cc_new = 1; + } + pkrb5_cc_close(ctx, defcache); + } else { + cc = defcache; + } + + code = pkrb5_unparse_name(ctx, me, &name); + if (code) goto cleanup; + + if (lifetime == 0) + lifetime = Leash_get_default_lifetime(); + else + lifetime *= 5*60; + + if (renew_life > 0) + renew_life *= 5*60; + + if (lifetime) + pkrb5_get_init_creds_opt_set_tkt_life(options, lifetime); + pkrb5_get_init_creds_opt_set_forwardable(options, + forwardable ? 1 : 0); + pkrb5_get_init_creds_opt_set_proxiable(options, + proxiable ? 1 : 0); + pkrb5_get_init_creds_opt_set_renew_life(options, + renew_life); + if (addressless) + pkrb5_get_init_creds_opt_set_address_list(options,NULL); + else { + if (publicIP) + { + // we are going to add the public IP address specified by the user + // to the list provided by the operating system + krb5_address ** local_addrs=NULL; + DWORD netIPAddr; + + pkrb5_os_localaddr(ctx, &local_addrs); + while ( local_addrs[i++] ); + addr_count = i + 1; + + addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *)); + if ( !addrs ) { + pkrb5_free_addresses(ctx, local_addrs); + assert(0); + } + memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1)); + i = 0; + while ( local_addrs[i] ) { + addrs[i] = (krb5_address *)malloc(sizeof(krb5_address)); + if (addrs[i] == NULL) { + pkrb5_free_addresses(ctx, local_addrs); + assert(0); + } + + addrs[i]->magic = local_addrs[i]->magic; + addrs[i]->addrtype = local_addrs[i]->addrtype; + addrs[i]->length = local_addrs[i]->length; + addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length); + if (!addrs[i]->contents) { + pkrb5_free_addresses(ctx, local_addrs); + assert(0); + } + + memcpy(addrs[i]->contents,local_addrs[i]->contents, + local_addrs[i]->length); /* safe */ + i++; + } + pkrb5_free_addresses(ctx, local_addrs); + + addrs[i] = (krb5_address *)malloc(sizeof(krb5_address)); + if (addrs[i] == NULL) + assert(0); + + addrs[i]->magic = KV5M_ADDRESS; + addrs[i]->addrtype = AF_INET; + addrs[i]->length = 4; + addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length); + if (!addrs[i]->contents) + assert(0); + + netIPAddr = htonl(publicIP); + memcpy(addrs[i]->contents,&netIPAddr,4); + + pkrb5_get_init_creds_opt_set_address_list(options,addrs); + + } + } + + code = pkrb5_get_init_creds_opt_set_out_ccache(ctx, options, cc); + if (code) + goto cleanup; + + code = pkrb5_get_init_creds_password(ctx, + &my_creds, + me, + password, // password + leash_krb5_prompter, // prompter + hParent, // prompter data + 0, // start time + 0, // service name + options); + // @TODO: make this an option + if ((!code) && (cc != defcache)) { + code = pkrb5_cc_switch(ctx, cc); + if (!code) { + const char *cctype = pkrb5_cc_get_type(ctx, cc); + if (cctype != NULL) { + char defname[20]; + sprintf_s(defname, sizeof(defname), "%s:", cctype); + pkrb5int_cc_user_set_default_name(ctx, defname); + } + } + } + cleanup: + if (code && cc_new) { + // don't leave newly-generated empty ccache lying around on failure + pkrb5_cc_destroy(ctx, cc); + cc = NULL; + } + if ( addrs ) { + for ( i=0;i<addr_count;i++ ) { + if ( addrs[i] ) { + if ( addrs[i]->contents ) + free(addrs[i]->contents); + free(addrs[i]); + } + } + } + if (my_creds.client == me) + my_creds.client = 0; + pkrb5_free_cred_contents(ctx, &my_creds); + if (name) + pkrb5_free_unparsed_name(ctx, name); + if (me) + pkrb5_free_principal(ctx, me); + if (cc) + pkrb5_cc_close(ctx, cc); + if (options) + pkrb5_get_init_creds_opt_free(ctx, options); + if (ctx && (ctx != alt_ctx)) + pkrb5_free_context(ctx); + return(code); +#endif //!NO_KRB5 +} + + +/**************************************/ +/* LeashKRB5destroyTicket(): */ +/**************************************/ +int +Leash_krb5_kdestroy( + void + ) +{ +#ifdef NO_KRB5 + return(0); +#else + krb5_context ctx; + krb5_ccache cache; + krb5_error_code rc; + + ctx = NULL; + cache = NULL; + rc = Leash_krb5_initialize(&ctx); + if (rc) + return(rc); + + if (rc = pkrb5_cc_default(ctx, &cache)) + return(rc); + + rc = pkrb5_cc_destroy(ctx, cache); + + if (ctx != NULL) + pkrb5_free_context(ctx); + + return(rc); + +#endif //!NO_KRB5 +} + +krb5_error_code +Leash_krb5_cc_default(krb5_context *ctx, krb5_ccache *cache) +{ + krb5_error_code rc; + krb5_flags flags; + + char *functionName = NULL; + if (*cache == 0) { + rc = pkrb5_cc_default(*ctx, cache); + if (rc) { + functionName = "krb5_cc_default()"; + goto on_error; + } + } +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; +#endif + rc = pkrb5_cc_set_flags(*ctx, *cache, flags); + if (rc) { + if (rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) { + if (*cache != NULL && *ctx != NULL) + pkrb5_cc_close(*ctx, *cache); + } else { + functionName = "krb5_cc_set_flags()"; + goto on_error; + } + } +on_error: + if (rc && functionName) { + Leash_krb5_error(rc, functionName, 0, ctx, cache); + } + return rc; +} + +/**************************************/ +/* Leash_krb5_initialize(): */ +/**************************************/ +int Leash_krb5_initialize(krb5_context *ctx) +{ +#ifdef NO_KRB5 + return(0); +#else + + LPCSTR functionName = NULL; + krb5_error_code rc; + + if (pkrb5_init_context == NULL) + return 1; + + if (*ctx == 0) { + if (rc = (*pkrb5_init_context)(ctx)) { + functionName = "krb5_init_context()"; + return Leash_krb5_error(rc, functionName, 0, ctx, NULL); + } + } + return 0; +#endif //!NO_KRB5 +} + + +/**************************************/ +/* Leash_krb5_error(): */ +/**************************************/ +int +Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, + int FreeContextFlag, krb5_context * ctx, + krb5_ccache * cache) +{ +#ifdef NO_KRB5 + return 0; +#else +#ifdef USE_MESSAGE_BOX + char message[256]; + const char *errText; + + errText = perror_message(rc); + _snprintf(message, sizeof(message), + "%s\n(Kerberos error %ld)\n\n%s failed", + errText, + rc, + FailedFunctionName); + message[sizeof(message)-1] = 0; + + MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR | + MB_TASKMODAL | + MB_SETFOREGROUND); +#endif /* USE_MESSAGE_BOX */ + + if (ctx != NULL && *ctx != NULL) { + if (cache != NULL && *cache != NULL) { + pkrb5_cc_close(*ctx, *cache); + *cache = NULL; + } + + if (FreeContextFlag) { + pkrb5_free_context(*ctx); + *ctx = NULL; + } + } + + return rc; + +#endif //!NO_KRB5 +} + + +BOOL +Leash_ms2mit(BOOL save_creds) +{ +#ifdef NO_KRB5 + return(FALSE); +#else /* NO_KRB5 */ + krb5_context kcontext = 0; + krb5_error_code code; + krb5_ccache ccache=0; + krb5_ccache mslsa_ccache=0; + krb5_creds creds; + krb5_cc_cursor cursor=0; + krb5_principal princ = 0; + BOOL rc = FALSE; + + if ( !pkrb5_init_context ) + goto cleanup; + + if (code = pkrb5_init_context(&kcontext)) + goto cleanup; + + if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if ( save_creds ) { + if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) + goto cleanup; + + if (code = pkrb5_cc_default(kcontext, &ccache)) + goto cleanup; + + if (code = pkrb5_cc_initialize(kcontext, ccache, princ)) + goto cleanup; + + if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) + goto cleanup; + + rc = TRUE; + } else { + /* Enumerate tickets from cache looking for an initial ticket */ + if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) + goto cleanup; + + while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds))) + { + if ( creds.ticket_flags & TKT_FLG_INITIAL ) { + rc = TRUE; + pkrb5_free_cred_contents(kcontext, &creds); + break; + } + pkrb5_free_cred_contents(kcontext, &creds); + } + pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor); + } + + cleanup: + if (princ) + pkrb5_free_principal(kcontext, princ); + if (ccache) + pkrb5_cc_close(kcontext, ccache); + if (mslsa_ccache) + pkrb5_cc_close(kcontext, mslsa_ccache); + if (kcontext) + pkrb5_free_context(kcontext); + return(rc); +#endif /* NO_KRB5 */ +} + + +#ifndef NO_KRB5 +/* User Query data structures and functions */ + +struct textField { + char * buf; /* Destination buffer address */ + int len; /* Destination buffer length */ + char * label; /* Label for this field */ + char * def; /* Default response for this field */ + int echo; /* 0 = no, 1 = yes, 2 = asterisks */ +}; + +static int mid_cnt = 0; +static struct textField * mid_tb = NULL; + +#define ID_TEXT 150 +#define ID_MID_TEXT 300 + +static BOOL CALLBACK +MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam) +{ + int i; + + switch ( message ) { + case WM_INITDIALOG: + if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT ) + { + SetFocus(GetDlgItem( hDialog, ID_MID_TEXT)); + return FALSE; + } + 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) + SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0); + } + return TRUE; + + case WM_COMMAND: + switch ( LOWORD(wParam) ) { + case IDOK: + for ( i=0; i < mid_cnt ; i++ ) { + if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) ) + *mid_tb[i].buf = '\0'; + } + /* fallthrough */ + case IDCANCEL: + EndDialog(hDialog, LOWORD(wParam)); + return TRUE; + } + } + return FALSE; +} + +static LPWORD +lpwAlign( LPWORD lpIn ) +{ + ULONG ul; + + ul = (ULONG) lpIn; + ul += 3; + ul >>=2; + ul <<=2; + return (LPWORD) ul;; +} + +/* + * dialog widths are measured in 1/4 character widths + * dialog height are measured in 1/8 character heights + */ + +static LRESULT +MultiInputDialog( HINSTANCE hinst, HWND hwndOwner, + char * ptext[], int numlines, int width, + int tb_cnt, struct textField * tb) +{ + HGLOBAL hgbl; + LPDLGTEMPLATE lpdt; + LPDLGITEMTEMPLATE lpdit; + LPWORD lpw; + LPWSTR lpwsz; + LRESULT ret; + int nchar, i; + size_t pwid; + + 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_SETFOREGROUND | DS_3DLOOK + | DS_SHELLFONT | DS_NOFAILCREATE; + lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls + lpdt->x = 10; + lpdt->y = 10; + lpdt->cx = 20 + width * 4; + lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14; + + lpw = (LPWORD) (lpdt + 1); + *lpw++ = 0; // no menu + *lpw++ = 0; // predefined dialog box class (by default) + + lpwsz = (LPWSTR) lpw; + nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128); + lpw += nchar; + *lpw++ = 8; // font size (points) + lpwsz = (LPWSTR) lpw; + nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg", + -1, lpwsz, 128); + lpw += nchar; + + //----------------------- + // Define an OK button. + //----------------------- + lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary + 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->y = 10 + (numlines + tb_cnt + 2) * 14; + lpdit->cx = 40; + lpdit->cy = 14; + lpdit->id = IDOK; // OK button identifier + + lpw = (LPWORD) (lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0080; // button class + + lpwsz = (LPWSTR) lpw; + nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50); + lpw += nchar; + *lpw++ = 0; // no creation data + + //----------------------- + // Define an Cancel button. + //----------------------- + lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary + 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->y = 10 + (numlines + tb_cnt + 2) * 14; + lpdit->cx = 40; + lpdit->cy = 14; + lpdit->id = IDCANCEL; // CANCEL button identifier + + lpw = (LPWORD) (lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0080; // button class + + lpwsz = (LPWSTR) lpw; + nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50); + lpw += nchar; + *lpw++ = 0; // no creation data + + /* Add controls for preface data */ + for ( i=0; i<numlines; i++) { + /*----------------------- + * Define a static text control. + *-----------------------*/ + lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ + lpdit = (LPDLGITEMTEMPLATE) lpw; + lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; + lpdit->dwExtendedStyle = 0; + lpdit->x = 10; + lpdit->y = 10 + i * 14; + lpdit->cx = strlen(ptext[i]) * 4 + 10; + lpdit->cy = 14; + lpdit->id = ID_TEXT + i; // text identifier + + lpw = (LPWORD) (lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0082; // static class + + lpwsz = (LPWSTR) lpw; + 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); + } + + for ( i=0; i<tb_cnt; i++) { + /* Prompt */ + /*----------------------- + * Define a static text control. + *-----------------------*/ + lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ + lpdit = (LPDLGITEMTEMPLATE) lpw; + lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; + lpdit->dwExtendedStyle = 0; + lpdit->x = 10; + lpdit->y = 10 + (numlines + i + 1) * 14; + lpdit->cx = pwid * 4; + lpdit->cy = 14; + lpdit->id = ID_TEXT + numlines + i; // text identifier + + lpw = (LPWORD) (lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0082; // static class + + lpwsz = (LPWSTR) lpw; + nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "", + -1, lpwsz, 128); + lpw += nchar; + *lpw++ = 0; // no creation data + + /*----------------------- + * Define an edit control. + *-----------------------*/ + lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */ + 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->y = 10 + (numlines + i + 1) * 14; + lpdit->cx = (width - (pwid + 1)) * 4; + lpdit->cy = 14; + lpdit->id = ID_MID_TEXT + i; // identifier + + lpw = (LPWORD) (lpdit + 1); + *lpw++ = 0xFFFF; + *lpw++ = 0x0081; // edit class + + lpwsz = (LPWSTR) lpw; + 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); + + switch ( ret ) { + case 0: /* Timeout */ + return -1; + case IDOK: + return 1; + case IDCANCEL: + return 0; + default: { + char buf[256]; + sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError()); + MessageBox(hwndOwner, + buf, + "GetLastError()", + MB_OK | MB_ICONINFORMATION | MB_TASKMODAL); + return -1; + } + } +} + +static int +multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[]) +{ + extern HINSTANCE hLeashInst; + size_t maxwidth = 0; + int numlines = 0; + size_t len; + char * plines[16], *p = preface ? preface : ""; + int i; + + for ( i=0; i<16; i++ ) + plines[i] = NULL; + + while (*p && numlines < 16) { + plines[numlines++] = p; + for ( ;*p && *p != '\r' && *p != '\n'; p++ ); + if ( *p == '\r' && *(p+1) == '\n' ) { + *p++ = '\0'; + p++; + } else if ( *p == '\n' ) { + *p++ = '\0'; + } + if ( strlen(plines[numlines-1]) > maxwidth ) + maxwidth = strlen(plines[numlines-1]); + } + + for ( i=0;i<n;i++ ) { + len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len); + if ( maxwidth < len ) + maxwidth = len; + } + + return(MultiInputDialog(hLeashInst, hParent, plines, numlines, maxwidth, n, tb)); +} + +static krb5_error_code KRB5_CALLCONV +leash_krb5_prompter( krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]) +{ + krb5_error_code errcode = 0; + int i; + struct textField * tb = NULL; + int len = 0, blen=0, nlen=0; + HWND hParent = (HWND)data; + + if (name) + nlen = strlen(name)+2; + + if (banner) + blen = strlen(banner)+2; + + tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts); + if ( tb != NULL ) { + int ok; + memset(tb,0,sizeof(struct textField) * num_prompts); + for ( i=0; i < num_prompts; i++ ) { + tb[i].buf = prompts[i].reply->data; + tb[i].len = prompts[i].reply->length; + 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); + } else + errcode = -2; + } + + if ( tb ) + free(tb); + if (errcode) { + for (i = 0; i < num_prompts; i++) { + memset(prompts[i].reply->data, 0, prompts[i].reply->length); + } + } + return errcode; +} +#endif /* NO_KRB5 */ diff --git a/src/windows/leashdll/leash-int.h b/src/windows/leashdll/leash-int.h new file mode 100644 index 000000000000..b5c0b2738b78 --- /dev/null +++ b/src/windows/leashdll/leash-int.h @@ -0,0 +1,359 @@ +#ifndef __LEASH_INT_H__ +#define __LEASH_INT_H__ + +#include <stdio.h> +#include <stdlib.h> + +#include "leashdll.h" +#include <leashwin.h> + +#include "tlhelp32.h" + +#define MIT_PWD_DLL_CLASS "MITPasswordWndDLL" + +BOOL +Register_MITPasswordEditControl( + HINSTANCE hInst + ); + +BOOL +Unregister_MITPasswordEditControl( + HINSTANCE hInst + ); + +// Some defines swiped from leash.h +// These are necessary but they must be kept sync'ed with leash.h +#define HELPFILE "leash32.hlp" +extern char KRB_HelpFile[_MAX_PATH]; + +// Function Prototypes. +int lsh_com_err_proc (LPSTR whoami, long code, LPSTR fmt, va_list args); +int DoNiftyErrorReport(long errnum, LPSTR what); +LONG Leash_timesync(int); +BOOL Leash_ms2mit(BOOL); + +#ifndef NO_AFS +int not_an_API_LeashAFSGetToken(TICKETINFO * ticketinfo, TicketList** ticketList, char * kprinc); +long FAR not_an_API_LeashFreeTicketList(TicketList** ticketList) ; +#endif + +// Crap... +#include <krb5.h> + +long +Leash_int_kinit_ex( + krb5_context ctx, + HWND hParent, + char * principal, + char * password, + int lifetime, + int forwardable, + int proxiable, + int renew_life, + int addressless, + unsigned long publicIP, + int displayErrors + ); + +long +Leash_int_checkpwd( + char * principal, + char * password, + int displayErrors + ); + +long +Leash_int_changepwd( + char * principal, + char * password, + char * newpassword, + char** result_string, + int displayErrors + ); + +int +Leash_krb5_kdestroy( + void + ); + +int +Leash_krb5_kinit( + krb5_context, + HWND hParent, + char * principal_name, + char * password, + krb5_deltat lifetime, + DWORD forwardable, + DWORD proxiable, + krb5_deltat renew_life, + DWORD addressless, + DWORD publicIP + ); + +long +Leash_convert524( + krb5_context ctx + ); + +int +Leash_afs_unlog( + void + ); + +int +Leash_afs_klog( + char *, + char *, + char *, + int + ); + +int +LeashKRB5_renew(void); + +LONG +write_registry_setting( + char* setting, + DWORD type, + void* buffer, + size_t size + ); + +LONG +read_registry_setting_user( + char* setting, + void* buffer, + size_t size + ); + +LONG +read_registry_setting( + char* setting, + void* buffer, + size_t size + ); + +BOOL +get_STRING_from_registry( + HKEY hBaseKey, + char * key, + char * value, + char * outbuf, + DWORD outlen + ); + +BOOL +get_DWORD_from_registry( + HKEY hBaseKey, + char * key, + char * value, + DWORD * result + ); + +int +config_boolean_to_int( + const char *s + ); + +BOOL GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData); +BOOL IsKerberosLogon(VOID); + +#ifndef NO_KRB5 +int Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, + int FreeContextFlag, krb5_context *ctx, + krb5_ccache *cache); +int Leash_krb5_initialize(krb5_context *); +krb5_error_code +Leash_krb5_cc_default(krb5_context *ctx, krb5_ccache *cache); +#endif /* NO_KRB5 */ + +LPSTR err_describe(LPSTR buf, long code); + +// toolhelp functions +TYPEDEF_FUNC( + HANDLE, + WINAPI, + CreateToolhelp32Snapshot, + (DWORD, DWORD) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32First, + (HANDLE, LPMODULEENTRY32) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + Module32Next, + (HANDLE, LPMODULEENTRY32) + ); + +// psapi functions +TYPEDEF_FUNC( + DWORD, + WINAPI, + GetModuleFileNameExA, + (HANDLE, HMODULE, LPSTR, DWORD) + ); +TYPEDEF_FUNC( + BOOL, + WINAPI, + EnumProcessModules, + (HANDLE, HMODULE*, DWORD, LPDWORD) + ); + +#define pGetModuleFileNameEx pGetModuleFileNameExA +#define TOOLHELPDLL "kernel32.dll" +#define PSAPIDLL "psapi.dll" + +// psapi functions +extern DECL_FUNC_PTR(GetModuleFileNameExA); +extern DECL_FUNC_PTR(EnumProcessModules); + +// toolhelp functions +extern DECL_FUNC_PTR(CreateToolhelp32Snapshot); +extern DECL_FUNC_PTR(Module32First); +extern DECL_FUNC_PTR(Module32Next); + +/* In order to avoid including the private CCAPI headers */ +typedef int cc_int32; + +#define CC_API_VER_1 1 +#define CC_API_VER_2 2 + +#define CCACHE_API cc_int32 + +/* +** The Official Error Codes +*/ +#define CC_NOERROR 0 +#define CC_BADNAME 1 +#define CC_NOTFOUND 2 +#define CC_END 3 +#define CC_IO 4 +#define CC_WRITE 5 +#define CC_NOMEM 6 +#define CC_FORMAT 7 +#define CC_LOCKED 8 +#define CC_BAD_API_VERSION 9 +#define CC_NO_EXIST 10 +#define CC_NOT_SUPP 11 +#define CC_BAD_PARM 12 +#define CC_ERR_CACHE_ATTACH 13 +#define CC_ERR_CACHE_RELEASE 14 +#define CC_ERR_CACHE_FULL 15 +#define CC_ERR_CRED_VERSION 16 + +enum { + CC_CRED_VUNKNOWN = 0, // For validation + CC_CRED_V4 = 1, + CC_CRED_V5 = 2, + CC_CRED_VMAX = 3 // For validation +}; + +typedef struct opaque_dll_control_block_type* apiCB; +typedef struct _infoNC { + char* name; + char* principal; + cc_int32 vers; +} infoNC; + +TYPEDEF_FUNC( +CCACHE_API, +__cdecl, +cc_initialize, + ( + apiCB** cc_ctx, // < DLL's primary control structure. + // returned here, passed everywhere else + cc_int32 api_version, // > ver supported by caller (use CC_API_VER_1) + cc_int32* api_supported, // < if ~NULL, max ver supported by DLL + const char** vendor // < if ~NULL, vendor name in read only C string + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +__cdecl, +cc_shutdown, + ( + apiCB** cc_ctx // <> DLL's primary control structure. NULL after + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +__cdecl, +cc_get_NC_info, + ( + apiCB* cc_ctx, // > DLL's primary control structure + struct _infoNC*** ppNCi // < (NULL before call) null terminated, + // list of a structs (free via cc_free_infoNC()) + ) +); + +TYPEDEF_FUNC( +CCACHE_API, +__cdecl, +cc_free_NC_info, + ( + apiCB* cc_ctx, + struct _infoNC*** ppNCi // < free list of structs returned by + // cc_get_cache_names(). set to NULL on return + ) +); +#define CCAPI_DLL "krbcc32.dll" + +/* The following definitions are summarized from KRB4, KRB5, Leash32, and + * Leashw32 modules. They are current as of KfW 2.6.2. There is no + * guarrantee that changes to other modules will be updated in this list. + */ + +/* Must match the values used in Leash32.exe */ +#define LEASH_SETTINGS_REGISTRY_KEY_NAME "Software\\MIT\\Leash32\\Settings" +#define LEASH_SETTINGS_REGISTRY_VALUE_AFS_STATUS "AfsStatus" +#define LEASH_SETTINGS_REGISTRY_VALUE_DEBUG_WINDOW "DebugWindow" +#define LEASH_SETTINGS_REGISTRY_VALUE_LARGE_ICONS "LargeIcons" +#define LEASH_SETTINGS_REGISTRY_VALUE_DESTROY_TKTS "DestroyTickets" +#define LEASH_SETTINGS_REGISTRY_VALUE_LOW_TKT_ALARM "LowTicketAlarm" +#define LEASH_SETTINGS_REGISTRY_VALUE_AUTO_RENEW_TKTS "AutoRenewTickets" +#define LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM "UpperCaseRealm" +#define LEASH_SETTINGS_REGISTRY_VALUE_TIMEHOST "TIMEHOST" +#define LEASH_SETTINGS_REGISTRY_VALUE_CREATE_MISSING_CFG "CreateMissingConfig" +#define LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT "MsLsaImport" + +/* These values are defined and used within Leashw32.dll */ +#define LEASH_REGISTRY_KEY_NAME "Software\\MIT\\Leash" +#define LEASH_REGISTRY_VALUE_LIFETIME "lifetime" +#define LEASH_REGISTRY_VALUE_RENEW_TILL "renew_till" +#define LEASH_REGISTRY_VALUE_RENEWABLE "renewable" +#define LEASH_REGISTRY_VALUE_FORWARDABLE "forwardable" +#define LEASH_REGISTRY_VALUE_NOADDRESSES "noaddresses" +#define LEASH_REGISTRY_VALUE_PROXIABLE "proxiable" +#define LEASH_REGISTRY_VALUE_PUBLICIP "publicip" +#define LEASH_REGISTRY_VALUE_USEKRB4 "usekrb4" +#define LEASH_REGISTRY_VALUE_KINIT_OPT "hide_kinit_options" +#define LEASH_REGISTRY_VALUE_LIFE_MIN "life_min" +#define LEASH_REGISTRY_VALUE_LIFE_MAX "life_max" +#define LEASH_REGISTRY_VALUE_RENEW_MIN "renew_min" +#define LEASH_REGISTRY_VALUE_RENEW_MAX "renew_max" +#define LEASH_REGISTRY_VALUE_LOCK_LOCATION "lock_file_locations" +#define LEASH_REGISTRY_VALUE_PRESERVE_KINIT "preserve_kinit_options" + +/* must match values used within krbv4w32.dll */ +#define KRB4_REGISTRY_KEY_NAME "Software\\MIT\\Kerberos4" +#define KRB4_REGISTRY_VALUE_CONFIGFILE "config" +#define KRB4_REGISTRY_VALUE_KRB_CONF "krb.conf" +#define KRB4_REGISTRY_VALUE_KRB_REALMS "krb.realms" +#define KRB4_REGISTRY_VALUE_TICKETFILE "ticketfile" + +/* must match values used within krb5_32.dll */ +#define KRB5_REGISTRY_KEY_NAME "Software\\MIT\\Kerberos5" +#define KRB5_REGISTRY_VALUE_CCNAME "ccname" +#define KRB5_REGISTRY_VALUE_CONFIGFILE "config" + +/* must match values used within wshelper.dll */ +#define WSHELP_REGISTRY_KEY_NAME "Software\\MIT\\WsHelper" +#define WSHELP_REGISTRY_VALUE_DEBUG "DebugOn" + +#endif /* __LEASH_INT_H__ */ diff --git a/src/windows/leashdll/leashdll.c b/src/windows/leashdll/leashdll.c new file mode 100644 index 000000000000..b6d6318772f9 --- /dev/null +++ b/src/windows/leashdll/leashdll.c @@ -0,0 +1,373 @@ +#include <windows.h> +#include "leashdll.h" +#include <leashwin.h> +#include "leash-int.h" + +HINSTANCE hLeashInst; + +#ifndef NO_KRB4 +HINSTANCE hKrb4 = 0; +#endif +HINSTANCE hKrb5 = 0; +HINSTANCE hKrb524 = 0; +HINSTANCE hSecur32 = 0; +HINSTANCE hComErr = 0; +HINSTANCE hService = 0; +HINSTANCE hProfile = 0; +HINSTANCE hPsapi = 0; +HINSTANCE hToolHelp32 = 0; +HINSTANCE hCcapi = 0; + +DWORD AfsAvailable = 0; + +// krb5 functions +DECL_FUNC_PTR(krb5_change_password); +DECL_FUNC_PTR(krb5_get_init_creds_opt_alloc); +DECL_FUNC_PTR(krb5_get_init_creds_opt_free); +DECL_FUNC_PTR(krb5_get_init_creds_opt_init); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list); +DECL_FUNC_PTR(krb5_get_init_creds_opt_set_out_ccache); +DECL_FUNC_PTR(krb5_get_init_creds_password); +DECL_FUNC_PTR(krb5_build_principal_ext); +DECL_FUNC_PTR(krb5_cc_get_name); +DECL_FUNC_PTR(krb5_cc_resolve); +DECL_FUNC_PTR(krb5_cc_default); +DECL_FUNC_PTR(krb5_cc_default_name); +DECL_FUNC_PTR(krb5_cc_set_default_name); +DECL_FUNC_PTR(krb5_cc_initialize); +DECL_FUNC_PTR(krb5_cc_destroy); +DECL_FUNC_PTR(krb5_cc_close); +DECL_FUNC_PTR(krb5_cc_store_cred); +DECL_FUNC_PTR(krb5_cc_copy_creds); +// DECL_FUNC_PTR(krb5_cc_retrieve_cred); +DECL_FUNC_PTR(krb5_cc_get_principal); +DECL_FUNC_PTR(krb5_cc_start_seq_get); +DECL_FUNC_PTR(krb5_cc_next_cred); +DECL_FUNC_PTR(krb5_cc_end_seq_get); +// DECL_FUNC_PTR(krb5_cc_remove_cred); +DECL_FUNC_PTR(krb5_cc_set_flags); +// DECL_FUNC_PTR(krb5_cc_get_type); +DECL_FUNC_PTR(krb5_free_context); +DECL_FUNC_PTR(krb5_free_cred_contents); +DECL_FUNC_PTR(krb5_free_principal); +DECL_FUNC_PTR(krb5_get_in_tkt_with_password); +DECL_FUNC_PTR(krb5_init_context); +DECL_FUNC_PTR(krb5_parse_name); +DECL_FUNC_PTR(krb5_timeofday); +DECL_FUNC_PTR(krb5_timestamp_to_sfstring); +DECL_FUNC_PTR(krb5_unparse_name); +DECL_FUNC_PTR(krb5_get_credentials); +DECL_FUNC_PTR(krb5_mk_req); +DECL_FUNC_PTR(krb5_sname_to_principal); +DECL_FUNC_PTR(krb5_get_credentials_renew); +DECL_FUNC_PTR(krb5_free_data); +DECL_FUNC_PTR(krb5_free_data_contents); +// DECL_FUNC_PTR(krb5_get_realm_domain); +DECL_FUNC_PTR(krb5_free_unparsed_name); +DECL_FUNC_PTR(krb5_os_localaddr); +DECL_FUNC_PTR(krb5_copy_keyblock_contents); +DECL_FUNC_PTR(krb5_copy_data); +DECL_FUNC_PTR(krb5_free_creds); +DECL_FUNC_PTR(krb5_build_principal); +DECL_FUNC_PTR(krb5_get_renewed_creds); +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_ticket); +DECL_FUNC_PTR(krb5_decode_ticket); +DECL_FUNC_PTR(krb5_get_host_realm); +DECL_FUNC_PTR(krb5_free_host_realm); +DECL_FUNC_PTR(krb5_c_random_make_octets); +DECL_FUNC_PTR(krb5_free_addresses); +DECL_FUNC_PTR(krb5_free_default_realm); +DECL_FUNC_PTR(krb5_principal_compare); +DECL_FUNC_PTR(krb5_string_to_deltat); +DECL_FUNC_PTR(krb5_is_config_principal); +DECL_FUNC_PTR(krb5_cccol_cursor_new); +DECL_FUNC_PTR(krb5_cccol_cursor_free); +DECL_FUNC_PTR(krb5_cccol_cursor_next); +DECL_FUNC_PTR(krb5_cc_cache_match); +DECL_FUNC_PTR(krb5_cc_get_type); +DECL_FUNC_PTR(krb5_cc_new_unique); +DECL_FUNC_PTR(krb5_cc_support_switch); +DECL_FUNC_PTR(krb5_cc_switch); +DECL_FUNC_PTR(krb5_cc_get_full_name); +DECL_FUNC_PTR(krb5_free_string); +DECL_FUNC_PTR(krb5int_cc_user_set_default_name); + +// ComErr functions +DECL_FUNC_PTR(com_err); +DECL_FUNC_PTR(error_message); + +// Profile functions +DECL_FUNC_PTR(profile_init); +DECL_FUNC_PTR(profile_release); +DECL_FUNC_PTR(profile_get_subsection_names); +DECL_FUNC_PTR(profile_free_list); +DECL_FUNC_PTR(profile_get_string); +DECL_FUNC_PTR(profile_release_string); +DECL_FUNC_PTR(profile_get_integer); + +// Service functions +DECL_FUNC_PTR(OpenSCManagerA); +DECL_FUNC_PTR(OpenServiceA); +DECL_FUNC_PTR(QueryServiceStatus); +DECL_FUNC_PTR(CloseServiceHandle); +DECL_FUNC_PTR(LsaNtStatusToWinError); + +// LSA Functions +DECL_FUNC_PTR(LsaConnectUntrusted); +DECL_FUNC_PTR(LsaLookupAuthenticationPackage); +DECL_FUNC_PTR(LsaCallAuthenticationPackage); +DECL_FUNC_PTR(LsaFreeReturnBuffer); +DECL_FUNC_PTR(LsaGetLogonSessionData); + +// CCAPI Functions +DECL_FUNC_PTR(cc_initialize); +DECL_FUNC_PTR(cc_shutdown); +DECL_FUNC_PTR(cc_get_NC_info); +DECL_FUNC_PTR(cc_free_NC_info); + +FUNC_INFO k5_fi[] = { + MAKE_FUNC_INFO(krb5_change_password), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_alloc), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_free), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_init), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list), + MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_out_ccache), + MAKE_FUNC_INFO(krb5_get_init_creds_password), + MAKE_FUNC_INFO(krb5_build_principal_ext), + MAKE_FUNC_INFO(krb5_cc_get_name), + MAKE_FUNC_INFO(krb5_cc_resolve), + MAKE_FUNC_INFO(krb5_cc_default), + MAKE_FUNC_INFO(krb5_cc_default_name), + MAKE_FUNC_INFO(krb5_cc_set_default_name), + MAKE_FUNC_INFO(krb5_cc_initialize), + MAKE_FUNC_INFO(krb5_cc_destroy), + MAKE_FUNC_INFO(krb5_cc_close), + MAKE_FUNC_INFO(krb5_cc_copy_creds), + MAKE_FUNC_INFO(krb5_cc_store_cred), +// MAKE_FUNC_INFO(krb5_cc_retrieve_cred), + MAKE_FUNC_INFO(krb5_cc_get_principal), + MAKE_FUNC_INFO(krb5_cc_start_seq_get), + MAKE_FUNC_INFO(krb5_cc_next_cred), + MAKE_FUNC_INFO(krb5_cc_end_seq_get), +// MAKE_FUNC_INFO(krb5_cc_remove_cred), + MAKE_FUNC_INFO(krb5_cc_set_flags), +// MAKE_FUNC_INFO(krb5_cc_get_type), + MAKE_FUNC_INFO(krb5_free_context), + MAKE_FUNC_INFO(krb5_free_cred_contents), + MAKE_FUNC_INFO(krb5_free_principal), + MAKE_FUNC_INFO(krb5_get_in_tkt_with_password), + MAKE_FUNC_INFO(krb5_init_context), + MAKE_FUNC_INFO(krb5_parse_name), + MAKE_FUNC_INFO(krb5_timeofday), + MAKE_FUNC_INFO(krb5_timestamp_to_sfstring), + MAKE_FUNC_INFO(krb5_unparse_name), + MAKE_FUNC_INFO(krb5_get_credentials), + MAKE_FUNC_INFO(krb5_mk_req), + MAKE_FUNC_INFO(krb5_sname_to_principal), + MAKE_FUNC_INFO(krb5_get_credentials_renew), + MAKE_FUNC_INFO(krb5_free_data), + MAKE_FUNC_INFO(krb5_free_data_contents), +// MAKE_FUNC_INFO(krb5_get_realm_domain), + MAKE_FUNC_INFO(krb5_free_unparsed_name), + MAKE_FUNC_INFO(krb5_os_localaddr), + MAKE_FUNC_INFO(krb5_copy_keyblock_contents), + MAKE_FUNC_INFO(krb5_copy_data), + MAKE_FUNC_INFO(krb5_free_creds), + MAKE_FUNC_INFO(krb5_build_principal), + MAKE_FUNC_INFO(krb5_get_renewed_creds), + MAKE_FUNC_INFO(krb5_free_addresses), + 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_ticket), + MAKE_FUNC_INFO(krb5_decode_ticket), + MAKE_FUNC_INFO(krb5_get_host_realm), + MAKE_FUNC_INFO(krb5_free_host_realm), + MAKE_FUNC_INFO(krb5_c_random_make_octets), + MAKE_FUNC_INFO(krb5_free_default_realm), + MAKE_FUNC_INFO(krb5_principal_compare), + MAKE_FUNC_INFO(krb5_string_to_deltat), + MAKE_FUNC_INFO(krb5_is_config_principal), + MAKE_FUNC_INFO(krb5_cccol_cursor_new), + MAKE_FUNC_INFO(krb5_cccol_cursor_next), + MAKE_FUNC_INFO(krb5_cccol_cursor_free), + MAKE_FUNC_INFO(krb5_cc_cache_match), + MAKE_FUNC_INFO(krb5_cc_get_type), + MAKE_FUNC_INFO(krb5_cc_new_unique), + MAKE_FUNC_INFO(krb5_cc_support_switch), + MAKE_FUNC_INFO(krb5_cc_switch), + MAKE_FUNC_INFO(krb5_cc_get_full_name), + MAKE_FUNC_INFO(krb5_free_string), + MAKE_FUNC_INFO(krb5int_cc_user_set_default_name), + END_FUNC_INFO +}; + +FUNC_INFO profile_fi[] = { + MAKE_FUNC_INFO(profile_init), + MAKE_FUNC_INFO(profile_release), + MAKE_FUNC_INFO(profile_get_subsection_names), + MAKE_FUNC_INFO(profile_free_list), + MAKE_FUNC_INFO(profile_get_string), + MAKE_FUNC_INFO(profile_release_string), + MAKE_FUNC_INFO(profile_get_integer), + END_FUNC_INFO +}; + +FUNC_INFO ce_fi[] = { + MAKE_FUNC_INFO(com_err), + MAKE_FUNC_INFO(error_message), + END_FUNC_INFO +}; + +FUNC_INFO service_fi[] = { + MAKE_FUNC_INFO(OpenSCManagerA), + MAKE_FUNC_INFO(OpenServiceA), + MAKE_FUNC_INFO(QueryServiceStatus), + MAKE_FUNC_INFO(CloseServiceHandle), + MAKE_FUNC_INFO(LsaNtStatusToWinError), + END_FUNC_INFO +}; + +FUNC_INFO lsa_fi[] = { + MAKE_FUNC_INFO(LsaConnectUntrusted), + MAKE_FUNC_INFO(LsaLookupAuthenticationPackage), + MAKE_FUNC_INFO(LsaCallAuthenticationPackage), + MAKE_FUNC_INFO(LsaFreeReturnBuffer), + MAKE_FUNC_INFO(LsaGetLogonSessionData), + END_FUNC_INFO +}; + +// CCAPI v2 +FUNC_INFO ccapi_fi[] = { + MAKE_FUNC_INFO(cc_initialize), + MAKE_FUNC_INFO(cc_shutdown), + MAKE_FUNC_INFO(cc_get_NC_info), + MAKE_FUNC_INFO(cc_free_NC_info), + END_FUNC_INFO +}; + +// psapi functions +DECL_FUNC_PTR(GetModuleFileNameExA); +DECL_FUNC_PTR(EnumProcessModules); + +FUNC_INFO psapi_fi[] = { + MAKE_FUNC_INFO(GetModuleFileNameExA), + MAKE_FUNC_INFO(EnumProcessModules), + END_FUNC_INFO +}; + +// toolhelp functions +DECL_FUNC_PTR(CreateToolhelp32Snapshot); +DECL_FUNC_PTR(Module32First); +DECL_FUNC_PTR(Module32Next); + +FUNC_INFO toolhelp_fi[] = { + MAKE_FUNC_INFO(CreateToolhelp32Snapshot), + MAKE_FUNC_INFO(Module32First), + MAKE_FUNC_INFO(Module32Next), + END_FUNC_INFO +}; + +BOOL WINAPI +DllMain( + HANDLE hinstDLL, + DWORD fdwReason, + LPVOID lpReserved + ) +{ + hLeashInst = hinstDLL; + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + { + OSVERSIONINFO osvi; + LoadFuncs(KRB5_DLL, k5_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); + LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1); + LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0); + LoadFuncs(CCAPI_DLL, ccapi_fi, &hCcapi, 0, 1, 0, 0); + + memset(&osvi, 0, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + // XXX: We should really use feature testing, first + // checking for CreateToolhelp32Snapshot. If that's + // not around, we try the psapi stuff. + // + // Only load LSA functions if on NT/2000/XP + if(osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + // Windows 9x + LoadFuncs(TOOLHELPDLL, toolhelp_fi, &hToolHelp32, 0, 1, 0, 0); + hPsapi = 0; + } + else if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Windows NT + LoadFuncs(PSAPIDLL, psapi_fi, &hPsapi, 0, 1, 0, 0); + hToolHelp32 = 0; + } + + + /* + * Register window class for the MITPasswordControl that + * replaces normal edit controls for password input. + * zero any fields we don't explicitly set + */ + hLeashInst = hinstDLL; + + Register_MITPasswordEditControl(hLeashInst); + +#ifndef NO_AFS + { + DWORD AfsStatus = 0; + GetAfsStatus(&AfsStatus); + + AfsAvailable = afscompat_init(); + + if ( AfsStatus && !AfsAvailable ) + SetAfsStatus(0); + } +#endif + return TRUE; + } + case DLL_PROCESS_DETACH: +#ifndef NO_AFS + afscompat_close(); +#endif + if (hKrb5) + FreeLibrary(hKrb5); + if (hCcapi) + FreeLibrary(hCcapi); + if (hProfile) + FreeLibrary(hProfile); + if (hComErr) + FreeLibrary(hComErr); + if (hService) + FreeLibrary(hService); + if (hSecur32) + FreeLibrary(hSecur32); + if (hPsapi) + FreeLibrary(hPsapi); + if (hToolHelp32) + FreeLibrary(hToolHelp32); + + return TRUE; + default: + return TRUE; + } +} diff --git a/src/windows/leashdll/leashdll.h b/src/windows/leashdll/leashdll.h new file mode 100644 index 000000000000..b990224da1b8 --- /dev/null +++ b/src/windows/leashdll/leashdll.h @@ -0,0 +1,272 @@ +#ifndef _LEASHDLL_H_ +#define _LEASHDLL_H_ + +#include <com_err.h> +#ifdef __cplusplus +extern "C" { +#endif +#ifndef NO_KRB4 +/* + * This is a hack needed because the real com_err.h does + * not define err_func. We need it in the case where + * we pull in the real com_err instead of the krb4 + * impostor. + */ +#ifndef _DCNS_MIT_COM_ERR_H +typedef LPSTR (*err_func)(int, long); +#endif + +#include <krberr.h> +extern void Leash_initialize_krb_error_func(err_func func,struct et_list **); +#undef init_krb_err_func +#define init_krb_err_func(erf) Leash_initialize_krb_error_func(erf,&_et_list) + +#include <kadm_err.h> + +extern void Leash_initialize_kadm_error_table(struct et_list **); +#undef init_kadm_err_tbl +#define init_kadm_err_tbl() Leash_initialize_kadm_error_table(&_et_list) +#define kadm_err_base ERROR_TABLE_BASE_kadm +#endif + +#define krb_err_func Leash_krb_err_func + +#include <stdarg.h> +int lsh_com_err_proc (LPSTR whoami, long code, + LPSTR fmt, va_list args); +void FAR Leash_load_com_err_callback(FARPROC,FARPROC,FARPROC); + + +#ifndef KRBERR +#define KRBERR(code) (code + krb_err_base) +#endif + + +/* Internal Stuff */ + +#include <windows.h> +#define SECURITY_WIN32 +#include <security.h> + +/* _WIN32_WINNT must be 0x0501 or greater to pull in definition of + * all required LSA data types when the Vista SDK NtSecAPI.h is used. + */ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#else +#if _WIN32_WINNT < 0x0501 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#endif +#include <ntsecapi.h> + +#include <krb5.h> + +#ifndef NO_KRB4 +extern HINSTANCE hKrb4; +#endif +extern HINSTANCE hKrb5; +extern HINSTANCE hProfile; + +#define TIMEHOST "TIMEHOST" + +#define LEASH_DEBUG_CLASS_GENERIC 0 +#define LEASH_DEBUG_CLASS_KRB4 1 +#define LEASH_DEBUG_CLASS_KRB4_APP 2 + +#define LEASH_PRIORITY_LOW 0 +#define LEASH_PRIORITY_HIGH 1 + +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _WIN64 +#define LEASH_DLL "leashw64.dll" +#define KRBCC32_DLL "krbcc64.dll" +#else +#define LEASH_DLL "leashw32.dll" +#define KRBCC32_DLL "krbcc32.dll" +#endif +#define SERVICE_DLL "advapi32.dll" +#define SECUR32_DLL "secur32.dll" + +////////////////////////////////////////////////////////////////////////////// + +#include <loadfuncs-com_err.h> +#include <loadfuncs-krb5.h> +#include <loadfuncs-profile.h> +#ifndef NO_KRB4 +#include <loadfuncs-krb.h> +#include <loadfuncs-krb524.h> +#endif +#include <loadfuncs-lsa.h> + +#include <errno.h> + +#ifndef NO_AFS +////Can't find it! +////#include "afscompat.h" +#endif + +// service definitions +typedef SC_HANDLE (WINAPI *FP_OpenSCManagerA)(char *, char *, DWORD); +typedef SC_HANDLE (WINAPI *FP_OpenServiceA)(SC_HANDLE, char *, DWORD); +typedef BOOL (WINAPI *FP_QueryServiceStatus)(SC_HANDLE, LPSERVICE_STATUS); +typedef BOOL (WINAPI *FP_CloseServiceHandle)(SC_HANDLE); + +////////////////////////////////////////////////////////////////////////////// + +#ifndef NO_KRB4 +// krb4 functions +extern DECL_FUNC_PTR(get_krb_err_txt_entry); +extern DECL_FUNC_PTR(k_isinst); +extern DECL_FUNC_PTR(k_isname); +extern DECL_FUNC_PTR(k_isrealm); +extern DECL_FUNC_PTR(kadm_change_your_password); +extern DECL_FUNC_PTR(kname_parse); +extern DECL_FUNC_PTR(krb_get_cred); +extern DECL_FUNC_PTR(krb_get_krbhst); +extern DECL_FUNC_PTR(krb_get_lrealm); +extern DECL_FUNC_PTR(krb_get_pw_in_tkt); +extern DECL_FUNC_PTR(krb_get_tf_realm); +extern DECL_FUNC_PTR(krb_mk_req); +extern DECL_FUNC_PTR(krb_realmofhost); +extern DECL_FUNC_PTR(tf_init); +extern DECL_FUNC_PTR(tf_close); +extern DECL_FUNC_PTR(tf_get_cred); +extern DECL_FUNC_PTR(tf_get_pname); +extern DECL_FUNC_PTR(tf_get_pinst); +extern DECL_FUNC_PTR(LocalHostAddr); +extern DECL_FUNC_PTR(tkt_string); +extern DECL_FUNC_PTR(krb_set_tkt_string); +extern DECL_FUNC_PTR(initialize_krb_error_func); +extern DECL_FUNC_PTR(initialize_kadm_error_table); +extern DECL_FUNC_PTR(dest_tkt); +extern DECL_FUNC_PTR(lsh_LoadKrb4LeashErrorTables); // XXX +extern DECL_FUNC_PTR(krb_in_tkt); +extern DECL_FUNC_PTR(krb_save_credentials); +extern DECL_FUNC_PTR(krb_get_krbconf2); +extern DECL_FUNC_PTR(krb_get_krbrealm2); +extern DECL_FUNC_PTR(krb_life_to_time); +#endif + +// krb5 functions +extern DECL_FUNC_PTR(krb5_change_password); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_alloc); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_free); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_init); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list); +extern DECL_FUNC_PTR(krb5_get_init_creds_opt_set_out_ccache); +extern DECL_FUNC_PTR(krb5_get_init_creds_password); +extern DECL_FUNC_PTR(krb5_build_principal_ext); +extern DECL_FUNC_PTR(krb5_cc_get_name); +extern DECL_FUNC_PTR(krb5_cc_resolve); +extern DECL_FUNC_PTR(krb5_cc_default); +extern DECL_FUNC_PTR(krb5_cc_default_name); +extern DECL_FUNC_PTR(krb5_cc_set_default_name); +extern DECL_FUNC_PTR(krb5_cc_initialize); +extern DECL_FUNC_PTR(krb5_cc_destroy); +extern DECL_FUNC_PTR(krb5_cc_close); +extern DECL_FUNC_PTR(krb5_cc_copy_creds); +extern DECL_FUNC_PTR(krb5_cc_store_cred); +// extern DECL_FUNC_PTR(krb5_cc_retrieve_cred); +extern DECL_FUNC_PTR(krb5_cc_get_principal); +extern DECL_FUNC_PTR(krb5_cc_start_seq_get); +extern DECL_FUNC_PTR(krb5_cc_next_cred); +extern DECL_FUNC_PTR(krb5_cc_end_seq_get); +// extern DECL_FUNC_PTR(krb5_cc_remove_cred); +extern DECL_FUNC_PTR(krb5_cc_set_flags); +// extern DECL_FUNC_PTR(krb5_cc_get_type); +extern DECL_FUNC_PTR(krb5_cc_get_full_name); +extern DECL_FUNC_PTR(krb5_free_context); +extern DECL_FUNC_PTR(krb5_free_cred_contents); +extern DECL_FUNC_PTR(krb5_free_principal); +extern DECL_FUNC_PTR(krb5_free_string); +extern DECL_FUNC_PTR(krb5_get_in_tkt_with_password); +extern DECL_FUNC_PTR(krb5_init_context); +extern DECL_FUNC_PTR(krb5_parse_name); +extern DECL_FUNC_PTR(krb5_timeofday); +extern DECL_FUNC_PTR(krb5_timestamp_to_sfstring); +extern DECL_FUNC_PTR(krb5_unparse_name); +extern DECL_FUNC_PTR(krb5_get_credentials); +extern DECL_FUNC_PTR(krb5_mk_req); +extern DECL_FUNC_PTR(krb5_sname_to_principal); +extern DECL_FUNC_PTR(krb5_get_credentials_renew); +extern DECL_FUNC_PTR(krb5_free_data); +extern DECL_FUNC_PTR(krb5_free_data_contents); +// extern DECL_FUNC_PTR(krb5_get_realm_domain); +extern DECL_FUNC_PTR(krb5_free_unparsed_name); +extern DECL_FUNC_PTR(krb5_os_localaddr); +extern DECL_FUNC_PTR(krb5_copy_keyblock_contents); +extern DECL_FUNC_PTR(krb5_copy_data); +extern DECL_FUNC_PTR(krb5_free_creds); +extern DECL_FUNC_PTR(krb5_build_principal); +extern DECL_FUNC_PTR(krb5_get_renewed_creds); +extern DECL_FUNC_PTR(krb5_free_addresses); +extern DECL_FUNC_PTR(krb5_get_default_config_files); +extern DECL_FUNC_PTR(krb5_free_config_files); +extern DECL_FUNC_PTR(krb5_get_default_realm); +extern DECL_FUNC_PTR(krb5_free_ticket); +extern DECL_FUNC_PTR(krb5_decode_ticket); +extern DECL_FUNC_PTR(krb5_get_host_realm); +extern DECL_FUNC_PTR(krb5_free_host_realm); +extern DECL_FUNC_PTR(krb5_c_random_make_octets); +extern DECL_FUNC_PTR(krb5_free_default_realm); +extern DECL_FUNC_PTR(krb5_principal_compare); +extern DECL_FUNC_PTR(krb5_string_to_deltat); +extern DECL_FUNC_PTR(krb5_is_config_principal); +extern DECL_FUNC_PTR(krb5_cccol_cursor_new); +extern DECL_FUNC_PTR(krb5_cccol_cursor_next); +extern DECL_FUNC_PTR(krb5_cccol_cursor_free); +extern DECL_FUNC_PTR(krb5_cc_cache_match); +extern DECL_FUNC_PTR(krb5_cc_get_type); +extern DECL_FUNC_PTR(krb5_cc_new_unique); +extern DECL_FUNC_PTR(krb5_cc_support_switch); +extern DECL_FUNC_PTR(krb5_cc_switch); +extern DECL_FUNC_PTR(krb5int_cc_user_set_default_name); + +#ifndef NO_KRB4 +// Krb524 functions +extern DECL_FUNC_PTR(krb524_init_ets); +extern DECL_FUNC_PTR(krb524_convert_creds_kdc); +#endif + +// ComErr functions +extern DECL_FUNC_PTR(com_err); +extern DECL_FUNC_PTR(error_message); + +// Profile functions +extern DECL_FUNC_PTR(profile_init); +extern DECL_FUNC_PTR(profile_release); +extern DECL_FUNC_PTR(profile_get_subsection_names); +extern DECL_FUNC_PTR(profile_free_list); +extern DECL_FUNC_PTR(profile_get_string); +extern DECL_FUNC_PTR(profile_release_string); +extern DECL_FUNC_PTR(profile_get_integer); + +// Service functions + +extern DECL_FUNC_PTR(OpenSCManagerA); +extern DECL_FUNC_PTR(OpenServiceA); +extern DECL_FUNC_PTR(QueryServiceStatus); +extern DECL_FUNC_PTR(CloseServiceHandle); +extern DECL_FUNC_PTR(LsaNtStatusToWinError); + +// LSA Functions + +extern DECL_FUNC_PTR(LsaConnectUntrusted); +extern DECL_FUNC_PTR(LsaLookupAuthenticationPackage); +extern DECL_FUNC_PTR(LsaCallAuthenticationPackage); +extern DECL_FUNC_PTR(LsaFreeReturnBuffer); +extern DECL_FUNC_PTR(LsaGetLogonSessionData); + +#ifdef __cplusplus +} +#endif + +#endif /* _LEASHDLL_H_ */ diff --git a/src/windows/leashdll/leasherr.c b/src/windows/leashdll/leasherr.c new file mode 100644 index 000000000000..da06b5a8a9bb --- /dev/null +++ b/src/windows/leashdll/leasherr.c @@ -0,0 +1,105 @@ +// ATTENTION: someone in the past edited this file manually +// I am continuing this tradition just to get the release out. 3/6/97 +// This needs to be revisited and repaired!!!XXXX +// pbh + + + /* + * leasherr.c + * This file is the C file for leasherr.et. + * Please do not edit it as it is automatically generated. + */ + +#include <stdlib.h> +#include <windows.h> + +static const char* const text[] = { + "Only one instance of Leash can be run at a time.", + "Principal invalid.", + "Realm failed.", + "Instance invalid.", + "Realm invalid.", + "Unexpected end of Kerberos memory storage.", + "Warning! Your Kerberos tickets expire soon.", + "You did not type the same new password.", + "You can only use printable characters in a password.", + "Fatal error; cannot run this program.", + "Couldn't initialize WinSock.", + "Couldn't find the timeserver host entry.", + "Couldn't open a socket.", + "Couldn't connect to timeserver.", + "Couldn't get time from server.", + "Couldn't get local time of day.", + "Couldn't set local time of day.", + "Error while receiving time from server.", + "Protocol problem with timeserver.", + "The time was already reset. Try using a different program to synchronize the time.", + 0 +}; + +typedef LPSTR (*err_func)(int, long); +struct error_table { + char const * const * msgs; + err_func func; + long base; + int n_msgs; +}; +struct et_list { +#ifdef WINDOWS + HANDLE next; +#else + struct et_list *next; +#endif + const struct error_table * table; +}; + +static const struct error_table et = { text, (err_func)0, 40591872L, 20 }; + +#ifdef WINDOWS +void initialize_lsh_error_table(HANDLE *__et_list) { +// struct et_list *_link,*_et_list; + struct et_list *_link; + HANDLE ghlink; + + ghlink=GlobalAlloc(GHND,sizeof(struct et_list)); + _link=GlobalLock(ghlink); + _link->next=*__et_list; + _link->table=&et; + GlobalUnlock(ghlink); + *__et_list=ghlink; +} +#else +void initialize_lsh_error_table(struct et_list **__et_list) { + struct et_list *_link; + + _link=malloc(sizeof(struct et_list)); + _link->next=*__et_list; + _link->table=&et; + *__et_list=_link; +} +#endif + +#ifdef WINDOWS + +void Leash_initialize_krb_error_func(err_func func, HANDLE *__et_list) +{ +} + +void Leash_initialize_kadm_error_table(HANDLE *__et_list) +{ +} +#else +#include <krberr.h> + +void Leash_initialize_krb_error_func(err_func func, struct et_list **__et_list) +{ + (*pinitialize_krb_error_func)(func,__et_list); +} + +#include <kadm_err.h> + +void Leash_initialize_kadm_error_table(struct et_list **__et_list) +{ + initialize_kadm_error_table(__et_list); +} +#endif diff --git a/src/windows/leashdll/leasherr.et b/src/windows/leashdll/leasherr.et new file mode 100644 index 000000000000..d1d027bd1c41 --- /dev/null +++ b/src/windows/leashdll/leasherr.et @@ -0,0 +1,22 @@ +ERROR_TABLE lsh + ERROR_CODE LSH_ONLYONEME, "Only one instance of Leash can be run at a time." + ERROR_CODE LSH_INVPRINCIPAL, "Principal invalid." + ERROR_CODE LSH_FAILEDREALM, "Realm failed." + ERROR_CODE LSH_INVINSTANCE, "Instance invalid." + ERROR_CODE LSH_INVREALM, "Realm invalid." + ERROR_CODE LSH_EOF, "Unexpected end of Kerberos memory storage." + ERROR_CODE LSH_EXPIRESOON, "Warning! Your Kerberos tickets expire soon." + ERROR_CODE LSH_NOMATCH, "You did not type the same new password." + ERROR_CODE LSH_BADCHARS, "You can only use printable characters in a password." + ERROR_CODE LSH_FATAL_ERROR, "Fatal error; cannot run this program." + ERROR_CODE LSH_BADWINSOCK, "Couldn't initialize WinSock." + ERROR_CODE LSH_BADTIMESERV, "Couldn't find the timeserver host entry." + ERROR_CODE LSH_NOSOCKET, "Couldn't open a socket." + ERROR_CODE LSH_NOCONNECT, "Couldn't connect to timeserver." + ERROR_CODE LSH_TIMEFAILED, "Couldn't get time from server." + ERROR_CODE LSH_GETTIMEOFDAY, "Couldn't get local time of day." + ERROR_CODE LSH_SETTIMEOFDAY, "Couldn't set local time of day." + ERROR_CODE LSH_RECVTIME, "Error while receiving time from server." + ERROR_CODE LSH_RECVBYTES, "Protocol problem with timeserver." + ERROR_CODE LSH_ALREADY_SETTIME, "The time was already reset. Try using a different program to synchronize the time." +end diff --git a/src/windows/leashdll/leashids.h b/src/windows/leashdll/leashids.h new file mode 100644 index 000000000000..94e05b6b608a --- /dev/null +++ b/src/windows/leashdll/leashids.h @@ -0,0 +1,117 @@ +// *** Child Windows +#define ID_MAINLIST 100 +#define ID_COUNTDOWN 101 + +#define ID_DESTROY 111 +#define ID_CHANGEPASSWORD 112 +#define ID_INITTICKETS 113 +#define ID_SYNCTIME 114 + +#define ID_UPDATESTATE 120 +#define ID_UPDATEDISPLAY 121 +#define ID_KRBDLL_DEBUG 122 + + +// *** Menus + +#define ID_EXIT 200 + +#define ID_HELP_LEASH 210 +#define ID_HELP_KERBEROS 211 +#define ID_ABOUT 212 + +#define ID_CHECKV 299 + +// *** Password Dialog +#define ID_PRINCIPAL 301 +#define ID_OLDPASSWORD 302 +#define ID_CONFIRMPASSWORD1 303 +#define ID_CONFIRMPASSWORD2 304 +#define ID_PICFRAME 305 + +#define ID_PRINCCAPTION 311 +#define ID_OLDPCAPTION 312 +#define ID_CONFIRMCAPTION1 313 +#define ID_CONFIRMCAPTION2 314 +#define CAPTION_OFFSET 10 + +#define ID_DURATION 320 + +#define ID_RESTART 351 + +#define ID_CLOSEME 380 + +// *** About dialog stuff +#define ID_LEASH_CPYRT 400 +#define ID_LEASH_AUTHOR 401 +#define ID_KERB_CPYRT 402 +#define ID_KERB_AUTHOR 403 +#define ID_LEGALESE 404 +#define ID_ASSISTANCE 405 + +// *** Keyboard accelerator crud +#define ID_HELP 1000 +#define ID_CONTEXTSENSITIVEHELP 1001 +#define ID_ENDCSHELP 1002 +#define ID_HELPFIRST 1000 +#define ID_HELPLAST 1002 + +// *** window messages +#define WM_STARTUP (WM_USER + 1) +#define WM_F1DOWN (WM_USER + 2) +#define WM_DOHELP (WM_USER + 3) +#define WM_PAINTICON 0x0026 + +// *** command messages +#define ID_NEXTSTATE 10000 + +#define LSH_TIME_HOST 1970 +#define LSH_DEFAULT_TICKET_LIFE 1971 +#define LSH_DEFAULT_TICKET_RENEW_TILL 1972 +#define LSH_DEFAULT_TICKET_FORWARD 1973 +#define LSH_DEFAULT_TICKET_NOADDRESS 1974 +#define LSH_DEFAULT_TICKET_PROXIABLE 1975 +#define LSH_DEFAULT_TICKET_PUBLICIP 1976 +#define LSH_DEFAULT_TICKET_USEKRB4 1977 +#define LSH_DEFAULT_DIALOG_KINIT_OPT 1978 +#define LSH_DEFAULT_DIALOG_LIFE_MIN 1979 +#define LSH_DEFAULT_DIALOG_LIFE_MAX 1980 +#define LSH_DEFAULT_DIALOG_RENEW_MIN 1981 +#define LSH_DEFAULT_DIALOG_RENEW_MAX 1982 +#define LSH_DEFAULT_TICKET_RENEW 1983 +#define LSH_DEFAULT_DIALOG_LOCK_LOCATION 1984 +#define LSH_DEFAULT_UPPERCASEREALM 1985 +#define LSH_DEFAULT_MSLSA_IMPORT 1986 +#define LSH_DEFAULT_PRESERVE_KINIT 1987 + +// Authenticate Dialog +#define IDD_AUTHENTICATE 1162 +#define IDC_STATIC_IPADDR 1163 +#define IDC_STATIC_NAME 1164 +#define IDC_STATIC_PWD 1165 +#define IDC_EDIT_PRINCIPAL 1166 +#define IDC_COMBO_REALM 1167 +#define IDC_EDIT_PASSWORD 1168 +#define IDC_STATIC_LIFETIME 1169 +#define IDC_SLIDER_LIFETIME 1170 +#define IDC_STATIC_KRB5 1171 +#define IDC_CHECK_FORWARDABLE 1172 +#define IDC_CHECK_NOADDRESS 1173 +#define IDC_CHECK_RENEWABLE 1174 +#define IDC_SLIDER_RENEWLIFE 1175 +#define IDC_STATIC_LIFETIME_VALUE 1176 +#define IDC_STATIC_RENEW_TILL_VALUE 1177 +#define IDC_PICTURE_LEASH 1179 +#define IDC_BUTTON_OPTIONS 1086 +#define IDC_STATIC_REALM 1087 +#define IDC_STATIC_COPYRIGHT 1088 +#define IDC_STATIC_NOTICE 1089 +#define IDC_STATIC_RENEW 1090 +#define IDD_PASSWORD 1091 +#define IDC_BUTTON_CLEAR_HISTORY 1092 +#define IDC_CHECK_REMEMBER_PRINCIPAL 1093 +#define IDC_EDIT_PASSWORD2 1192 +#define IDC_STATIC_PWD2 1193 +#define IDC_EDIT_PASSWORD3 1194 +#define IDC_STATIC_PWD3 1195 +#define IDC_STATIC_VERSION 1196 diff --git a/src/windows/leashdll/leashw32.def b/src/windows/leashdll/leashw32.def new file mode 100644 index 000000000000..a45392475b64 --- /dev/null +++ b/src/windows/leashdll/leashw32.def @@ -0,0 +1,107 @@ +LIBRARY LEASHW32 + +DESCRIPTION 'DLL for Kerberos ticket initialization' + +HEAPSIZE 8092 +STACKSIZE 36864 + +EXPORTS +; DllMain @1 + ; Leash_kinit_dlg @3 + ; Leash_changepwd_dlg @4 + ; Leash_kinit @48 + ; Leash_kdestroy @49 + ; Leash_klist @50 + ; Leash_checkpwd @51 + ; Leash_changepwd @52 + ; Leash_get_lsh_errno @61 + ; initialize_lsh_error_table @80 + ; lsh_com_err_proc @81 + ; Leash_initialize_krb_error_func @82 + ; Leash_initialize_kadm_error_table @83 + ; Leash_krb_err_func @84 + ; Leash_load_com_err_callback @85 + ; Leash_set_help_file @86 + ; Leash_get_help_file @87 + ; Leash_timesync @88 +; Leash_WhichOS @89 + + Leash_kinit_dlg + Leash_kinit_dlg_ex + Leash_changepwd_dlg + Leash_changepwd_dlg_ex + Leash_kinit + Leash_kinit_ex + Leash_kdestroy + Leash_klist + Leash_checkpwd + Leash_changepwd + Leash_get_lsh_errno + initialize_lsh_error_table + lsh_com_err_proc + Leash_initialize_krb_error_func + Leash_initialize_kadm_error_table + Leash_krb_err_func + Leash_load_com_err_callback + Leash_set_help_file + Leash_get_help_file + Leash_timesync + Leash_get_default_lifetime + Leash_set_default_lifetime + Leash_reset_default_lifetime + Leash_get_default_renew_till + Leash_set_default_renew_till + Leash_reset_default_renew_till + Leash_get_default_forwardable + Leash_set_default_forwardable + Leash_reset_default_forwardable + Leash_get_default_renewable + Leash_set_default_renewable + Leash_reset_default_renewable + Leash_get_default_noaddresses + Leash_set_default_noaddresses + Leash_reset_default_noaddresses + Leash_get_default_proxiable + Leash_set_default_proxiable + Leash_reset_default_proxiable + Leash_get_default_publicip + Leash_set_default_publicip + Leash_reset_default_publicip + Leash_get_default_use_krb4 + Leash_set_default_use_krb4 + Leash_reset_default_use_krb4 + Leash_get_default_life_min + Leash_set_default_life_min + Leash_reset_default_life_min + Leash_get_default_life_max + Leash_set_default_life_max + Leash_reset_default_life_max + Leash_get_default_renew_min + Leash_set_default_renew_min + Leash_reset_default_renew_min + Leash_get_default_renew_max + Leash_set_default_renew_max + Leash_reset_default_renew_max + Leash_get_lock_file_locations + Leash_set_lock_file_locations + Leash_reset_lock_file_locations + Leash_get_default_uppercaserealm + Leash_set_default_uppercaserealm + Leash_reset_default_uppercaserealm + Leash_get_default_mslsa_import + Leash_set_default_mslsa_import + Leash_reset_default_mslsa_import + Leash_get_default_preserve_kinit_settings + Leash_set_default_preserve_kinit_settings + Leash_reset_default_preserve_kinit_settings + Leash_import + Leash_importable + Leash_renew + Leash_reset_defaults + + ; XXX - These have to go... + not_an_API_LeashAFSGetToken + not_an_API_LeashFreeTicketList + not_an_API_LeashKRB4GetTickets + not_an_API_LeashGetTimeServerName + not_an_API_Leash_AcquireInitialTicketsIfNeeded diff --git a/src/windows/leashdll/lsh_pwd.c b/src/windows/leashdll/lsh_pwd.c new file mode 100644 index 000000000000..ac85625a0bef --- /dev/null +++ b/src/windows/leashdll/lsh_pwd.c @@ -0,0 +1,1991 @@ +#define SCALE_FACTOR 31/20 + +/* LSH_PWD.C + + Jason Hunter + 8/2/94 + DCNS/IS MIT + + Re-written for KFW 2.6 by Jeffrey Altman <jaltman@mit.edu> + + Contains the callback functions for the EnterPassword an + ChangePassword dialog boxes and well as the API function + calls: + + Lsh_Enter_Password_Dialog + Lsh_Change_Password_Dialog + + for calling the dialogs. + + Also contains the callback for the MITPasswordControl. + +*/ + +/* Standard Include files */ +#include <windows.h> +#include <stdio.h> +#include <string.h> + +/* Private Inlclude files */ +#include "leashdll.h" +#include <conf.h> +#include <leashwin.h> +#include "leash-int.h" +#include "leashids.h" +#include <leasherr.h> +#ifndef NO_KRB5 +#include <krb5.h> +#endif /* NO_KRB5 */ +#include <commctrl.h> + +extern void * Leash_pec_create(HWND hEditCtl); +extern void Leash_pec_destroy(void *pAutoComplete); +extern void Leash_pec_add_principal(char *principal); +extern void Leash_pec_clear_history(void *pec); + +/* Global Variables. */ +static long lsh_errno; +static char *err_context; /* error context */ +extern HINSTANCE hLeashInst; +extern HINSTANCE hKrb4; +extern HINSTANCE hKrb5; + + +INT_PTR +CALLBACK +PasswordProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ); + +INT_PTR +CALLBACK +AuthenticateProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ); + +INT_PTR +CALLBACK +NewPasswordProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ); + + +long Leash_get_lsh_errno(LONG *err_val) +{ + return lsh_errno; +} + +/*/////// ******** API Calls follow here. ******** /////////*/ + +static int +NetId_dialog(LPLSH_DLGINFO lpdlginfo) +{ + LRESULT lrc; + HWND hNetIdMgr; + HWND hForeground; + + hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon"); + if (hNetIdMgr != NULL) { + char desiredPrincipal[512]; + NETID_DLGINFO *dlginfo; + char *desiredName = 0; + char *desiredRealm = 0; + HANDLE hMap; + DWORD tid = GetCurrentThreadId(); + char mapname[256]; + + strcpy(desiredPrincipal, lpdlginfo->principal); + + /* do we want a specific client principal? */ + if (desiredPrincipal[0]) { + char * p; + desiredName = desiredPrincipal; + for (p = desiredName; *p && *p != '@'; p++); + if ( *p == '@' ) { + *p = '\0'; + desiredRealm = ++p; + } + } + + sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid); + + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, + 0, 4096, mapname); + if (hMap == NULL) { + return -1; + } else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) { + CloseHandle(hMap); + return -1; + } + + dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE, + 0, 0, 4096, NULL); + if (dlginfo == NULL) { + CloseHandle(hMap); + return -1; + } + + hForeground = GetForegroundWindow(); + + memset(dlginfo, 0, sizeof(NETID_DLGINFO)); + + dlginfo->size = sizeof(NETID_DLGINFO); + if (lpdlginfo->dlgtype == DLGTYPE_PASSWD) + dlginfo->dlgtype = NETID_DLGTYPE_TGT; + else + dlginfo->dlgtype = NETID_DLGTYPE_CHPASSWD; + dlginfo->in.use_defaults = 1; + + if (lpdlginfo->title) { + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + lpdlginfo->title, -1, + dlginfo->in.title, NETID_TITLE_SZ); + } else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) { + char mytitle[NETID_TITLE_SZ]; + sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + mytitle, -1, + dlginfo->in.title, NETID_TITLE_SZ); + } else { + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + "Obtain Kerberos TGT", -1, + dlginfo->in.title, NETID_TITLE_SZ); + } + if (desiredName) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + desiredName, -1, + dlginfo->in.username, NETID_USERNAME_SZ); + if (desiredRealm) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + desiredRealm, -1, + dlginfo->in.realm, NETID_REALM_SZ); + lrc = SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid); + + UnmapViewOfFile(dlginfo); + CloseHandle(hMap); + + SetForegroundWindow(hForeground); + return lrc; + } + return -1; +} + +static int +NetId_dialog_ex(LPLSH_DLGINFO_EX lpdlginfo) +{ + HWND hNetIdMgr; + HWND hForeground; + + hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon"); + if (hNetIdMgr != NULL) { + NETID_DLGINFO *dlginfo; + char *desiredName = lpdlginfo->username; + char *desiredRealm = lpdlginfo->realm; + LPSTR title; + char *ccache; + LRESULT lrc; + HANDLE hMap; + DWORD tid = GetCurrentThreadId(); + char mapname[256]; + + sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid); + + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, + 0, 4096, mapname); + if (hMap == NULL) { + return -1; + } else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) { + CloseHandle(hMap); + return -1; + } + + dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE, + 0, 0, 4096, NULL); + if (dlginfo == NULL) { + CloseHandle(hMap); + return -1; + } + + hForeground = GetForegroundWindow(); + + if (lpdlginfo->size == LSH_DLGINFO_EX_V1_SZ || + lpdlginfo->size == LSH_DLGINFO_EX_V2_SZ) + { + title = lpdlginfo->title; + desiredName = lpdlginfo->username; + desiredRealm = lpdlginfo->realm; + ccache = NULL; + } else { + title = lpdlginfo->in.title; + desiredName = lpdlginfo->in.username; + desiredRealm = lpdlginfo->in.realm; + ccache = lpdlginfo->in.ccache; + } + + memset(dlginfo, 0, sizeof(NETID_DLGINFO)); + + dlginfo->size = sizeof(NETID_DLGINFO); + if (lpdlginfo->dlgtype == DLGTYPE_PASSWD) + dlginfo->dlgtype = NETID_DLGTYPE_TGT; + else + dlginfo->dlgtype = NETID_DLGTYPE_CHPASSWD; + + dlginfo->in.use_defaults = lpdlginfo->use_defaults; + dlginfo->in.forwardable = lpdlginfo->forwardable; + dlginfo->in.noaddresses = lpdlginfo->noaddresses; + dlginfo->in.lifetime = lpdlginfo->lifetime; + dlginfo->in.renew_till = lpdlginfo->renew_till; + dlginfo->in.proxiable = lpdlginfo->proxiable; + dlginfo->in.publicip = lpdlginfo->publicip; + + if (title) { + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + title, -1, + dlginfo->in.title, NETID_TITLE_SZ); + } else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) { + char mytitle[NETID_TITLE_SZ]; + sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + mytitle, -1, + dlginfo->in.title, NETID_TITLE_SZ); + } else { + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + "Obtain Kerberos TGT", -1, + dlginfo->in.title, NETID_TITLE_SZ); + } + if (desiredName) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + desiredName, -1, + dlginfo->in.username, NETID_USERNAME_SZ); + if (desiredRealm) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + desiredRealm, -1, + dlginfo->in.realm, NETID_REALM_SZ); + if (ccache) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + ccache, -1, + dlginfo->in.ccache, NETID_CCACHE_NAME_SZ); + lrc = SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid); + + if (lrc > 0) { + if (lpdlginfo->size == LSH_DLGINFO_EX_V2_SZ) + { + WideCharToMultiByte(CP_ACP, 0, dlginfo->out.username, -1, + lpdlginfo->out.username, LEASH_USERNAME_SZ, + NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, dlginfo->out.realm, -1, + lpdlginfo->out.realm, LEASH_REALM_SZ, + NULL, NULL); + } + if (lpdlginfo->size == LSH_DLGINFO_EX_V3_SZ) + { + WideCharToMultiByte(CP_ACP, 0, dlginfo->out.ccache, -1, + lpdlginfo->out.ccache, LEASH_CCACHE_NAME_SZ, + NULL, NULL); + } + } + + UnmapViewOfFile(dlginfo); + CloseHandle(hMap); + + SetForegroundWindow(hForeground); + return lrc; + } + return -1; +} + + +#define LEASH_DLG_MUTEX_NAME TEXT("Leash_Dialog_Mutex") +int Leash_kinit_dlg(HWND hParent, LPLSH_DLGINFO lpdlginfo) +{ + int rc; + HANDLE hMutex; + + rc = NetId_dialog(lpdlginfo); + if (rc > -1) + return rc; + + hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME); + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) { + return -1; + } + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return 1; /* pretend the dialog was displayed and succeeded */ + } + + lpdlginfo->dlgtype = DLGTYPE_PASSWD; + + /* set the help file */ + Leash_set_help_file(NULL); + + /* Call the Dialog box with the DLL's Password Callback and the + DLL's instance handle. */ + rc = DialogBoxParam(hLeashInst, "EnterPasswordDlg", hParent, + PasswordProc, (LPARAM)lpdlginfo); + + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return rc; +} + + +int Leash_kinit_dlg_ex(HWND hParent, LPLSH_DLGINFO_EX lpdlginfo) +{ + int rc; + HANDLE hMutex; + + rc = NetId_dialog_ex(lpdlginfo); + if (rc > -1) + return rc; + + hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME); + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) { + return -1; + } + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return 1; /* pretend the dialog was displayed and succeeded */ + } + + /* set the help file */ + Leash_set_help_file(NULL); + + /* Call the Dialog box with the DLL's Password Callback and the + DLL's instance handle. */ + rc = DialogBoxParam(hLeashInst, MAKEINTRESOURCE(IDD_AUTHENTICATE), hParent, + AuthenticateProc, (LPARAM)lpdlginfo); + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return rc; +} + + +int Leash_changepwd_dlg(HWND hParent, LPLSH_DLGINFO lpdlginfo) +{ + int rc; + HANDLE hMutex; + + rc = NetId_dialog(lpdlginfo); + if (rc > -1) + return rc; + + hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME); + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) { + return -1; + } + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return 1; /* pretend the dialog was displayed and succeeded */ + } + + lpdlginfo->dlgtype = DLGTYPE_CHPASSWD; + + /* Call the Dialog box with the DLL's Password Callback and the + DLL's instance handle. */ + rc = DialogBoxParam(hLeashInst, "CHANGEPASSWORDDLG", hParent, + PasswordProc, (LPARAM)lpdlginfo); + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return rc; +} + +int Leash_changepwd_dlg_ex(HWND hParent, LPLSH_DLGINFO_EX lpdlginfo) +{ + int rc; + HANDLE hMutex; + + rc = NetId_dialog_ex(lpdlginfo); + if (rc > -1) + return rc; + + hMutex = CreateMutex(NULL, TRUE, LEASH_DLG_MUTEX_NAME); + if ( GetLastError() == ERROR_ALREADY_EXISTS ) { + if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) { + return -1; + } + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return 1; /* pretend the dialog was displayed and succeeded */ + } + + lpdlginfo->dlgtype = DLGTYPE_CHPASSWD; + + /* Call the Dialog box with the DLL's Password Callback and the + DLL's instance handle. */ + rc = DialogBoxParam(hLeashInst, MAKEINTRESOURCE(IDD_PASSWORD), hParent, + NewPasswordProc, (LPARAM)lpdlginfo); + ReleaseMutex(hMutex); + CloseHandle(hMutex); + return rc; +} + + +/* These little utils are taken from lshutil.c + they are added here for the Call back funtion. +****** beginning of added utils from lshutil.c ******/ + +BOOL IsDlgItem(HWND hWnd, WORD id) +{ + HWND hChild; + + hChild = GetDlgItem(hWnd, id); + return hChild ? IsWindow(hChild) : 0; +} + +int lsh_getkeystate(WORD keyid) +{ + static BYTE keys[256]; + + GetKeyboardState((LPBYTE) &keys); + return (int) keys[keyid]; +} + +LPSTR krb_err_func(int offset, long code) +{ + return(NULL); +} + +/****** End of Added utils from leash.c ******/ + + +int PaintLogoBitmap( HANDLE hPicFrame ) +{ + HBITMAP hBitmap; + HBITMAP hOldBitmap; + BITMAP Bitmap; + HDC hdc, hdcMem; + RECT rect; + + /* Invalidate the drawing space of the picframe. */ + InvalidateRect( hPicFrame, NULL, TRUE); + UpdateWindow( hPicFrame ); + + hdc = GetDC(hPicFrame); + hdcMem = CreateCompatibleDC(hdc); + GetClientRect(hPicFrame, &rect); + hBitmap = LoadBitmap(hLeashInst, "LOGOBITMAP"); + hOldBitmap = SelectObject(hdcMem, hBitmap); + GetObject(hBitmap, sizeof(Bitmap), (LPSTR) &Bitmap); + StretchBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, + Bitmap.bmWidth, Bitmap.bmHeight, SRCCOPY); + + SelectObject(hdcMem, hOldBitmap); /* pbh 8-15-94 */ + ReleaseDC(hPicFrame, hdc); + DeleteObject( hBitmap ); /* pbh 8-15-94 */ + DeleteDC( hdcMem ); /* pbh 8-15-94 */ + + return 0; +} + + +/* Callback function for the Password Dialog box that initilializes and + renews tickets. */ + +INT_PTR +CALLBACK +PasswordProc( + HWND hDialog, + UINT message, + WPARAM wParam, + LPARAM lParam + ) +{ + static POINT Position = { -1, -1 }; + static short state; + int lifetime; +#define ISCHPASSWD (lpdi->dlgtype == DLGTYPE_CHPASSWD) +#define STATE_INIT 0 +#define STATE_PRINCIPAL 1 +#define STATE_OLDPWD 2 +#define STATE_NEWPWD1 3 +#define STATE_NEWPWD2 4 +#define STATE_CLOSED 5 +#define NEXTSTATE(newstate) SendMessage(hDialog, WM_COMMAND, ID_NEXTSTATE, newstate) + static int ids[STATE_NEWPWD2 + 1] = { + 0, + ID_PRINCIPAL, ID_OLDPASSWORD, ID_CONFIRMPASSWORD1, + ID_CONFIRMPASSWORD2}; + static char principal[255], oldpassword[255], newpassword[255], + newpassword2[255]; + static char *strings[STATE_NEWPWD2 + 1] = { + NULL, principal, oldpassword, newpassword, newpassword2}; + static LPLSH_DLGINFO lpdi; + char gbuf[200]; /* global buffer for random stuff. */ + + +#define checkfirst(id, stuff) IsDlgItem(hDialog, id) ? stuff : 0 +#define CGetDlgItemText(hDlg, id, cp, len) checkfirst(id, GetDlgItemText(hDlg, id, cp, len)) +#define CSetDlgItemText(hDlg, id, cp) checkfirst(id, SetDlgItemText(hDlg, id, cp)) +#define CSetDlgItemInt(hDlg, id, i, b) checkfirst(id, SetDlgItemInt(hDlg, id, i, b)) +#define CSendDlgItemMessage(hDlg, id, m, w, l) checkfirst(id, SendDlgItemMessage(hDlg, id, m, w, l)) +#define CSendMessage(hwnd, m, w, l) IsWindow(hwnd) ? SendMessage(hwnd, m, w, l) : 0 +#define CShowWindow(hwnd, state) IsWindow(hwnd) ? ShowWindow(hwnd, state) : 0 + +#define GETITEMTEXT(id, cp, maxlen) \ + GetDlgItemText(hDialog, id, (LPSTR)(cp), maxlen) +#define CloseMe(x) SendMessage(hDialog, WM_COMMAND, ID_CLOSEME, x) + + +#define EDITFRAMEIDOFFSET 500 + + switch (message) { + + case WM_INITDIALOG: + + *( (LPLSH_DLGINFO far *)(&lpdi) ) = (LPLSH_DLGINFO)(LPSTR)lParam; + lpdi->dlgstatemax = ISCHPASSWD ? STATE_NEWPWD2 + : STATE_OLDPWD; + SetWindowText(hDialog, lpdi->title); + /* stop at old password for normal password dlg */ + + SetProp(hDialog, "HANDLES_HELP", (HANDLE)1); + + if (lpdi->principal) + lstrcpy(principal, lpdi->principal); + else + { + principal[0] = '\0'; + /* is there a principal already being used? if so, use it. */ + } + + CSetDlgItemText(hDialog, ID_PRINCIPAL, principal); + + lifetime = Leash_get_default_lifetime(); + if (lifetime <= 0) + lifetime = 600; /* 10 hours */ + + CSetDlgItemInt(hDialog, ID_DURATION, lifetime, FALSE); + + /* setup text of stuff. */ + + if (Position.x > 0 && Position.y > 0 && + Position.x < GetSystemMetrics(SM_CXSCREEN) && + Position.y < GetSystemMetrics(SM_CYSCREEN)) + SetWindowPos(hDialog, 0, Position.x, Position.y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + + /* set window pos to last saved window pos */ + + + /* replace standard edit control with our own password edit + control for password entry. */ + { + RECT r; + POINT pxy, psz; + HWND hwnd; + int i; + + for (i = ID_OLDPASSWORD; i <= ids[lpdi->dlgstatemax]; i++) + { + hwnd = GetDlgItem(hDialog, i); + GetWindowRect(hwnd, &r); + psz.x = r.right - r.left; + psz.y = r.bottom - r.top; + + pxy.x = r.left; pxy.y = r.top; + ScreenToClient(hDialog, &pxy); + + /* create a substitute window: */ + + DestroyWindow(hwnd); + /* kill off old edit window. */ + + CreateWindow(MIT_PWD_DLL_CLASS, /* our password window :o] */ + "", /* no text */ + WS_CHILD | WS_VISIBLE | WS_TABSTOP, /* child window, visible,tabstop */ + pxy.x, pxy.y, /* x, y coords */ + psz.x, psz.y, /* width, height */ + hDialog, /* the parent */ + (HMENU)i, /* same id *//* id offset for the frames */ + (HANDLE)hLeashInst,/* instance handles */ + NULL); /* createstruct */ + } + } + + state = STATE_INIT; + NEXTSTATE(STATE_PRINCIPAL); + break; + + case WM_PAINT: + PaintLogoBitmap( GetDlgItem(hDialog, ID_PICFRAME) ); + break; + + case WM_COMMAND: + switch (wParam) { + case ID_HELP: + { + WinHelp(GetWindow(hDialog,GW_OWNER), KRB_HelpFile, HELP_CONTEXT, + ISCHPASSWD ? ID_CHANGEPASSWORD : ID_INITTICKETS); + } + break; + case ID_CLOSEME: + { + int i; + + for (i = STATE_PRINCIPAL; i <= lpdi->dlgstatemax; i++) + { + memset(strings[i], '\0', 255); + SetDlgItemText(hDialog, ids[i], ""); + } + /* I claim these passwords in the name + of planet '\0'... */ + + RemoveProp(hDialog, "HANDLES_HELP"); + state = STATE_CLOSED; + EndDialog(hDialog, (int)lParam); + return TRUE; + } + break; + case ID_DURATION: + break; + case ID_PRINCIPAL: + case ID_OLDPASSWORD: + case ID_CONFIRMPASSWORD1: + case ID_CONFIRMPASSWORD2: + if (HIWORD(lParam) == EN_SETFOCUS) + { + /* nothing, for now. */ + } + break; + case ID_NEXTSTATE: + { + RECT rbtn, redit; + POINT p; + int idfocus, i, s; + HWND hfocus, hbtn; + int oldstate = state; + + state = (int)lParam; + idfocus = ids[state]; + +#ifdef ONE_NEWPWDBOX + if (state == STATE_NEWPWD2) + SendDlgItemMessage(hDialog, ID_CONFIRMPASSWORD1, WM_SETTEXT, + 0, (LONG)(LPSTR)""); +#endif + + for (s = STATE_PRINCIPAL; s <= lpdi->dlgstatemax; s++) + { + i = ids[s]; + + if (s > state) + SendDlgItemMessage(hDialog, i, WM_SETTEXT, 0, + (LONG)(LPSTR)""); + EnableWindow(GetDlgItem(hDialog, i), i == idfocus); + ShowWindow(GetDlgItem(hDialog, i), + (i <= idfocus ? SW_SHOW : SW_HIDE)); + /* ShowWindow(GetDlgItem(hDialog, i + CAPTION_OFFSET), + (i <= idfocus ? SW_SHOW : SW_HIDE));*/ + /* show caption? */ + } +#ifdef ONE_NEWPWDBOX + CSetDlgItemText(hDialog, ID_CONFIRMCAPTION1, + state < STATE_NEWPWD2 ? + "Enter new password:" : + "Enter new password again:"); + if (state == STATE_NEWPWD2) + { + HWND htext; + htext = GetDlgItem(hDialog, ID_CONFIRMCAPTION1); + FlashAnyWindow(htext); + WinSleep(50); + FlashAnyWindow(htext); + } +#endif + + hfocus = GetDlgItem(hDialog, idfocus); + if ( hfocus != (HWND)NULL ){ + SetFocus(hfocus); /* switch focus */ + if (idfocus >= ID_OLDPASSWORD) + SendMessage(hfocus, WM_SETTEXT, 0, (LPARAM) (LPSTR) ""); + else + { + SendMessage(hfocus, EM_SETSEL, 0, MAKELONG(0, -1)); + } + GetWindowRect(hfocus, &redit); + } + + hbtn = GetDlgItem(hDialog, IDOK); + if( IsWindow(hbtn) ){ + GetWindowRect(hbtn, &rbtn); + p.x = rbtn.left; p.y = redit.top; + ScreenToClient(hDialog, &p); + + SetWindowPos(hbtn, 0, p.x, p.y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + } + } + break; + case IDOK: + { + char* p_Principal; + DWORD value = 0; + + GETITEMTEXT(ids[state], (LPSTR)strings[state], 255); + + switch(state) + { + case STATE_PRINCIPAL: + { + if (!principal[0]) + { + MessageBox(hDialog, + "You are not allowed to enter a blank principal.", + "Invalid Principal", + MB_OK | MB_ICONSTOP); + NEXTSTATE(STATE_PRINCIPAL); + return TRUE; + } + + // Change 'principal' to upper case after checking + // "UpperCase" value in the Registry + p_Principal = strchr(principal, '@'); + + if (p_Principal && Leash_get_default_uppercaserealm()) + strupr(p_Principal); + break; + } + case STATE_OLDPWD: + { + int duration; + + if (!ISCHPASSWD) + duration = GetDlgItemInt(hDialog, ID_DURATION, 0, FALSE); + if (!oldpassword[0]) + { + MessageBox(hDialog, "You are not allowed to enter a " + "blank password.", + "Invalid Password", + MB_OK | MB_ICONSTOP); + NEXTSTATE(STATE_OLDPWD); + return TRUE; + } + if (lpdi->dlgtype == DLGTYPE_CHPASSWD) + lsh_errno = Leash_int_checkpwd(principal, oldpassword, 1); + else + { + lsh_errno = Leash_int_kinit_ex( 0, + hDialog, + principal, + oldpassword, + duration, + Leash_get_default_forwardable(), + Leash_get_default_proxiable(), + Leash_get_default_renew_till(), + Leash_get_default_noaddresses(), + Leash_get_default_publicip(), + 1 + ); + } + if (lsh_errno != 0) + { + int next_state = state; + int capslock; + char *cp; + + err_context = ""; + + switch(lsh_errno) + { + case LSH_INVPRINCIPAL: + case LSH_INVINSTANCE: + case LSH_INVREALM: + next_state = STATE_PRINCIPAL; + break; + } + capslock = lsh_getkeystate(VK_CAPITAL); + /* low-order bit means caps lock is + toggled; if so, warn user since there's + been an error. */ + if (capslock & 1) + { + lstrcpy((LPSTR)gbuf, (LPSTR)err_context); + cp = gbuf + lstrlen((LPSTR)gbuf); + if (cp != gbuf) + *cp++ = ' '; + lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)"); + err_context = gbuf; + } + +// XXX DoNiftyErrorReport(lsh_errno, ISCHPASSWD ? "" +// XXX : "Ticket initialization failed."); + NEXTSTATE(next_state); + return TRUE; + } + if (ISCHPASSWD) + break; + CloseMe(TRUE); /* success */ + } + break; + case STATE_NEWPWD1: + { + int i = 0; + int bit8 = 0; + + for( i = 0; i < 255; i++ ){ + if( newpassword[i] == '\0' ){ + if ( bit8 ) { + MessageBox(hDialog, + "Passwords should not contain non-ASCII characters.", + "Internationalization Warning", + MB_OK | MB_ICONINFORMATION); + } + i = 255; + break; + } else if( !isprint(newpassword[i]) ){ + memset(newpassword, '\0', 255); + /* I claim these passwords in the name of planet '\0'... */ + MessageBox(hDialog, + "Passwords may not contain non-printable characters.", + "Invalid Password", + MB_OK | MB_ICONSTOP); + NEXTSTATE(STATE_NEWPWD1); + return TRUE; + } else if ( newpassword[i] > 127 ) + bit8 = 1; + } + } + break; + case STATE_NEWPWD2: + if (lstrcmp(newpassword, newpassword2)) + { + NEXTSTATE(STATE_NEWPWD1); + MessageBox(hDialog, + "The new password was not entered the same way twice.", + "Password validation error", + MB_OK | MB_ICONSTOP); + return TRUE; + } + else + { + /* make them type both pwds again if error */ + int next_state = STATE_NEWPWD1; + int capslock; + char *cp; + + capslock = lsh_getkeystate(VK_CAPITAL); + /* low-order bit means caps lock is + toggled; if so, warn user since there's + been an error. */ + if (capslock & 1) + { + lstrcpy((LPSTR)gbuf, (LPSTR)err_context); + cp = gbuf + lstrlen((LPSTR)gbuf); + if (cp != gbuf) + *cp++ = ' '; + lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)"); + err_context = gbuf; + } + + if ((lsh_errno = + Leash_int_changepwd(principal, oldpassword, + newpassword, 0, 1)) + == 0){ + CloseMe(TRUE); + } + else { + // XXX - DoNiftyErrorReport(lsh_errno, "Error while changing password."); + NEXTSTATE(next_state); + return TRUE; + + } + } + break; + } + /* increment state, but send the old state as a + parameter */ + SendMessage(hDialog, WM_COMMAND, ID_NEXTSTATE, state + 1); + } + break; + case IDCANCEL: + CloseMe(FALSE); + break; + case ID_RESTART: + { + int i; + + for (i = ID_OLDPASSWORD; i <= ids[lpdi->dlgstatemax]; i++) + SetDlgItemText(hDialog, i, ""); + SendMessage(hDialog, WM_COMMAND, ID_NEXTSTATE, + STATE_PRINCIPAL); + } + break; + } + break; + + case WM_MOVE: + if (state != STATE_CLOSED) +#ifdef _WIN32 +#define LONG2POINT(l,pt) ((pt).x=(SHORT)LOWORD(l), \ + (pt).y=(SHORT)HIWORD(l)) + LONG2POINT(lParam,Position); +#else + Position = MAKEPOINT(lParam); +#endif + break; + } + return FALSE; +} + + +#define KRB_FILE "KRB.CON" +#define KRBREALM_FILE "KRBREALM.CON" +#define KRB5_FILE "KRB5.INI" + +BOOL +GetProfileFile( + LPSTR confname, + UINT szConfname + ) +{ + char **configFile = NULL; + if (hKrb5 && + pkrb5_get_default_config_files(&configFile)) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname, "\\",sizeof(confname)-strlen(confname)); + confname[szConfname-1] = '\0'; + strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname)); + confname[szConfname-1] = '\0'; + return FALSE; + } + + *confname = 0; + + if (hKrb5 && configFile) + { + strncpy(confname, *configFile, szConfname); + pkrb5_free_config_files(configFile); + } + + if (!*confname) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname, "\\",sizeof(confname)-strlen(confname)); + confname[szConfname-1] = '\0'; + strncat(confname, KRB5_FILE,sizeof(confname)-strlen(confname)); + confname[szConfname-1] = '\0'; + } + + return FALSE; +} + +BOOL +GetKrb4ConFile( + LPSTR confname, + UINT szConfname + ) +{ + if (hKrb5 + ) + { // hold krb.con where krb5.ini is located + CHAR krbConFile[MAX_PATH]=""; + LPSTR pFind; + + //strcpy(krbConFile, CLeashApp::m_krbv5_profile->first_file->filename); + if (GetProfileFile(krbConFile, sizeof(krbConFile))) + { + GetWindowsDirectory(krbConFile,sizeof(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + strncat(krbConFile, KRB5_FILE,sizeof(krbConFile)-strlen(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + } + + pFind = strrchr(krbConFile, '\\'); + if (pFind) + { + *pFind = 0; + strncat(krbConFile, "\\",sizeof(krbConFile)-strlen(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + strncat(krbConFile, KRB_FILE,sizeof(krbConFile)-strlen(krbConFile)); + krbConFile[MAX_PATH-1] = '\0'; + } + else + krbConFile[0] = 0; + + strncpy(confname, krbConFile, szConfname); + confname[szConfname-1] = '\0'; + } + return FALSE; +} + +BOOL +GetKrb4RealmFile( + LPSTR confname, + UINT szConfname + ) +{ + if (hKrb5 + ) + { // hold krb.con where krb5.ini is located + CHAR krbRealmConFile[MAX_PATH]; + LPSTR pFind; + + //strcpy(krbRealmConFile, CLeashApp::m_krbv5_profile->first_file->filename); + if (GetProfileFile(krbRealmConFile, sizeof(krbRealmConFile))) + { + GetWindowsDirectory(krbRealmConFile,sizeof(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + strncat(krbRealmConFile, "\\",sizeof(krbRealmConFile)-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + strncat(krbRealmConFile, KRB5_FILE,sizeof(krbRealmConFile)-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + } + + pFind = strrchr(krbRealmConFile, '\\'); + if (pFind) + { + *pFind = 0; + strncat(krbRealmConFile, "\\", sizeof(krbRealmConFile)-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + strncat(krbRealmConFile, KRBREALM_FILE, sizeof(krbRealmConFile)-strlen(krbRealmConFile)); + krbRealmConFile[MAX_PATH-1] = '\0'; + } + else + krbRealmConFile[0] = 0; + + strncpy(confname, krbRealmConFile, szConfname); + confname[szConfname-1] = '\0'; + } + return FALSE; +} + +int +readstring(FILE * file, char * buf, int len) +{ + int c,i; + memset(buf, '\0', sizeof(buf)); + for (i=0, c=fgetc(file); c != EOF ; c=fgetc(file), i++) + { + if (i < sizeof(buf)) { + if (c == '\n') { + buf[i] = '\0'; + return i; + } else { + buf[i] = c; + } + } else { + if (c == '\n') { + buf[len-1] = '\0'; + return(i); + } + } + } + if (c == EOF) { + if (i > 0 && i < len) { + buf[i] = '\0'; + return(i); + } else { + buf[len-1] = '\0'; + return(-1); + } + } + return(-1); +} + +typedef struct _slider_info { + int slider_id; + int text_id; + int min; + int max; + int increment; + struct _slider_info * next; +} slider_info; +static slider_info * sliders = NULL; + +static slider_info * +FreeSlider(slider_info * s) +{ + slider_info * n = NULL; + + if (s) { + n = s->next; + free(s); + } + return n; +} + +static void +CleanupSliders(void) +{ + while(sliders) + sliders = FreeSlider(sliders); +} + + +static unsigned short +NewSliderValue(HWND hDialog, int id) +{ + int value = 0; + slider_info * s = sliders; + while(s) { + if (s->slider_id == id) { + int pos = CSendDlgItemMessage( hDialog, id, + TBM_GETPOS, + (WPARAM) 0, (LPARAM) 0); + value = s->min + (pos * s->increment); + break; + } + s = s->next; + } + return(value); +} + +static const char * +NewSliderString(int id, int pos) +{ + static char buf[64]=""; + char * p = buf; + int value = 0; + int must_hours = 0; + slider_info * s = sliders; + while(s) { + if (s->slider_id == id) { + value = s->min + pos * s->increment; + *p = 0; + if (value >= 60 * 24) { + sprintf(p,"%d day(s) ",value / (60 * 24)); + value %= (60 * 24); + p += strlen(p); + must_hours = 1; + } + if (must_hours || value >= 60) { + sprintf(p,"%d hour(s) ",value / 60); + value %= 60; + p += strlen(p); + } + sprintf(p,"%d minute(s) ",value); + break; + } + s = s->next; + } + return(buf); +} + +static void +SetupSlider( HWND hDialog, + int sliderID, + int textFieldID, + int minimum, + int maximum, + int value) +{ + int min = minimum; + int max = maximum; + int increment = 0; + int range; + int roundedMinimum; + int roundedMaximum; + int roundedValue; + slider_info * new_info; + + if (max < min) { + // swap values + int temp = max; + max = min; + min = temp; + } + range = max - min; + + if (range < 5*60) { increment = 1; // 1 s if under 5 m + } else if (range < 30*60) { increment = 5; // 5 s if under 30 m + } else if (range < 60*60) { increment = 15; // 15 s if under 1 h + } else if (range < 2*60*60) { increment = 30; // 30 s if under 2 h + } else if (range < 5*60*60) { increment = 60; // 1 m if under 5 h + } else if (range < 50*60*60) { increment = 5*60; // 5 m if under 50 h + } else if (range < 200*60*60) { increment = 15*60; // 15 m if under 200 h + } else if (range < 500*60*60) { increment = 30*60; // 30 m if under 500 h + } else { increment = 60*60; } // 1 h otherwise + + roundedMinimum = (min / increment) * increment; + if (roundedMinimum > min) { roundedMinimum -= increment; } + if (roundedMinimum <= 0) { roundedMinimum += increment; } // make positive + + roundedMaximum = (max / increment) * increment; + if (roundedMaximum < max) { roundedMaximum += increment; } + + roundedValue = (value / increment) * increment; + if (roundedValue < roundedMinimum) { roundedValue = roundedMinimum; } + if (roundedValue > roundedMaximum) { roundedValue = roundedMaximum; } + + if (roundedMinimum == roundedMaximum) { + // [textField setTextColor: [NSColor grayColor]]; + EnableWindow(GetDlgItem(hDialog,sliderID),FALSE); + } else { + // [textField setTextColor: [NSColor blackColor]]; + EnableWindow(GetDlgItem(hDialog,sliderID),TRUE); + } + + CSendDlgItemMessage( hDialog, sliderID, + TBM_SETRANGEMIN, + (WPARAM) FALSE, + (LPARAM) 0 ); + CSendDlgItemMessage( hDialog, sliderID, + TBM_SETRANGEMAX, + (WPARAM) FALSE, + (LPARAM) (roundedMaximum - roundedMinimum) / increment ); + CSendDlgItemMessage( hDialog, sliderID, + TBM_SETPOS, + (WPARAM) TRUE, + (LPARAM) (roundedValue - roundedMinimum) / increment); + + new_info = (slider_info *) malloc(sizeof(slider_info)); + new_info->slider_id = sliderID; + new_info->text_id = textFieldID; + new_info->min = roundedMinimum; + new_info->max = roundedMaximum; + new_info->increment = increment; + new_info->next = sliders; + sliders = new_info; + + SetWindowText(GetDlgItem(hDialog, textFieldID), + NewSliderString(sliderID,(roundedValue - roundedMinimum) / increment)); +} + + +static void +AdjustOptions(HWND hDialog, int show, int hideDiff) +{ + RECT rect; + RECT dlgRect; + HWND hwnd; + int diff; + + Leash_set_hide_kinit_options(!show); + + ShowWindow(GetDlgItem(hDialog,IDC_STATIC_LIFETIME),show); + ShowWindow(GetDlgItem(hDialog,IDC_STATIC_LIFETIME_VALUE),show); + ShowWindow(GetDlgItem(hDialog,IDC_SLIDER_LIFETIME),show); + ShowWindow(GetDlgItem(hDialog,IDC_SLIDER_RENEWLIFE),show); + ShowWindow(GetDlgItem(hDialog,IDC_STATIC_RENEW),show); + ShowWindow(GetDlgItem(hDialog,IDC_STATIC_RENEW_TILL_VALUE),show); + ShowWindow(GetDlgItem(hDialog,IDC_CHECK_FORWARDABLE),show); + ShowWindow(GetDlgItem(hDialog,IDC_CHECK_NOADDRESS),show); + ShowWindow(GetDlgItem(hDialog,IDC_CHECK_RENEWABLE),show); + ShowWindow(GetDlgItem(hDialog,IDC_STATIC_KRB5),show); + ShowWindow(GetDlgItem(hDialog,IDC_BUTTON_CLEAR_HISTORY),show); + + GetWindowRect( hDialog, &dlgRect ); + diff = dlgRect.top + GetSystemMetrics(SM_CYCAPTION) + + GetSystemMetrics(SM_CYDLGFRAME) + (show ? -1 : 1) * hideDiff; + + hwnd = GetDlgItem(hDialog,IDOK); + GetWindowRect(hwnd,&rect); + SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE); + hwnd = GetDlgItem(hDialog,IDCANCEL); + GetWindowRect(hwnd,&rect); + SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE); + hwnd = GetDlgItem(hDialog,IDC_BUTTON_OPTIONS); + GetWindowRect(hwnd,&rect); + SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE); + hwnd = GetDlgItem(hDialog,IDC_STATIC_VERSION); + GetWindowRect(hwnd,&rect); + SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE); + hwnd = GetDlgItem(hDialog,IDC_STATIC_COPYRIGHT); + GetWindowRect(hwnd,&rect); + SetWindowPos(hwnd,0,rect.left-dlgRect.left-GetSystemMetrics(SM_CXDLGFRAME),rect.top-diff,0,0,SWP_NOZORDER|SWP_NOSIZE); + SetWindowPos(hDialog,0,0,0, + dlgRect.right-dlgRect.left, + dlgRect.bottom-dlgRect.top+(show ? 1 : - 1) * hideDiff, + SWP_NOZORDER|SWP_NOMOVE); + + CSetDlgItemText(hDialog, IDC_BUTTON_OPTIONS, + show ? "Hide Advanced" : "Show Advanced"); + +} + +/* Callback function for the Authentication Dialog box that initializes and + renews tickets. */ + +INT_PTR +CALLBACK +AuthenticateProc( + HWND hDialog, + UINT message, + WPARAM wParam, + LPARAM lParam + ) +{ + static POINT Position = { -1, -1 }; + static char principal[256]=""; + static char password[256]=""; + static int lifetime=0; + static int renew_till=0; + static int forwardable=0; + static int noaddresses=0; + static int proxiable=0; + static int publicip=0; + static LPLSH_DLGINFO_EX lpdi; + static HWND hDlg=0; + static HWND hSliderLifetime=0; + static HWND hSliderRenew=0; + static RECT dlgRect; + static int hideDiff = 0; + static void *pAutoComplete = 0; + long realm_count = 0; + int disable_noaddresses = 0; + HWND hEditCtrl=0; + HWND hFocusCtrl=0; + BOOL bReadOnlyPrinc=0; + + switch (message) { + + case WM_INITDIALOG: + hDlg = hDialog; + + hEditCtrl = GetDlgItem(hDialog, IDC_EDIT_PRINCIPAL); + if (hEditCtrl) + pAutoComplete = Leash_pec_create(hEditCtrl); + hSliderLifetime = GetDlgItem(hDialog, IDC_STATIC_LIFETIME_VALUE); + hSliderRenew = GetDlgItem(hDialog, IDC_STATIC_RENEW_TILL_VALUE); + + *( (LPLSH_DLGINFO_EX far *)(&lpdi) ) = (LPLSH_DLGINFO_EX)(LPSTR)lParam; + + if ((lpdi->size != LSH_DLGINFO_EX_V1_SZ && + lpdi->size != LSH_DLGINFO_EX_V2_SZ && + lpdi->size < LSH_DLGINFO_EX_V3_SZ) || + (lpdi->dlgtype & DLGTYPE_MASK) != DLGTYPE_PASSWD) { + + MessageBox(hDialog, "An incorrect initialization data structure was provided.", + "AuthenticateProc()", + MB_OK | MB_ICONSTOP); + return FALSE; + } + bReadOnlyPrinc = (lpdi->dlgtype & DLGFLAG_READONLYPRINC) ? + TRUE : FALSE; + + if ( lpdi->size >= LSH_DLGINFO_EX_V2_SZ ) { + lpdi->out.username[0] = 0; + lpdi->out.realm[0] = 0; + } + if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ ) { + lpdi->out.ccache[0] = 0; + } + + if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ ) + SetWindowText(hDialog, lpdi->in.title); + else + SetWindowText(hDialog, lpdi->title); + + SetProp(hDialog, "HANDLES_HELP", (HANDLE)1); + if (lpdi->use_defaults) { + lifetime = Leash_get_default_lifetime(); + if (lifetime <= 0) + lifetime = 600; /* 10 hours */ + if (Leash_get_default_renewable()) { + renew_till = Leash_get_default_renew_till(); + if (renew_till < 0) + renew_till = 10800; /* 7 days */ + } else + renew_till = 0; + forwardable = Leash_get_default_forwardable(); + if (forwardable < 0) + forwardable = 0; + noaddresses = Leash_get_default_noaddresses(); + if (noaddresses < 0) + noaddresses = 0; + proxiable = Leash_get_default_proxiable(); + if (proxiable < 0) + proxiable = 0; + publicip = Leash_get_default_publicip(); + if (publicip < 0) + publicip = 0; + } else { + forwardable = lpdi->forwardable; + noaddresses = lpdi->noaddresses; + lifetime = lpdi->lifetime; + renew_till = lpdi->renew_till; + proxiable = lpdi->proxiable; + publicip = lpdi->publicip; + } + if (lpdi->username && (strlen(lpdi->username) > 0) && + lpdi->realm && (strlen(lpdi->realm) > 0)) { + sprintf_s(principal, sizeof(principal), "%s@%s", lpdi->username, + lpdi->realm); + } else { + principal[0] = 0; + } + Edit_SetReadOnly(hEditCtrl, bReadOnlyPrinc); + CSetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, principal); + CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD, ""); + +#if 0 /* 20030619 - mjv wishes to return to the default character */ + /* echo spaces */ + CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETPASSWORDCHAR, 32, 0); +#endif + + /* Set Lifetime Slider + * min value = 5 + * max value = 1440 + * current value + */ + + SetupSlider( hDialog, + IDC_SLIDER_LIFETIME, + IDC_STATIC_LIFETIME_VALUE, + Leash_get_default_life_min(), + Leash_get_default_life_max(), + lifetime ); + + CheckDlgButton(hDialog, IDC_CHECK_REMEMBER_PRINCIPAL, TRUE); + /* Set Forwardable checkbox */ + CheckDlgButton(hDialog, IDC_CHECK_FORWARDABLE, forwardable); + /* Set NoAddress checkbox */ + CheckDlgButton(hDialog, IDC_CHECK_NOADDRESS, noaddresses); + if ( disable_noaddresses ) + EnableWindow(GetDlgItem(hDialog,IDC_CHECK_NOADDRESS),FALSE); + /* Set Renewable checkbox */ + CheckDlgButton(hDialog, IDC_CHECK_RENEWABLE, renew_till); + /* if not renewable, disable Renew Till slider */ + /* if renewable, set Renew Till slider + * min value + * max value + * current value + */ + SetupSlider( hDialog, + IDC_SLIDER_RENEWLIFE, + IDC_STATIC_RENEW_TILL_VALUE, + Leash_get_default_renew_min(), + Leash_get_default_renew_max(), + renew_till); + if (renew_till) { + EnableWindow(GetDlgItem(hDialog,IDC_SLIDER_RENEWLIFE),TRUE); + } else { + EnableWindow(GetDlgItem(hDialog,IDC_SLIDER_RENEWLIFE),FALSE); + } + + // Compute sizes of items necessary to show/hide the advanced options + GetWindowRect( hDialog, &dlgRect ); + { + RECT okRect, staticRect; + GetWindowRect(GetDlgItem(hDialog,IDC_STATIC_LIFETIME),&staticRect); + GetWindowRect(GetDlgItem(hDialog,IDOK),&okRect); + hideDiff = okRect.top - staticRect.top; + } + + if ( hKrb5 ) { + if (Leash_get_hide_kinit_options()) + AdjustOptions(hDialog,0,hideDiff); + } else { + AdjustOptions(hDialog,0,hideDiff); + EnableWindow(GetDlgItem(hDialog,IDC_BUTTON_OPTIONS),FALSE); + ShowWindow(GetDlgItem(hDialog,IDC_BUTTON_OPTIONS),SW_HIDE); + } + + /* setup text of stuff. */ + + if (Position.x > 0 && Position.y > 0 && + Position.x < GetSystemMetrics(SM_CXSCREEN) && + Position.y < GetSystemMetrics(SM_CYSCREEN)) + SetWindowPos(hDialog, HWND_TOP, Position.x, Position.y, 0, 0, SWP_NOSIZE); + else /* Center the window on the desktop */ + SetWindowPos(hDialog, HWND_TOP, + (GetSystemMetrics(SM_CXSCREEN) - dlgRect.right + dlgRect.left)/2, + (GetSystemMetrics(SM_CYSCREEN) - dlgRect.bottom + dlgRect.top)/2, + 0, 0, + SWP_NOSIZE); + + /* Take keyboard focus */ + SetActiveWindow(hDialog); + SetForegroundWindow(hDialog); + /* put focus on password if princ is read-only */ + hFocusCtrl = (bReadOnlyPrinc || principal[0] != '\0') ? + GetDlgItem(hDialog, IDC_EDIT_PASSWORD) : hEditCtrl; + if (((HWND)wParam) != hFocusCtrl) { + SetFocus(hFocusCtrl); + } + break; + + case WM_HSCROLL: + switch (LOWORD(wParam)) { + case TB_THUMBTRACK: + case TB_THUMBPOSITION: + { + long pos = HIWORD(wParam); // the position of the slider + int ctrlID = GetDlgCtrlID((HWND)lParam); + + if (ctrlID == IDC_SLIDER_RENEWLIFE) { + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_RENEW_TILL_VALUE), + NewSliderString(IDC_SLIDER_RENEWLIFE,pos)); + } + if (ctrlID == IDC_SLIDER_LIFETIME) { + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_LIFETIME_VALUE), + NewSliderString(IDC_SLIDER_LIFETIME,pos)); + } + } + break; + case TB_BOTTOM: + case TB_TOP: + case TB_ENDTRACK: + case TB_LINEDOWN: + case TB_LINEUP: + case TB_PAGEDOWN: + case TB_PAGEUP: + default: + { + int ctrlID = GetDlgCtrlID((HWND)lParam); + long pos = SendMessage(GetDlgItem(hDialog,ctrlID), TBM_GETPOS, 0, 0); // the position of the slider + + if (ctrlID == IDC_SLIDER_RENEWLIFE) { + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_RENEW_TILL_VALUE), + NewSliderString(IDC_SLIDER_RENEWLIFE,pos)); + } + if (ctrlID == IDC_SLIDER_LIFETIME) { + SetWindowText(GetDlgItem(hDialog, IDC_STATIC_LIFETIME_VALUE), + NewSliderString(IDC_SLIDER_LIFETIME,pos)); + } + } + } + break; + + case WM_COMMAND: + switch (wParam) { + case IDC_BUTTON_OPTIONS: + { + AdjustOptions(hDialog,Leash_get_hide_kinit_options(),hideDiff); + GetWindowRect(hDialog,&dlgRect); + if ( dlgRect.bottom > GetSystemMetrics(SM_CYSCREEN)) + SetWindowPos( hDialog,0, + dlgRect.left, + GetSystemMetrics(SM_CYSCREEN) - dlgRect.bottom + dlgRect.top, + 0,0, + SWP_NOZORDER|SWP_NOSIZE); + + } + break; + case IDC_BUTTON_CLEAR_HISTORY: + Leash_pec_clear_history(pAutoComplete); + break; + case IDC_CHECK_RENEWABLE: + { + if (IsDlgButtonChecked(hDialog, IDC_CHECK_RENEWABLE)) { + EnableWindow(hSliderRenew,TRUE); + } else { + EnableWindow(hSliderRenew,FALSE); + } + } + break; + case ID_HELP: + { + WinHelp(GetWindow(hDialog,GW_OWNER), KRB_HelpFile, HELP_CONTEXT, + ID_INITTICKETS); + } + break; + case ID_CLOSEME: + { + CleanupSliders(); + memset(password,0,sizeof(password)); + RemoveProp(hDialog, "HANDLES_HELP"); + if (pAutoComplete) { + Leash_pec_destroy(pAutoComplete); + pAutoComplete = NULL; + } + EndDialog(hDialog, (int)lParam); + return TRUE; + } + break; + case IDOK: + { + DWORD value = 0; + + CGetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, principal, sizeof(principal)); + CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD, password, sizeof(password)); + + if (!principal[0]) { + MessageBox(hDialog, + "You are not allowed to enter a blank principal.", + "Invalid Principal", + MB_OK | MB_ICONSTOP); + return TRUE; + } + // @TODO: parse realm portion and auto-uppercase +/* + if (Leash_get_default_uppercaserealm()) + { + // found + strupr(realm); + } +*/ + + if (!password[0]) + { + MessageBox(hDialog, + "You are not allowed to enter a blank password.", + "Invalid Password", + MB_OK | MB_ICONSTOP); + return TRUE; + } + + lifetime = NewSliderValue(hDialog, IDC_SLIDER_LIFETIME); + + forwardable = proxiable = + IsDlgButtonChecked(hDialog, IDC_CHECK_FORWARDABLE); + noaddresses = IsDlgButtonChecked(hDialog, IDC_CHECK_NOADDRESS); + if (IsDlgButtonChecked(hDialog, IDC_CHECK_RENEWABLE)) { + renew_till = NewSliderValue(hDialog, IDC_SLIDER_RENEWLIFE); + } else { + renew_till= 0; + } + + lsh_errno = Leash_int_kinit_ex( 0, + hDialog, + principal, password, lifetime, + forwardable, + proxiable, + renew_till, + noaddresses, + publicip, + 1 + ); + if (lsh_errno != 0) + { +#ifdef COMMENT + char gbuf[256]; + int capslock; + char *cp; +#endif + err_context = ""; + switch(lsh_errno) + { + case LSH_INVPRINCIPAL: + case LSH_INVINSTANCE: + CSendDlgItemMessage(hDialog, IDC_EDIT_PRINCIPAL, EM_SETSEL, 0, 256); + SetFocus(GetDlgItem(hDialog,IDC_EDIT_PRINCIPAL)); + break; + case LSH_INVREALM: + CSendDlgItemMessage(hDialog, IDC_COMBO_REALM, EM_SETSEL, 0, 256); + SetFocus(GetDlgItem(hDialog,IDC_COMBO_REALM)); + break; + default: + CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETSEL, 0, 256); + SetFocus(GetDlgItem(hDialog,IDC_EDIT_PASSWORD)); + return(TRUE); + } +#ifdef COMMENT + capslock = lsh_getkeystate(VK_CAPITAL); + /* low-order bit means caps lock is + toggled; if so, warn user since there's + been an error. */ + if (capslock & 1) + { + lstrcpy((LPSTR)gbuf, (LPSTR)err_context); + cp = gbuf + lstrlen((LPSTR)gbuf); + if (cp != gbuf) + *cp++ = ' '; + lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)"); + err_context = gbuf; + } + + // XXX DoNiftyErrorReport(lsh_errno, ISCHPASSWD ? "" + // XXX : "Ticket initialization failed."); +#endif /* COMMENT */ + return TRUE; + } + + if ( Leash_get_default_preserve_kinit_settings() ) + { + Leash_set_default_lifetime(lifetime); + if ( renew_till > 0 ) { + Leash_set_default_renew_till(renew_till); + Leash_set_default_renewable(1); + } else { + Leash_set_default_renewable(0); + } + Leash_set_default_forwardable(forwardable); + Leash_set_default_noaddresses(noaddresses); + } +/* @TODO: out username/realm + if ( lpdi->size >= LSH_DLGINFO_EX_V2_SZ ) { + strncpy(lpdi->out.username, username, LEASH_USERNAME_SZ); + lpdi->out.username[LEASH_USERNAME_SZ-1] = 0; + strncpy(lpdi->out.realm, realm, LEASH_REALM_SZ); + lpdi->out.realm[LEASH_REALM_SZ-1] = 0; + } +*/ + if (IsDlgButtonChecked(hDialog, IDC_CHECK_REMEMBER_PRINCIPAL)) + Leash_pec_add_principal(principal); + + CloseMe(TRUE); /* success */ + return FALSE; + } + break; + case IDCANCEL: + CloseMe(FALSE); + break; + } + break; + + case WM_MOVE: +#ifdef _WIN32 +#define LONG2POINT(l,pt) ((pt).x=(SHORT)LOWORD(l), \ + (pt).y=(SHORT)HIWORD(l)) + LONG2POINT(lParam,Position); +#else + Position = MAKEPOINT(lParam); +#endif + break; + } + return FALSE; +} + +/* Callback function for the Change Password Dialog box */ + +INT_PTR +CALLBACK +NewPasswordProc( + HWND hDialog, + UINT message, + WPARAM wParam, + LPARAM lParam + ) +{ + static POINT Position = { -1, -1 }; + static char password[256]=""; + static char password2[256]=""; + static char password3[256]=""; + static LPLSH_DLGINFO_EX lpdi; + static HWND hDlg=0; + static void *pAutoComplete = NULL; + char principal[256]; + long realm_count = 0; + HWND hEditCtrl = NULL; + + switch (message) { + + case WM_INITDIALOG: + hDlg = hDialog; + + *( (LPLSH_DLGINFO_EX far *)(&lpdi) ) = (LPLSH_DLGINFO_EX)(LPSTR)lParam; + + if ((lpdi->size < LSH_DLGINFO_EX_V3_SZ && + lpdi->size != LSH_DLGINFO_EX_V1_SZ && + lpdi->size != LSH_DLGINFO_EX_V2_SZ) || + lpdi->dlgtype != DLGTYPE_CHPASSWD) { + + MessageBox(hDialog, "An incorrect initialization data structure was provided.", + "PasswordProc()", + MB_OK | MB_ICONSTOP); + return FALSE; + } + + if ( lpdi->size >= LSH_DLGINFO_EX_V2_SZ ) { + lpdi->out.username[0] = 0; + lpdi->out.realm[0] = 0; + } + if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ ) { + lpdi->out.ccache[0] = 0; + } + + if ( lpdi->size >= LSH_DLGINFO_EX_V3_SZ ) + SetWindowText(hDialog, lpdi->in.title); + else + SetWindowText(hDialog, lpdi->title); + + SetProp(hDialog, "HANDLES_HELP", (HANDLE)1); + + if (lpdi->username != NULL && (strlen(lpdi->username) > 0) && + lpdi->realm != NULL && (strlen(lpdi->realm) > 0)) { + sprintf_s(principal, + sizeof(principal), "%s@%s", lpdi->username, lpdi->realm); + } else { + principal[0] = 0; + } + + CSetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, principal); + CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD, ""); + CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD2, ""); + CSetDlgItemText(hDialog, IDC_EDIT_PASSWORD3, ""); + + hEditCtrl = GetDlgItem(hDialog, IDC_EDIT_PRINCIPAL); + if (hEditCtrl) + pAutoComplete = Leash_pec_create(hEditCtrl); + +#if 0 /* 20030619 - mjv wishes to return to the default character */ + /* echo spaces */ + CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD, EM_SETPASSWORDCHAR, 32, 0); + CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD2, EM_SETPASSWORDCHAR, 32, 0); + CSendDlgItemMessage(hDialog, IDC_EDIT_PASSWORD3, EM_SETPASSWORDCHAR, 32, 0); +#endif + /* setup text of stuff. */ + + if (Position.x > 0 && Position.y > 0 && + Position.x < GetSystemMetrics(SM_CXSCREEN) && + Position.y < GetSystemMetrics(SM_CYSCREEN)) + SetWindowPos(hDialog, 0, Position.x, Position.y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + else { /* Center the window on the desktop */ + RECT dlgRect; + GetWindowRect( hDialog, &dlgRect ); + SetWindowPos(hDialog, 0, + (GetSystemMetrics(SM_CXSCREEN) - dlgRect.right + dlgRect.left)/2, + (GetSystemMetrics(SM_CYSCREEN) - dlgRect.bottom + dlgRect.top)/2, + 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + } + /* set window pos to last saved window pos */ + break; + + case WM_COMMAND: + switch (wParam) { + case ID_HELP: + { + WinHelp(GetWindow(hDialog,GW_OWNER), KRB_HelpFile, HELP_CONTEXT, + ID_INITTICKETS); + } + break; + case ID_CLOSEME: + { + CleanupSliders(); + memset(password,0,sizeof(password)); + memset(password2,0,sizeof(password2)); + memset(password3,0,sizeof(password3)); + RemoveProp(hDialog, "HANDLES_HELP"); + EndDialog(hDialog, (int)lParam); + if (pAutoComplete != NULL) { + Leash_pec_destroy(pAutoComplete); + pAutoComplete = NULL; + } + return TRUE; + } + break; + case IDOK: + { + DWORD value = 0; + int i = 0; + int bit8 = 0; + + CGetDlgItemText(hDialog, IDC_EDIT_PRINCIPAL, principal, sizeof(principal)); + CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD, password, sizeof(password)); + CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD2, password2, sizeof(password2)); + CGetDlgItemText(hDialog, IDC_EDIT_PASSWORD3, password3, sizeof(password3)); + + if (!principal[0]) + { + MessageBox(hDialog, "You are not allowed to enter a " + "blank username.", + "Invalid Principal", + MB_OK | MB_ICONSTOP); + return TRUE; + } + + if (!password[0] || !password2[0] || !password3[0]) + { + MessageBox(hDialog, "You are not allowed to enter a " + "blank password.", + "Invalid Password", + MB_OK | MB_ICONSTOP); + return TRUE; + } + + for( i = 0; i < 255; i++ ){ + if( password2[i] == '\0' ){ + if ( bit8 ) { + MessageBox(hDialog, + "Passwords should not contain non-ASCII characters.", + "Internationalization Warning", + MB_OK | MB_ICONINFORMATION); + } + i = 255; + break; + } else if( !isprint(password2[i]) ){ + memset(password2, '\0', sizeof(password2)); + memset(password3, '\0', sizeof(password3)); + /* I claim these passwords in the name of planet '\0'... */ + MessageBox(hDialog, + "Passwords may not contain non-printable characters.", + "Invalid Password", + MB_OK | MB_ICONSTOP); + return TRUE; + } else if ( password2[i] > 127 ) + bit8 = 1; + } + + if (lstrcmp(password2, password3)) + { + MessageBox(hDialog, + "The new password was not entered the same way twice.", + "Password validation error", + MB_OK | MB_ICONSTOP); + return TRUE; + } + + lsh_errno = Leash_int_changepwd(principal, password, password2, 0, 1); + if (lsh_errno != 0) + { +#ifdef COMMENT + char gbuf[256]; + int capslock; + char *cp; +#endif /* COMMENT */ + + err_context = ""; + switch(lsh_errno) + { + case LSH_INVPRINCIPAL: + case LSH_INVINSTANCE: + case LSH_INVREALM: + break; + default: + return(TRUE); + } +#ifdef COMMENT + capslock = lsh_getkeystate(VK_CAPITAL); + /* low-order bit means caps lock is + toggled; if so, warn user since there's + been an error. */ + if (capslock & 1) + { + lstrcpy((LPSTR)gbuf, (LPSTR)err_context); + cp = gbuf + lstrlen((LPSTR)gbuf); + if (cp != gbuf) + *cp++ = ' '; + lstrcpy(cp, "(This may be because your CAPS LOCK key is down.)"); + err_context = gbuf; + } + + // XXX DoNiftyErrorReport(lsh_errno, ISCHPASSWD ? "" + // XXX : "Ticket initialization failed."); +#endif /* COMMENT */ + return TRUE; + } + Leash_pec_add_principal(principal); + MessageBox(NULL, "Password successfully changed.", + "Password change", MB_OK); + CloseMe(TRUE); /* success */ + } + break; + case IDCANCEL: + CloseMe(FALSE); + break; + } + break; + + case WM_MOVE: +#ifdef _WIN32 +#define LONG2POINT(l,pt) ((pt).x=(SHORT)LOWORD(l), \ + (pt).y=(SHORT)HIWORD(l)) + LONG2POINT(lParam,Position); +#else + Position = MAKEPOINT(lParam); +#endif + break; + } + return FALSE; +} diff --git a/src/windows/leashdll/lsh_pwd.rc b/src/windows/leashdll/lsh_pwd.rc new file mode 100644 index 000000000000..98b4d5c647ab --- /dev/null +++ b/src/windows/leashdll/lsh_pwd.rc @@ -0,0 +1,251 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "leashids.h" +#include "winver.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +LOGOBITMAP BITMAP DISCARDABLE "res\\islogo.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +LEASHICON ICON DISCARDABLE "res\\leash.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ENTERPASSWORDDLG DIALOG DISCARDABLE 23, 48, 262, 108 +STYLE DS_MODALFRAME | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Enter Password" +FONT 10, "System" +BEGIN + EDITTEXT ID_PRINCIPAL,6,17,96,12,ES_AUTOHSCROLL + LTEXT "Enter your username:",ID_PRINCCAPTION,6,7,140,8 + DEFPUSHBUTTON "OK",IDOK,110,42,32,14 + EDITTEXT ID_OLDPASSWORD,6,43,96,12,ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "Enter your password:",ID_OLDPCAPTION,6,33,91,8 + EDITTEXT ID_DURATION,40,59,20,12 + LTEXT "Duration:",-1,6,61,30,8 + LTEXT "minutes",-1,62,61,64,8 + ICON "LeashIcon",-1,6,78,18,20 + PUSHBUTTON "&Cancel",IDCANCEL,30,78,32,14 + PUSHBUTTON "&Restart",ID_RESTART,70,78,32,14 + PUSHBUTTON "&Help",ID_HELP,110,78,32,14 + CONTROL "",ID_PICFRAME,"Static",SS_BLACKFRAME,153,4,100,100 +END + +CHANGEPASSWORDDLG DIALOG DISCARDABLE 27, 41, 270, 155 +STYLE DS_MODALFRAME | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Change Password" +FONT 8, "System" +BEGIN + EDITTEXT ID_PRINCIPAL,6,35,96,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,110,60,32,14 + EDITTEXT ID_OLDPASSWORD,6,61,96,12,ES_PASSWORD | ES_AUTOHSCROLL + EDITTEXT ID_CONFIRMPASSWORD1,6,87,96,12,ES_PASSWORD | + ES_AUTOHSCROLL + EDITTEXT ID_CONFIRMPASSWORD2,6,113,96,12,ES_PASSWORD | + ES_AUTOHSCROLL + LTEXT "Enter your username:",ID_PRINCCAPTION,6,25,140,8 + LTEXT "Enter your old password:",ID_OLDPCAPTION,6,51,91,8 + LTEXT "Enter your new password:",ID_CONFIRMCAPTION1,6,77,96,8 + LTEXT "Retype your new password:",ID_CONFIRMCAPTION2,6,103,100, + 8 + ICON "LeashIcon",-1,6,134,18,20 + PUSHBUTTON "&Cancel",IDCANCEL,30,134,32,14 + PUSHBUTTON "&Restart",ID_RESTART,70,134,32,14 + PUSHBUTTON "&Help",ID_HELP,110,134,32,14 + LTEXT "To change your password, fill in the following fields as they appear.", + -1,6,3,140,21 + CONTROL "",ID_PICFRAME,"Static",SS_BLACKFRAME,157,27,100,100 +END + +IDD_AUTHENTICATE DIALOGEX 0, 0, 370, 248 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Authenticate to Kerberos" +FONT 8, "Microsoft Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_PRINCIPAL,89,42,199,14,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD,89,58,259,14,ES_PASSWORD | + ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,302,219,49,14 + PUSHBUTTON "Cancel",IDCANCEL,249,219,49,14 + PUSHBUTTON "Hide Advanced",IDC_BUTTON_OPTIONS,146,219,89,14 + PUSHBUTTON "Clear History",IDC_BUTTON_CLEAR_HISTORY,288,42,60,14 + CONTROL "Remember this principal", IDC_CHECK_REMEMBER_PRINCIPAL, + "Button", BS_AUTOCHECKBOX | WS_TABSTOP,89,72,100,14 + CONTROL "Ticket Lifetime",IDC_SLIDER_LIFETIME,"msctls_trackbar32", + TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,90,97,258,15 + CONTROL "Forwardable and Proxiable (can be forwarded to other machines)", + IDC_CHECK_FORWARDABLE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,89,123,253,10 + CONTROL "Renewable (can be renewed during the renewable lifetime)", + IDC_CHECK_RENEWABLE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,89,135,253,10 + CONTROL "Slider2",IDC_SLIDER_RENEWLIFE,"msctls_trackbar32", + TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,90,178,258,15 + RTEXT "Principal:",IDC_STATIC_NAME,13,44,74,8 + RTEXT "Password:",IDC_STATIC_PWD,13,60,74,8 + RTEXT "Ticket Lifetime:",IDC_STATIC_LIFETIME,23,87,65,8,0, + WS_EX_RIGHT + LTEXT "Flag this ticket as:",IDC_STATIC_KRB5,32,123,56,8 + LTEXT "HMS",IDC_STATIC_LIFETIME_VALUE,90,87,131,8 + LTEXT "HMS",IDC_STATIC_RENEW_TILL_VALUE,90,164,141,8 + ICON LEASHICON,IDC_PICTURE_LEASH,21,15,20,20 + LTEXT "Please Authenticate", + IDC_STATIC_NOTICE,51,23,276,8 + RTEXT "Renewable Lifetime:",IDC_STATIC_RENEW,10,164,79,8 +END + +IDD_PASSWORD DIALOG DISCARDABLE 0, 0, 382, 150 +STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Change Password" +FONT 8, "Microsoft Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_PRINCIPAL,99,40,259,14,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD,99,60,259,14,ES_PASSWORD | + ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD2,99,85,259,14,ES_PASSWORD | + ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD3,99,105,259,14,ES_PASSWORD | + ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,313,125,49,14 + PUSHBUTTON "Cancel",IDCANCEL,256,125,49,14 + RTEXT "Principal:",IDC_STATIC_NAME,22,43,74,12 + RTEXT "Old Password:",IDC_STATIC_PWD,22,63,74,12 + ICON LEASHICON,IDC_PICTURE_LEASH,15,15,20,20 + LTEXT "Change your Kerberos password or phrase", + IDC_STATIC_NOTICE,48,20,276,8 + RTEXT "New Password:",IDC_STATIC_PWD2,22,88,74,12 + RTEXT "New Password (again):",IDC_STATIC_PWD3,22,108,74,12 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""leashids.h""\r\n" + "#include ""ver.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "#include ""..\\version.rc""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_PASSWORD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 375 + TOPMARGIN, 7 + BOTTOMMARGIN, 191 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + LSH_TIME_HOST "time" + LSH_DEFAULT_TICKET_LIFE "600" + LSH_DEFAULT_TICKET_RENEW_TILL "10080" + LSH_DEFAULT_TICKET_FORWARD "1" + LSH_DEFAULT_TICKET_NOADDRESS "1" + LSH_DEFAULT_TICKET_PROXIABLE "0" + LSH_DEFAULT_TICKET_PUBLICIP "0" + LSH_DEFAULT_TICKET_USEKRB4 "0" + LSH_DEFAULT_DIALOG_KINIT_OPT "1" + LSH_DEFAULT_DIALOG_LIFE_MIN "30" + LSH_DEFAULT_DIALOG_LIFE_MAX "1440" + LSH_DEFAULT_DIALOG_RENEW_MIN "600" + LSH_DEFAULT_DIALOG_RENEW_MAX "43200" + LSH_DEFAULT_TICKET_RENEW "1" + LSH_DEFAULT_UPPERCASEREALM "1" + LSH_DEFAULT_MSLSA_IMPORT "2" + LSH_DEFAULT_PRESERVE_KINIT "0" +END + +STRINGTABLE DISCARDABLE +BEGIN + LSH_DEFAULT_DIALOG_LOCK_LOCATION "0" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +#include "..\version.rc" + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/src/windows/leashdll/lshcallb.c b/src/windows/leashdll/lshcallb.c new file mode 100644 index 000000000000..0344b796f3ac --- /dev/null +++ b/src/windows/leashdll/lshcallb.c @@ -0,0 +1,14 @@ +#include <windows.h> + +int (*Lcom_err)(LPSTR,long,LPSTR,...); +LPSTR (*Lerror_message)(long); +LPSTR (*Lerror_table_name)(long); + +void Leash_load_com_err_callback(FARPROC ce, + FARPROC em, + FARPROC etn) +{ + (FARPROC)Lcom_err=ce; + (FARPROC)Lerror_message=em; + (FARPROC)Lerror_table_name=etn; +} diff --git a/src/windows/leashdll/lshfunc.c b/src/windows/leashdll/lshfunc.c new file mode 100644 index 000000000000..0f76cc334fd6 --- /dev/null +++ b/src/windows/leashdll/lshfunc.c @@ -0,0 +1,3145 @@ +#include <windows.h> +#include <stdio.h> +#include <sys/types.h> +#include <winsock2.h> +#include "leashdll.h" +#ifndef NO_KRB4 +#include <KerberosIV/krb.h> +#include <prot.h> +#else +/* General definitions */ +#define KSUCCESS 0 +#define KFAILURE 255 +#endif +#include <time.h> + +#include <leashwin.h> +#include "leasherr.h" +#include "leash-int.h" +#include "leashids.h" + +#include <mitwhich.h> + +#include "reminder.h" + +static char FAR *err_context; + +char KRB_HelpFile[_MAX_PATH] = HELPFILE; + +#define LEN 64 /* Maximum Hostname Length */ + +#define LIFE DEFAULT_TKT_LIFE /* lifetime of ticket in 5-minute units */ + +static +char* +clean_string( + char* s + ) +{ + char* p = s; + char* b = s; + + if (!s) return s; + + for (p = s; *p; p++) { + switch (*p) { + case '\007': + /* Add more cases here */ + break; + default: + *b = *p; + b++; + } + } + *b = *p; + return s; +} + +static +int +leash_error_message( + const char *error, + int rcL, + int rc5, + int rcA, + char* result_string, + int displayMB + ) +{ + char message[2048]; + char *p = message; + int size = sizeof(message) - 1; /* -1 to leave room for NULL terminator */ + int n; + + // XXX: ignore AFS for now. + + if (!rc5 && !rcL) + return 0; + + n = _snprintf(p, size, "%s\n\n", error); + p += n; + size -= n; + + if (rc5 && !result_string) + { + n = _snprintf(p, size, + "Kerberos 5: %s (error %ld)\n", + perror_message(rc5), + rc5 + ); + p += n; + size -= n; + } + if (rcL) + { + char buffer[1024]; + n = _snprintf(p, size, + "\n%s\n", + err_describe(buffer, rcL) + ); + p += n; + size -= n; + } + if (result_string) + { + n = _snprintf(p, size, + "%s\n", + result_string); + p += n; + size -= n; + } +#ifdef USE_MESSAGE_BOX + *p = 0; /* ensure NULL termination of message */ + if ( displayMB ) + MessageBox(NULL, message, "MIT Kerberos", + MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND); +#endif /* USE_MESSAGE_BOX */ + if (rc5) return rc5; + if (rcL) return rcL; + return 0; +} + + +static +char * +make_postfix( + const char * base, + const char * postfix, + char ** rcopy + ) +{ + int base_size; + int ret_size; + char * copy = 0; + char * ret = 0; + + base_size = strlen(base) + 1; + ret_size = base_size + strlen(postfix) + 1; + copy = malloc(base_size); + ret = malloc(ret_size); + + if (!copy || !ret) + goto cleanup; + + strncpy(copy, base, base_size); + copy[base_size - 1] = 0; + + strncpy(ret, base, base_size); + strncpy(ret + (base_size - 1), postfix, ret_size - (base_size - 1)); + ret[ret_size - 1] = 0; + + cleanup: + if (!copy || !ret) { + if (copy) + free(copy); + if (ret) + free(ret); + copy = ret = 0; + } + // INVARIANT: (ret ==> copy) && (copy ==> ret) + *rcopy = copy; + return ret; +} + +static +long +make_temp_cache_v5( + const char * postfix, + krb5_context * pctx + ) +{ + static krb5_context ctx = 0; + static char * old_cache = 0; + + // INVARIANT: old_cache ==> ctx && ctx ==> old_cache + + if (pctx) + *pctx = 0; + + if (!pkrb5_init_context || !pkrb5_free_context || !pkrb5_cc_resolve || + !pkrb5_cc_default_name || !pkrb5_cc_set_default_name) + return 0; + + if (old_cache) { + krb5_ccache cc = 0; + if (!pkrb5_cc_resolve(ctx, pkrb5_cc_default_name(ctx), &cc)) + pkrb5_cc_destroy(ctx, cc); + pkrb5_cc_set_default_name(ctx, old_cache); + free(old_cache); + old_cache = 0; + } + if (ctx) { + pkrb5_free_context(ctx); + ctx = 0; + } + + if (postfix) + { + char * tmp_cache = 0; + krb5_error_code rc = 0; + + rc = pkrb5_init_context(&ctx); + if (rc) goto cleanup; + + tmp_cache = make_postfix(pkrb5_cc_default_name(ctx), postfix, + &old_cache); + + if (!tmp_cache) { + rc = ENOMEM; + goto cleanup; + } + + rc = pkrb5_cc_set_default_name(ctx, tmp_cache); + + cleanup: + if (rc && ctx) { + pkrb5_free_context(ctx); + ctx = 0; + } + if (tmp_cache) + free(tmp_cache); + if (pctx) + *pctx = ctx; + return rc; + } + return 0; +} + +long +Leash_checkpwd( + char *principal, + char *password + ) +{ + return Leash_int_checkpwd(principal, password, 0); +} + +long +Leash_int_checkpwd( + char * principal, + char * password, + int displayErrors + ) +{ + long rc = 0; + krb5_context ctx = 0; // statically allocated in make_temp_cache_v5 + // XXX - we ignore errors in make_temp_cache_v? This is BAD!!! + make_temp_cache_v5("_checkpwd", &ctx); + rc = Leash_int_kinit_ex( ctx, 0, + principal, password, 0, 0, 0, 0, + Leash_get_default_noaddresses(), + Leash_get_default_publicip(), + displayErrors + ); + make_temp_cache_v5(0, &ctx); + return rc; +} + +static +long +Leash_changepwd_v5( + char * principal, + char * password, + char * newpassword, + char** error_str + ) +{ + krb5_error_code rc = 0; + int result_code; + krb5_data result_code_string, result_string; + krb5_context context = 0; + krb5_principal princ = 0; + krb5_get_init_creds_opt opts; + krb5_creds creds; + DWORD addressless = 0; + + result_string.data = 0; + result_code_string.data = 0; + + if ( !pkrb5_init_context ) + goto cleanup; + + if (rc = pkrb5_init_context(&context)) { +#if 0 + com_err(argv[0], ret, "initializing kerberos library"); +#endif + goto cleanup; + } + + if (rc = pkrb5_parse_name(context, principal, &princ)) { +#if 0 + com_err(argv[0], ret, "parsing client name"); +#endif + goto cleanup; + } + + pkrb5_get_init_creds_opt_init(&opts); + pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); + pkrb5_get_init_creds_opt_set_renew_life(&opts, 0); + pkrb5_get_init_creds_opt_set_forwardable(&opts, 0); + pkrb5_get_init_creds_opt_set_proxiable(&opts, 0); + + addressless = Leash_get_default_noaddresses(); + if (addressless) + pkrb5_get_init_creds_opt_set_address_list(&opts,NULL); + + + if (rc = pkrb5_get_init_creds_password(context, &creds, princ, password, + 0, 0, 0, "kadmin/changepw", &opts)) { + if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) { +#if 0 + com_err(argv[0], 0, + "Password incorrect while getting initial ticket"); +#endif + } + else { +#if 0 + com_err(argv[0], ret, "getting initial ticket"); +#endif + } + goto cleanup; + } + + if (rc = pkrb5_change_password(context, &creds, newpassword, + &result_code, &result_code_string, + &result_string)) { +#if 0 + com_err(argv[0], ret, "changing password"); +#endif + goto cleanup; + } + + if (result_code) { + int len = result_code_string.length + + (result_string.length ? (sizeof(": ") - 1) : 0) + + result_string.length; + if (len && error_str) { + *error_str = malloc(len + 1); + if (*error_str) + _snprintf(*error_str, len + 1, + "%.*s%s%.*s", + result_code_string.length, result_code_string.data, + result_string.length?": ":"", + result_string.length, result_string.data); + } + rc = result_code; + goto cleanup; + } + + cleanup: + if (result_string.data) + pkrb5_free_data_contents(context, &result_string); + + if (result_code_string.data) + pkrb5_free_data_contents(context, &result_code_string); + + if (princ) + pkrb5_free_principal(context, princ); + + if (context) + pkrb5_free_context(context); + + return rc; +} + +/* + * Leash_changepwd + * + * Try to change the password using krb5. + */ +long +Leash_changepwd( + char * principal, + char * password, + char * newpassword, + char** result_string + ) +{ + return Leash_int_changepwd(principal, password, newpassword, result_string, 0); +} + +long +Leash_int_changepwd( + char * principal, + char * password, + char * newpassword, + char** result_string, + int displayErrors + ) +{ + char* v5_error_str = 0; + char* error_str = 0; + int rc5 = 0; + int rc = 0; + if (hKrb5) + rc = rc5 = Leash_changepwd_v5(principal, password, newpassword, + &v5_error_str); + if (!rc) + return 0; + if (v5_error_str) { + int len = 0; + char v5_prefix[] = "Kerberos 5: "; + char sep[] = "\n"; + + clean_string(v5_error_str); + + if (v5_error_str) + len += sizeof(sep) + sizeof(v5_prefix) + strlen(v5_error_str) + + sizeof(sep); + error_str = malloc(len + 1); + if (error_str) { + char* p = error_str; + int size = len + 1; + int n; + if (v5_error_str) { + n = _snprintf(p, size, "%s%s%s%s", + sep, v5_prefix, v5_error_str, sep); + p += n; + size -= n; + } + if (result_string) + *result_string = error_str; + } + } + return leash_error_message("Error while changing password.", + 0, rc5, 0, error_str, + displayErrors + ); +} + +int (*Lcom_err)(LPSTR,long,LPSTR,...); +LPSTR (*Lerror_message)(long); +LPSTR (*Lerror_table_name)(long); + + +long +Leash_kinit( + char * principal, + char * password, + int lifetime + ) +{ + return Leash_int_kinit_ex( 0, 0, + principal, + password, + lifetime, + Leash_get_default_forwardable(), + Leash_get_default_proxiable(), + Leash_get_default_renew_till(), + Leash_get_default_noaddresses(), + Leash_get_default_publicip(), + 0 + ); +} + +long +Leash_kinit_ex( + char * principal, + char * password, + int lifetime, + int forwardable, + int proxiable, + int renew_life, + int addressless, + unsigned long publicip + ) +{ + return Leash_int_kinit_ex( 0, /* krb5 context */ + 0, /* parent window */ + principal, + password, + lifetime, + forwardable, + proxiable, + renew_life, + addressless, + publicip, + 0 + ); +} + +long +Leash_int_kinit_ex( + krb5_context ctx, + HWND hParent, + char * principal, + char * password, + int lifetime, + int forwardable, + int proxiable, + int renew_life, + int addressless, + unsigned long publicip, + int displayErrors + ) +{ + char aname[ANAME_SZ]; + char inst[INST_SZ]; + char realm[REALM_SZ]; + char first_part[256]; + char second_part[256]; + char temp[1024]; + char* custom_msg; + int count; + int i; + int rc5 = 0; + int rcA = 0; + int rcB = 0; + int rcL = 0; + + if (lifetime < 5) + lifetime = 1; + else + lifetime /= 5; + + if (renew_life > 0 && renew_life < 5) + renew_life = 1; + else + renew_life /= 5; + + /* This should be changed if the maximum ticket lifetime */ + /* changes */ + + if (lifetime > 255) + lifetime = 255; + + err_context = "parsing principal"; + + memset(temp, '\0', sizeof(temp)); + memset(inst, '\0', sizeof(inst)); + memset(realm, '\0', sizeof(realm)); + memset(first_part, '\0', sizeof(first_part)); + memset(second_part, '\0', sizeof(second_part)); + + sscanf(principal, "%[/0-9a-zA-Z._-]@%[/0-9a-zA-Z._-]", first_part, second_part); + strcpy(temp, first_part); + strcpy(realm, second_part); + memset(first_part, '\0', sizeof(first_part)); + memset(second_part, '\0', sizeof(second_part)); + if (sscanf(temp, "%[@0-9a-zA-Z._-]/%[@0-9a-zA-Z._-]", first_part, second_part) == 2) + { + strcpy(aname, first_part); + strcpy(inst, second_part); + } + else + { + count = 0; + i = 0; + for (i = 0; temp[i]; i++) + { + if (temp[i] == '.') + ++count; + } + if (count > 1) + { + strcpy(aname, temp); + } + else + { + { + strcpy(aname, temp); + } + } + } + + memset(temp, '\0', sizeof(temp)); + strcpy(temp, aname); + if (strlen(inst) != 0) + { + strcat(temp, "/"); + strcat(temp, inst); + } + if (strlen(realm) != 0) + { + strcat(temp, "@"); + strcat(temp, realm); + } + + rc5 = Leash_krb5_kinit(ctx, hParent, + temp, password, lifetime, + forwardable, + proxiable, + renew_life, + addressless, + publicip + ); +#ifndef NO_AFS + if ( !rc5 ) { + char c; + char *r; + char *t; + for ( r=realm, t=temp; c=*r; r++,t++ ) + *t = isupper(c) ? tolower(c) : c; + *t = '\0'; + + rcA = Leash_afs_klog("afs", temp, "", lifetime); + rcB = Leash_afs_klog("afs", "", "", lifetime); + if (!(rcA && rcB)) + rcA = 0; + else if (!rcA) + rcA = rcB; + } +#endif /* NO_AFS */ + custom_msg = (rc5 == KRB5KRB_AP_ERR_BAD_INTEGRITY) ? "Password incorrect" : NULL; + return leash_error_message("Ticket initialization failed.", + rcL, rc5, rcA, custom_msg, + displayErrors); +} + +long FAR +Leash_renew(void) +{ + if ( hKrb5 && !LeashKRB5_renew() ) { + int lifetime; + lifetime = Leash_get_default_lifetime() / 5; +#ifndef NO_AFS + { + TicketList * list = NULL, * token; + not_an_API_LeashAFSGetToken(NULL,&list,NULL); + for ( token = list ; token ; token = token->next ) + Leash_afs_klog("afs", token->realm, "", lifetime); + not_an_API_LeashFreeTicketList(&list); + } +#endif /* NO_AFS */ + return 1; + } + return 0; +} + +BOOL +GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData) +{ + NTSTATUS Status = 0; + HANDLE TokenHandle; + TOKEN_STATISTICS Stats; + DWORD ReqLen; + BOOL Success; + PSECURITY_LOGON_SESSION_DATA pSessionData; + + if (!ppSessionData) + return FALSE; + *ppSessionData = NULL; + + Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle ); + if ( !Success ) + return FALSE; + + Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen ); + CloseHandle( TokenHandle ); + if ( !Success ) + return FALSE; + + Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, &pSessionData ); + if ( FAILED(Status) || !pSessionData ) + return FALSE; + + *ppSessionData = pSessionData; + return TRUE; +} + +// 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 +// and will use it to retrieve new TGTs if the cache is empty and tickets +// are requested. + +BOOL +IsKerberosLogon(VOID) +{ + PSECURITY_LOGON_SESSION_DATA pSessionData = NULL; + BOOL Success = FALSE; + + if ( GetSecurityLogonSessionData(&pSessionData) ) { + if ( pSessionData->AuthenticationPackage.Buffer ) { + WCHAR buffer[256]; + WCHAR *usBuffer; + int usLength; + + Success = FALSE; + usBuffer = (pSessionData->AuthenticationPackage).Buffer; + usLength = (pSessionData->AuthenticationPackage).Length; + if (usLength < 256) + { + lstrcpynW (buffer, usBuffer, usLength); + lstrcatW (buffer,L""); + if ( !lstrcmpW(L"Kerberos",buffer) ) + Success = TRUE; + } + } + pLsaFreeReturnBuffer(pSessionData); + } + return Success; +} + +static BOOL +IsWindowsVista (void) +{ + static BOOL fChecked = FALSE; + static BOOL fIsVista = FALSE; + + if (!fChecked) + { + OSVERSIONINFO Version; + + memset (&Version, 0x00, sizeof(Version)); + Version.dwOSVersionInfoSize = sizeof(Version); + + if (GetVersionEx (&Version)) + { + if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT && Version.dwMajorVersion >= 6) + fIsVista = TRUE; + } + fChecked = TRUE; + } + + return fIsVista; +} + +static BOOL +IsProcessUacLimited (void) +{ + static BOOL fChecked = FALSE; + static BOOL fIsUAC = FALSE; + + if (!fChecked) + { + NTSTATUS Status = 0; + HANDLE TokenHandle; + DWORD ElevationLevel; + DWORD ReqLen; + BOOL Success; + + if (IsWindowsVista()) { + Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle ); + if ( Success ) { + Success = GetTokenInformation( TokenHandle, + TokenOrigin+1 /* ElevationLevel */, + &ElevationLevel, sizeof(DWORD), &ReqLen ); + CloseHandle( TokenHandle ); + if ( Success && ElevationLevel == 3 /* Limited */ ) + fIsUAC = TRUE; + } + } + fChecked = TRUE; + } + return fIsUAC; + +} + +// This looks really ugly because it is. The result of IsKerberosLogon() +// does not prove whether or not there are Kerberos tickets available to +// be imported. Only the call to Leash_ms2mit() which actually attempts +// to import tickets can do that. However, calling Leash_ms2mit() can +// result in a TGS_REQ being sent to the KDC and since Leash_importable() +// is called quite often we want to avoid this if at all possible. +// Unfortunately, we have be shown at least one case in which the primary +// authentication package was not Kerberos and yet there were Kerberos +// tickets available. Therefore, if IsKerberosLogon() is not TRUE we +// must call Leash_ms2mit() but we still do not want to call it in a +// tight loop so we cache the response and assume it won't change. + +// 2007-03-21 +// And the nightmare goes on. On Vista the Lsa call we use to determine +// whether or not Kerberos was used for logon fails to return and worse +// corrupts the stack. Therefore, we must now test to see if the +// operating system is Vista and skip the call to IsKerberosLogon() +// if it is. +long FAR +Leash_importable(void) +{ + if (IsProcessUacLimited()) + return FALSE; + + if ( !IsWindowsVista() && IsKerberosLogon() ) + return TRUE; + else { + static int response = -1; + if (response == -1) { + response = Leash_ms2mit(0); + } + return response; + } +} + +long FAR +Leash_import(void) +{ + if ( Leash_ms2mit(1) ) { + int lifetime; + lifetime = Leash_get_default_lifetime() / 5; +#ifndef NO_AFS + { + char c; + char *r; + char *t; + char cell[256]; + char realm[256]; + int i = 0; + int rcA = 0; + int rcB = 0; + + krb5_context ctx = 0; + krb5_error_code code = 0; + krb5_ccache cc = 0; + krb5_principal me = 0; + + if ( !pkrb5_init_context ) + goto cleanup; + + code = pkrb5_init_context(&ctx); + if (code) goto cleanup; + + code = pkrb5_cc_default(ctx, &cc); + if (code) goto cleanup; + + if (code = pkrb5_cc_get_principal(ctx, cc, &me)) + goto cleanup; + + for ( r=realm, t=cell, i=0; i<krb5_princ_realm(ctx, me)->length; r++,t++,i++ ) { + c = krb5_princ_realm(ctx, me)->data[i]; + *r = c; + *t = isupper(c) ? tolower(c) : c; + } + *r = *t = '\0'; + + rcA = Leash_afs_klog("afs", cell, "", lifetime); + rcB = Leash_afs_klog("afs", "", "", lifetime); + if (!(rcA && rcB)) + rcA = 0; + else if (!rcA) + rcA = rcB; + + cleanup: + if (me) + pkrb5_free_principal(ctx, me); + if (cc) + pkrb5_cc_close(ctx, cc); + if (ctx) + pkrb5_free_context(ctx); + } +#endif /* NO_AFS */ + return 1; + } + return 0; +} + +long +Leash_kdestroy(void) +{ + Leash_afs_unlog(); + Leash_krb5_kdestroy(); + + return 0; +} + +long FAR +not_an_API_LeashFreeTicketList(TicketList** ticketList) +{ + TicketList* tempList = *ticketList, *killList; + + //if (tempList == NULL) + //return -1; + + while (tempList) + { + killList = tempList; + + tempList = (TicketList*)tempList->next; + free(killList->service); + if (killList->encTypes) + free(killList->encTypes); + free(killList); + } + + *ticketList = NULL; + return 0; +} + +long +not_an_API_LeashKRB4GetTickets(TICKETINFO FAR* ticketinfo, + TicketList** ticketList) +{ + return(KFAILURE); +} + +long FAR Leash_klist(HWND hlist, TICKETINFO FAR *ticketinfo) +{ + return(KFAILURE); +} + + +// This function can be used to set the help file that will be +// referenced the DLL's PasswordProcDLL function and err_describe +// function. Returns true if the help file has been set to the +// argument or the environment variable KERB_HELP. Returns FALSE if +// the default helpfile as defined in by HELPFILE in lsh_pwd.h is +// used. +BOOL Leash_set_help_file( char *szHelpFile ) +{ + char tmpHelpFile[256]; + BOOL ret = 0; + + if( szHelpFile == NULL ){ + GetEnvironmentVariable("KERB_HELP", tmpHelpFile, sizeof(tmpHelpFile)); + } else { + strcpy( KRB_HelpFile, szHelpFile ); + ret++; + } + + if( !ret && tmpHelpFile[0] ){ + strcpy( KRB_HelpFile, tmpHelpFile ); + ret++; + } + + if( !ret){ + strcpy( KRB_HelpFile, HELPFILE ); + } + + return(ret); +} + + + +LPSTR Leash_get_help_file(void) +{ + return( KRB_HelpFile); +} + +int +Leash_debug( + int class, + int priority, + char* fmt, ... + ) +{ + + return 0; +} + + +static int +get_profile_file(LPSTR confname, UINT szConfname) +{ + char **configFile = NULL; + if (hKrb5) { + if (pkrb5_get_default_config_files(&configFile) || !configFile[0]) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,"\\KRB5.INI",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + return FALSE; + } + + *confname = 0; + + if (configFile) + { + strncpy(confname, *configFile, szConfname); + confname[szConfname-1] = '\0'; + pkrb5_free_config_files(configFile); + } + } + + if (!*confname) + { + GetWindowsDirectory(confname,szConfname); + confname[szConfname-1] = '\0'; + strncat(confname,"\\KRB5.INI",szConfname-strlen(confname)); + confname[szConfname-1] = '\0'; + } + + return FALSE; +} + +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +int +config_boolean_to_int(const char *s) +{ + const char *const *p; + + for(p=conf_yes; *p; p++) { + if (!strcasecmp(*p,s)) + return 1; + } + + for(p=conf_no; *p; p++) { + if (!strcasecmp(*p,s)) + return 0; + } + + /* Default to "no" */ + return 0; +} + +/* + * Leash_get_default_lifetime: + * + * This function is used to get the default ticket lifetime for this + * process in minutes. A return value of 0 indicates no setting or + * "default" setting obtained. + * + * Here is where we look in order: + * + * - LIFETIME environment variable + * - HKCU\Software\MIT\Leash,lifetime + * - HKLM\Software\MIT\Leash,lifetime + * - string resource in the leash DLL + */ + +BOOL +get_DWORD_from_registry( + HKEY hBaseKey, + char * key, + char * value, + DWORD * result + ) +{ + HKEY hKey; + DWORD dwCount; + LONG rc; + + rc = RegOpenKeyEx(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey); + if (rc) + return FALSE; + + dwCount = sizeof(DWORD); + rc = RegQueryValueEx(hKey, value, 0, 0, (LPBYTE) result, &dwCount); + RegCloseKey(hKey); + + return rc?FALSE:TRUE; +} + +BOOL +get_STRING_from_registry( + HKEY hBaseKey, + char * key, + char * value, + char * outbuf, + DWORD outlen + ) +{ + HKEY hKey; + DWORD dwCount; + LONG rc; + + if (!outbuf || outlen == 0) + return FALSE; + + rc = RegOpenKeyEx(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey); + if (rc) + return FALSE; + + dwCount = outlen; + rc = RegQueryValueEx(hKey, value, 0, 0, (LPBYTE) outbuf, &dwCount); + RegCloseKey(hKey); + + return rc?FALSE:TRUE; +} + +static +BOOL +get_default_lifetime_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_LIFETIME, + result); +} + +DWORD +Leash_reset_default_lifetime( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFETIME); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_lifetime( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFETIME, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_lifetime( + ) +{ + HMODULE hmLeash; + char env[32]; + DWORD result; + + + if (GetEnvironmentVariable("LIFETIME",env,sizeof(env))) + { + return atoi(env); + } + + + if (get_default_lifetime_from_registry(HKEY_CURRENT_USER, &result) || + get_default_lifetime_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + if ( hKrb5 ) { + CHAR confname[MAX_PATH]; + + if (!get_profile_file(confname, sizeof(confname))) + { + profile_t profile; + const char *filenames[2]; + long retval; + + filenames[0] = confname; + filenames[1] = NULL; + if (!pprofile_init(filenames, &profile)) { + char * value = NULL; + + retval = pprofile_get_string(profile, "libdefaults", "ticket_lifetime", NULL, NULL, &value); + if (retval == 0 && value) { + krb5_deltat d; + + retval = pkrb5_string_to_deltat(value, &d); + + if (retval == KRB5_DELTAT_BADFORMAT) { + /* Historically some sites use relations of + the form 'ticket_lifetime = 24000' where + the unit is left out but is assumed to be + seconds. Then there are other sites which + use the form 'ticket_lifetime = 600' where + the unit is assumed to be minutes. While + these are technically wrong (a unit needs + to be specified), we try to accomodate for + this using the safe assumption that the + unit is seconds and tack an 's' to the end + and see if that works. */ + + /* Of course, Leash is one of the platforms + that historically assumed no units and minutes + so this change is going to break some people + but its better to be consistent. */ + size_t cch; + char buf[256]; + + do { + cch = strlen(value) + 2; /* NUL and new 's' */ + if (cch > sizeof(buf)) + break; + + strcpy(buf, value); + strcat(buf, "s"); + + retval = pkrb5_string_to_deltat(buf, &d); + + if (retval == 0) { + result = d / 60; + } + } while(0); + } else if (retval == 0) { + result = d / 60; + } + + pprofile_release_string(value); + } + pprofile_release(profile); + /* value has been released but we can still use a check for + * non-NULL to see if we were able to read a value. + */ + if (retval == 0 && value) + return result; + } + } + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char lifetime[80]; + if (LoadString(hmLeash, LSH_DEFAULT_TICKET_LIFE, + lifetime, sizeof(lifetime))) + { + lifetime[sizeof(lifetime) - 1] = 0; + return atoi(lifetime); + } + } + return 0; +} + +static +BOOL +get_default_renew_till_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_RENEW_TILL, + result); +} + +DWORD +Leash_reset_default_renew_till( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_renew_till( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_renew_till( + ) +{ + HMODULE hmLeash; + char env[32]; + DWORD result; + + if(GetEnvironmentVariable("RENEW_TILL",env,sizeof(env))) + { + return atoi(env); + } + + if (get_default_renew_till_from_registry(HKEY_CURRENT_USER, &result) || + get_default_renew_till_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + if ( hKrb5 ) { + CHAR confname[MAX_PATH]; + if (!get_profile_file(confname, sizeof(confname))) + { + profile_t profile; + const char *filenames[2]; + int value=0; + long retval; + filenames[0] = confname; + filenames[1] = NULL; + + if (!pprofile_init(filenames, &profile)) { + char * value = NULL; + + retval = pprofile_get_string(profile, "libdefaults", "renew_lifetime", NULL, NULL, &value); + if (retval == 0 && value) { + krb5_deltat d; + + retval = pkrb5_string_to_deltat(value, &d); + if (retval == KRB5_DELTAT_BADFORMAT) { + /* Historically some sites use relations of + the form 'ticket_lifetime = 24000' where + the unit is left out but is assumed to be + seconds. Then there are other sites which + use the form 'ticket_lifetime = 600' where + the unit is assumed to be minutes. While + these are technically wrong (a unit needs + to be specified), we try to accomodate for + this using the safe assumption that the + unit is seconds and tack an 's' to the end + and see if that works. */ + + /* Of course, Leash is one of the platforms + that historically assumed no units and minutes + so this change is going to break some people + but its better to be consistent. */ + size_t cch; + char buf[256]; + do { + cch = strlen(value) + 2; /* NUL and new 's' */ + if (cch > sizeof(buf)) + break; + + strcpy(buf, value); + strcat(buf, "s"); + + retval = pkrb5_string_to_deltat(buf, &d); + if (retval == 0) { + result = d / 60; + } + } while(0); + } else if (retval == 0) { + result = d / 60; + } + pprofile_release_string(value); + } + pprofile_release(profile); + /* value has been released but we can still use a check for + * non-NULL to see if we were able to read a value. + */ + if (retval == 0 && value) + return result; + + pprofile_release(profile); + } + } + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char renew_till[80]; + if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW_TILL, + renew_till, sizeof(renew_till))) + { + renew_till[sizeof(renew_till) - 1] = 0; + return atoi(renew_till); + } + } + return 0; +} + +static +BOOL +get_default_forwardable_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_FORWARDABLE, + result); +} + +DWORD +Leash_reset_default_forwardable( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_forwardable( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_forwardable( + ) +{ + HMODULE hmLeash; + + char env[32]; + DWORD result; + + if(GetEnvironmentVariable("FORWARDABLE",env,sizeof(env))) + { + return atoi(env); + } + + if (get_default_forwardable_from_registry(HKEY_CURRENT_USER, &result) || + get_default_forwardable_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + if ( hKrb5 ) { + CHAR confname[MAX_PATH]; + if (!get_profile_file(confname, sizeof(confname))) + { + profile_t profile; + const char *filenames[2]; + char *value=0; + long retval; + filenames[0] = confname; + filenames[1] = NULL; + if (!pprofile_init(filenames, &profile)) { + retval = pprofile_get_string(profile, "libdefaults","forwardable", 0, 0, &value); + if ( value ) { + result = config_boolean_to_int(value); + pprofile_release_string(value); + pprofile_release(profile); + return result; + } + pprofile_release(profile); + } + } + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char forwardable[80]; + if (LoadString(hmLeash, LSH_DEFAULT_TICKET_FORWARD, + forwardable, sizeof(forwardable))) + { + forwardable[sizeof(forwardable) - 1] = 0; + return atoi(forwardable); + } + } + return 0; +} + +static +BOOL +get_default_renewable_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_RENEWABLE, + result); +} + +DWORD +Leash_reset_default_renewable( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEWABLE); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_renewable( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEWABLE, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_renewable( + ) +{ + HMODULE hmLeash; + char env[32]; + DWORD result; + + if(GetEnvironmentVariable("RENEWABLE",env,sizeof(env))) + { + return atoi(env); + } + + if (get_default_renewable_from_registry(HKEY_CURRENT_USER, &result) || + get_default_renewable_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + if ( hKrb5 ) { + CHAR confname[MAX_PATH]; + if (!get_profile_file(confname, sizeof(confname))) + { + profile_t profile; + const char *filenames[2]; + char *value=0; + long retval; + filenames[0] = confname; + filenames[1] = NULL; + if (!pprofile_init(filenames, &profile)) { + retval = pprofile_get_string(profile, "libdefaults","renewable", 0, 0, &value); + if ( value ) { + result = config_boolean_to_int(value); + pprofile_release_string(value); + pprofile_release(profile); + return result; + } + pprofile_release(profile); + } + } + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char renewable[80]; + if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW, + renewable, sizeof(renewable))) + { + renewable[sizeof(renewable) - 1] = 0; + return atoi(renewable); + } + } + return 0; +} + +static +BOOL +get_default_noaddresses_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_NOADDRESSES, + result); +} + +DWORD +Leash_reset_default_noaddresses( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_noaddresses( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_noaddresses( + ) +{ + HMODULE hmLeash; + char env[32]; + DWORD result; + + if ( hKrb5 ) { + // if the profile file cannot be opened then the value will be true + // if the noaddresses name cannot be found then the value will be true + // if true in the library, we can't alter it by other means + CHAR confname[MAX_PATH]; + result = 1; + if (!get_profile_file(confname, sizeof(confname))) + { + profile_t profile; + const char *filenames[2]; + char *value=0; + long retval; + filenames[0] = confname; + filenames[1] = NULL; + if (!pprofile_init(filenames, &profile)) { + retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value); + if ( value ) { + result = config_boolean_to_int(value); + pprofile_release_string(value); + } + pprofile_release(profile); + } + } + + if ( result ) + return 1; + } + + // The library default is false, check other locations + + if(GetEnvironmentVariable("NOADDRESSES",env,sizeof(env))) + { + return atoi(env); + } + + if (get_default_noaddresses_from_registry(HKEY_CURRENT_USER, &result) || + get_default_noaddresses_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char noaddresses[80]; + if (LoadString(hmLeash, LSH_DEFAULT_TICKET_NOADDRESS, + noaddresses, sizeof(noaddresses))) + { + noaddresses[sizeof(noaddresses) - 1] = 0; + } + } + return 1; +} + +static +BOOL +get_default_proxiable_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_PROXIABLE, + result); +} + +DWORD +Leash_reset_default_proxiable( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PROXIABLE); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_proxiable( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PROXIABLE, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_proxiable( + ) +{ + HMODULE hmLeash; + char env[32]; + DWORD result; + + if(GetEnvironmentVariable("PROXIABLE",env,sizeof(env))) + { + return atoi(env); + } + + if (get_default_proxiable_from_registry(HKEY_CURRENT_USER, &result) || + get_default_proxiable_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + if ( hKrb5 ) { + CHAR confname[MAX_PATH]; + if (!get_profile_file(confname, sizeof(confname))) + { + profile_t profile; + const char *filenames[2]; + char *value=0; + long retval; + filenames[0] = confname; + filenames[1] = NULL; + if (!pprofile_init(filenames, &profile)) { + retval = pprofile_get_string(profile, "libdefaults","proxiable", 0, 0, &value); + if ( value ) { + result = config_boolean_to_int(value); + pprofile_release_string(value); + pprofile_release(profile); + return result; + } + pprofile_release(profile); + } + } + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char proxiable[80]; + if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PROXIABLE, + proxiable, sizeof(proxiable))) + { + proxiable[sizeof(proxiable) - 1] = 0; + return atoi(proxiable); + } + } + return 0; +} + +static +BOOL +get_default_publicip_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_PUBLICIP, + result); +} + +DWORD +Leash_reset_default_publicip( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PUBLICIP); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_publicip( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PUBLICIP, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_publicip( + ) +{ + HMODULE hmLeash; + char env[32]; + DWORD result; + + if(GetEnvironmentVariable("PUBLICIP",env,sizeof(env))) + { + return atoi(env); + } + + if (get_default_publicip_from_registry(HKEY_CURRENT_USER, &result) || + get_default_publicip_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char publicip[80]; + if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PUBLICIP, + publicip, sizeof(publicip))) + { + publicip[sizeof(publicip) - 1] = 0; + return atoi(publicip); + } + } + return 0; +} + +static +BOOL +get_default_use_krb4_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_USEKRB4, + result); +} + +DWORD +Leash_reset_default_use_krb4( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_USEKRB4); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_use_krb4( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_USEKRB4, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_use_krb4( + ) +{ + return 0; /* don't use krb4 */ +} + +static +BOOL +get_hide_kinit_options_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_KINIT_OPT, + result); +} + +DWORD +Leash_reset_hide_kinit_options( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_hide_kinit_options( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_hide_kinit_options( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_hide_kinit_options_from_registry(HKEY_CURRENT_USER, &result) || + get_hide_kinit_options_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char use_krb4[80]; + if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_KINIT_OPT, + use_krb4, sizeof(use_krb4))) + { + use_krb4[sizeof(use_krb4) - 1] = 0; + return atoi(use_krb4); + } + } + return 0; /* hide unless otherwise indicated */ +} + + + +static +BOOL +get_default_life_min_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_LIFE_MIN, + result); +} + +DWORD +Leash_reset_default_life_min( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_life_min( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_life_min( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_default_life_min_from_registry(HKEY_CURRENT_USER, &result) || + get_default_life_min_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char use_krb4[80]; + if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MIN, + use_krb4, sizeof(use_krb4))) + { + use_krb4[sizeof(use_krb4) - 1] = 0; + return atoi(use_krb4); + } + } + return 5; /* 5 minutes */ +} + +static +BOOL +get_default_life_max_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_LIFE_MAX, + result); +} + +DWORD +Leash_reset_default_life_max( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_life_max( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_life_max( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_default_life_max_from_registry(HKEY_CURRENT_USER, &result) || + get_default_life_max_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char use_krb4[80]; + if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MAX, + use_krb4, sizeof(use_krb4))) + { + use_krb4[sizeof(use_krb4) - 1] = 0; + return atoi(use_krb4); + } + } + return 1440; +} + +static +BOOL +get_default_renew_min_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_RENEW_MIN, + result); +} + +DWORD +Leash_reset_default_renew_min( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_renew_min( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_renew_min( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_default_renew_min_from_registry(HKEY_CURRENT_USER, &result) || + get_default_renew_min_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char use_krb4[80]; + if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MIN, + use_krb4, sizeof(use_krb4))) + { + use_krb4[sizeof(use_krb4) - 1] = 0; + return atoi(use_krb4); + } + } + return 600; /* 10 hours */ +} + +static +BOOL +get_default_renew_max_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_RENEW_MAX, + result); +} + +DWORD +Leash_reset_default_renew_max( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_renew_max( + DWORD minutes + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX, 0, REG_DWORD, + (LPBYTE) &minutes, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_renew_max( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_default_renew_max_from_registry(HKEY_CURRENT_USER, &result) || + get_default_renew_max_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char use_krb4[80]; + if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MAX, + use_krb4, sizeof(use_krb4))) + { + use_krb4[sizeof(use_krb4) - 1] = 0; + return atoi(use_krb4); + } + } + return 60 * 24 * 30; +} + +static +BOOL +get_lock_file_locations_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_LOCK_LOCATION, + result); +} + +DWORD +Leash_reset_lock_file_locations( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LOCK_LOCATION); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_lock_file_locations( + DWORD onoff + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LOCK_LOCATION, 0, REG_DWORD, + (LPBYTE) &onoff, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_lock_file_locations( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_lock_file_locations_from_registry(HKEY_CURRENT_USER, &result) || + get_lock_file_locations_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char lock_file_locations[80]; + if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LOCK_LOCATION, + lock_file_locations, sizeof(lock_file_locations))) + { + lock_file_locations[sizeof(lock_file_locations) - 1] = 0; + return atoi(lock_file_locations); + } + } + return 0; +} + +static +BOOL +get_default_uppercaserealm_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_SETTINGS_REGISTRY_KEY_NAME, + LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM, + result); +} + +DWORD +Leash_reset_default_uppercaserealm( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_uppercaserealm( + DWORD onoff + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM, 0, REG_DWORD, + (LPBYTE) &onoff, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_uppercaserealm( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_default_uppercaserealm_from_registry(HKEY_CURRENT_USER, &result) || + get_default_uppercaserealm_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char uppercaserealm[80]; + if (LoadString(hmLeash, LSH_DEFAULT_UPPERCASEREALM, + uppercaserealm, sizeof(uppercaserealm))) + { + uppercaserealm[sizeof(uppercaserealm) - 1] = 0; + return atoi(uppercaserealm); + } + } + return 1; +} + +static +BOOL +get_default_mslsa_import_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_SETTINGS_REGISTRY_KEY_NAME, + LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT, + result); +} + +DWORD +Leash_reset_default_mslsa_import( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_mslsa_import( + DWORD onoffmatch + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT, 0, REG_DWORD, + (LPBYTE) &onoffmatch, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_mslsa_import( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_default_mslsa_import_from_registry(HKEY_CURRENT_USER, &result) || + get_default_mslsa_import_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char mslsa_import[80]; + if (LoadString(hmLeash, LSH_DEFAULT_MSLSA_IMPORT, + mslsa_import, sizeof(mslsa_import))) + { + mslsa_import[sizeof(mslsa_import) - 1] = 0; + return atoi(mslsa_import); + } + } + return 2; /* import only when mslsa realm matches default */ +} + + +static +BOOL +get_default_preserve_kinit_settings_from_registry( + HKEY hBaseKey, + DWORD * result + ) +{ + return get_DWORD_from_registry(hBaseKey, + LEASH_REGISTRY_KEY_NAME, + LEASH_REGISTRY_VALUE_PRESERVE_KINIT, + result); +} + +DWORD +Leash_reset_default_preserve_kinit_settings( + ) +{ + HKEY hKey; + LONG rc; + + rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey); + if (rc) + return rc; + + rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_set_default_preserve_kinit_settings( + DWORD onoff + ) +{ + HKEY hKey; + LONG rc; + + rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, + 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) + return rc; + + rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT, 0, REG_DWORD, + (LPBYTE) &onoff, sizeof(DWORD)); + RegCloseKey(hKey); + + return rc; +} + +DWORD +Leash_get_default_preserve_kinit_settings( + ) +{ + HMODULE hmLeash; + DWORD result; + + if (get_default_preserve_kinit_settings_from_registry(HKEY_CURRENT_USER, &result) || + get_default_preserve_kinit_settings_from_registry(HKEY_LOCAL_MACHINE, &result)) + { + return result; + } + + hmLeash = GetModuleHandle(LEASH_DLL); + if (hmLeash) + { + char preserve_kinit_settings[80]; + if (LoadString(hmLeash, LSH_DEFAULT_PRESERVE_KINIT, + preserve_kinit_settings, sizeof(preserve_kinit_settings))) + { + preserve_kinit_settings[sizeof(preserve_kinit_settings) - 1] = 0; + return atoi(preserve_kinit_settings); + } + } + return 1; +} + +void +Leash_reset_defaults(void) +{ + Leash_reset_default_lifetime(); + Leash_reset_default_renew_till(); + Leash_reset_default_renewable(); + Leash_reset_default_forwardable(); + Leash_reset_default_noaddresses(); + Leash_reset_default_proxiable(); + Leash_reset_default_publicip(); + Leash_reset_default_use_krb4(); + Leash_reset_hide_kinit_options(); + Leash_reset_default_life_min(); + Leash_reset_default_life_max(); + Leash_reset_default_renew_min(); + Leash_reset_default_renew_max(); + Leash_reset_default_uppercaserealm(); + Leash_reset_default_mslsa_import(); + Leash_reset_default_preserve_kinit_settings(); +} + +static void +acquire_tkt_send_msg_leash(const char *title, + const char *ccachename, + const char *name, + const char *realm) +{ + DWORD leashProcessId = 0; + DWORD bufsize = 4096; + DWORD step; + HANDLE hLeashProcess = NULL; + HANDLE hMapFile = NULL; + HANDLE hTarget = NULL; + HWND hLeashWnd = FindWindow("LEASH.0WNDCLASS", NULL); + char *strs; + void *view; + if (!hLeashWnd) + // no leash window + return; + + GetWindowThreadProcessId(hLeashWnd, &leashProcessId); + hLeashProcess = OpenProcess(PROCESS_DUP_HANDLE, + FALSE, + leashProcessId); + if (!hLeashProcess) + // can't get process handle; use GetLastError() for more info + return; + + hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max size (high 32) + bufsize, // max size (low 32) + NULL); // name + if (!hMapFile) { + // GetLastError() for more info + CloseHandle(hLeashProcess); + return; + } + + SetForegroundWindow(hLeashWnd); + + view = MapViewOfFile(hMapFile, + FILE_MAP_ALL_ACCESS, + 0, + 0, + bufsize); + if (view != NULL) { + /* construct a marshalling of data + * <title><principal><realm><ccache> + * then send to Leash + */ + strs = (char *)view; + // first reserve space for three more NULLs (4 strings total) + bufsize -= 3; + // Dialog title + if (title != NULL) + strcpy_s(strs, bufsize, title); + else if (name != NULL && realm != NULL) + sprintf_s(strs, bufsize, + "MIT Kerberos: Get Ticket for %s@%s", name, realm); + else + strcpy_s(strs, bufsize, "MIT Kerberos: Get Ticket"); + step = strlen(strs); + strs += step + 1; + bufsize -= step; + // name and realm + if (name != NULL) { + strcpy_s(strs, bufsize, name); + step = strlen(strs); + strs += step + 1; + bufsize -= step; + if (realm != NULL) { + strcpy_s(strs, bufsize, realm); + step = strlen(strs); + strs += step + 1; + bufsize -= step; + } else { + *strs = 0; + strs++; + } + } else { + *strs = 0; + strs++; + *strs = 0; + strs++; + } + + /* Append the ccache name */ + if (ccachename != NULL) + strcpy_s(strs, bufsize, ccachename); + else + *strs = 0; + + UnmapViewOfFile(view); + } + // Duplicate the file mapping handle to one leash can use + if (DuplicateHandle(GetCurrentProcess(), + hMapFile, + hLeashProcess, + &hTarget, + PAGE_READWRITE, + FALSE, + DUPLICATE_SAME_ACCESS | + DUPLICATE_CLOSE_SOURCE)) { + /* 32809 = ID_OBTAIN_TGT_WITH_LPARAM in src/windows/leash/resource.h */ + SendMessage(hLeashWnd, 32809, 0, (LPARAM) hTarget); + } else { + // GetLastError() + } +} + +static int +acquire_tkt_send_msg(krb5_context ctx, const char * title, + const char * ccachename, + krb5_principal desiredKrb5Principal, + char * out_ccname, int out_cclen) +{ + krb5_error_code err; + HWND hNetIdMgr; + HWND hForeground; + char *desiredName = 0; + char *desiredRealm = 0; + + /* do we want a specific client principal? */ + if (desiredKrb5Principal != NULL) { + err = pkrb5_unparse_name (ctx, desiredKrb5Principal, &desiredName); + if (!err) { + char * p; + for (p = desiredName; *p && *p != '@'; p++); + if ( *p == '@' ) { + *p = '\0'; + desiredRealm = ++p; + } + } + } + + hForeground = GetForegroundWindow(); + hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon"); + if (hNetIdMgr != NULL) { + HANDLE hMap; + DWORD tid = GetCurrentThreadId(); + char mapname[256]; + NETID_DLGINFO *dlginfo; + + sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid); + + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, + 0, 4096, mapname); + if (hMap == NULL) { + return -1; + } else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) { + CloseHandle(hMap); + return -1; + } + + dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE, + 0, 0, 4096, NULL); + if (dlginfo == NULL) { + CloseHandle(hMap); + return -1; + } + + memset(dlginfo, 0, sizeof(NETID_DLGINFO)); + + dlginfo->size = sizeof(NETID_DLGINFO); + dlginfo->dlgtype = NETID_DLGTYPE_TGT; + dlginfo->in.use_defaults = 1; + + if (title) { + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + title, -1, + dlginfo->in.title, NETID_TITLE_SZ); + } else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) { + char mytitle[NETID_TITLE_SZ]; + sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + mytitle, -1, + dlginfo->in.title, NETID_TITLE_SZ); + } else { + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + "Obtain Kerberos TGT", -1, + dlginfo->in.title, NETID_TITLE_SZ); + } + if (desiredName) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + desiredName, -1, + dlginfo->in.username, NETID_USERNAME_SZ); + if (desiredRealm) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + desiredRealm, -1, + dlginfo->in.realm, NETID_REALM_SZ); + if (ccachename) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, + ccachename, -1, + dlginfo->in.ccache, NETID_CCACHE_NAME_SZ); + SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid); + + if (out_ccname && out_cclen > 0) { + WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, dlginfo->out.ccache, -1, + out_ccname, out_cclen, NULL, NULL); + } + + UnmapViewOfFile(dlginfo); + CloseHandle(hMap); + } else { + acquire_tkt_send_msg_leash(title, + ccachename, desiredName, desiredRealm); + } + + SetForegroundWindow(hForeground); + if (desiredName != NULL) + pkrb5_free_unparsed_name(ctx, desiredName); + + return 0; +} + +static BOOL cc_have_tickets(krb5_context ctx, krb5_ccache cache) +{ + krb5_cc_cursor cur = NULL; + krb5_creds creds; + krb5_flags flags; + krb5_error_code code; + BOOL have_tickets = FALSE; + + // Don't need the actual ticket. + flags = KRB5_TC_NOTICKET; + code = pkrb5_cc_set_flags(ctx, cache, flags); + if (code) + goto cleanup; + code = pkrb5_cc_start_seq_get(ctx, cache, &cur); + if (code) + goto cleanup; + + _tzset(); + while (!(code = pkrb5_cc_next_cred(ctx, cache, &cur, &creds))) { + if ((!pkrb5_is_config_principal(ctx, creds.server)) && + (creds.times.endtime - time(0) > 0)) + have_tickets = TRUE; + + pkrb5_free_cred_contents(ctx, &creds); + } + if (code == KRB5_CC_END) { + code = pkrb5_cc_end_seq_get(ctx, cache, &cur); + if (code) + goto cleanup; + flags = 0; + code = pkrb5_cc_set_flags(ctx, cache, flags); + if (code) + goto cleanup; + } +cleanup: + return have_tickets; +} + +static BOOL +cc_have_tickets_for_princ(krb5_context ctx, + krb5_ccache cache, + krb5_principal princ) +{ + krb5_error_code code; + krb5_principal cc_princ = NULL; + BOOL have_tickets = FALSE; + code = pkrb5_cc_get_principal(ctx, cache, &cc_princ); + if (code) + goto cleanup; + + if (pkrb5_principal_compare(ctx, princ, cc_princ)) + have_tickets = cc_have_tickets(ctx, cache); + +cleanup: + if (cc_princ != NULL) + pkrb5_free_principal(ctx, cc_princ); + return have_tickets; +} + +static BOOL cc_default_have_tickets(krb5_context ctx) +{ + krb5_ccache cache = NULL; + BOOL have_tickets = FALSE; + if (pkrb5_cc_default(ctx, &cache) == 0) + have_tickets = cc_have_tickets(ctx, cache); + if (cache != NULL) + pkrb5_cc_close(ctx, cache); + return have_tickets; +} + +static BOOL +cccol_have_tickets_for_princ(krb5_context ctx, + krb5_principal princ, + char *ccname, + int cclen) +{ + krb5_error_code code; + krb5_ccache cache; + krb5_cccol_cursor cursor; + BOOL have_tickets = FALSE; + char *ccfullname; + + code = pkrb5_cccol_cursor_new(ctx, &cursor); + if (code) + goto cleanup; + + while (!have_tickets && + !(code = pkrb5_cccol_cursor_next(ctx, cursor, &cache)) && + cache != NULL) { + if (cc_have_tickets_for_princ(ctx, cache, princ)) { + if (pkrb5_cc_get_full_name(ctx, cache, &ccfullname)==0) { + strcpy_s(ccname, cclen, ccfullname); + pkrb5_free_string(ctx, ccfullname); + have_tickets = TRUE; + } + } + pkrb5_cc_close(ctx, cache); + } + pkrb5_cccol_cursor_free(ctx, &cursor); +cleanup: + + return have_tickets; +} + +static void +acquire_tkt_no_princ(krb5_context context, char * ccname, int cclen) +{ + TicketList *list = NULL; + krb5_context ctx; + DWORD dwMsLsaImport = Leash_get_default_mslsa_import(); + DWORD gle; + char ccachename[272]=""; + char loginenv[16]; + BOOL prompt; + BOOL haveTickets; + + GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv)); + prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND); + + ctx = context; + + SetLastError(0); + GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename)); + gle = GetLastError(); + if ( ((gle == ERROR_ENVVAR_NOT_FOUND) || !ccachename[0]) && context ) { + const char * ccdef = pkrb5_cc_default_name(ctx); + SetEnvironmentVariable("KRB5CCNAME", ccdef ? ccdef : NULL); + GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename)); + } + + haveTickets = cc_default_have_tickets(ctx); + if ((!haveTickets) && + dwMsLsaImport && Leash_importable() ) { + // We have the option of importing tickets from the MSLSA + // but should we? Do the tickets in the MSLSA cache belong + // to the default realm used by Leash? Does the default + // ccache name specify a principal name? Only import if we + // aren't going to break the default identity as specified + // by the user in Network Identity Manager. + int import = 0; + BOOL isCCPrinc; + + /* Determine if the default ccachename is principal name. If so, don't + * import the MSLSA: credentials into it unless the names match. + */ + isCCPrinc = (strncmp("API:",ccachename, 4) == 0 && strchr(ccachename, '@')); + + if ( dwMsLsaImport == 1 && !isCCPrinc ) { /* always import */ + import = 1; + } else if ( dwMsLsaImport ) { /* import when realms match */ + krb5_error_code code; + krb5_ccache mslsa_ccache=NULL; + krb5_principal princ = NULL; + char *mslsa_principal = NULL; + char ms_realm[128] = "", *def_realm = NULL, *r; + size_t i; + + if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ)) + goto cleanup; + + for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) { + *r = krb5_princ_realm(ctx, princ)->data[i]; + } + *r = '\0'; + + if (code = pkrb5_get_default_realm(ctx, &def_realm)) + goto cleanup; + + if (code = pkrb5_unparse_name(ctx, princ, &mslsa_principal)) + goto cleanup; + + import = (!isCCPrinc && !strcmp(def_realm, ms_realm)) || + (isCCPrinc && !strcmp(&ccachename[4], mslsa_principal)); + + cleanup: + if (mslsa_principal) + pkrb5_free_unparsed_name(ctx, mslsa_principal); + + if (def_realm) + pkrb5_free_default_realm(ctx, def_realm); + + if (princ) + pkrb5_free_principal(ctx, princ); + + if (mslsa_ccache) + pkrb5_cc_close(ctx, mslsa_ccache); + } + + if ( import ) { + Leash_import(); + haveTickets = cc_default_have_tickets(ctx); + } + } + + if ( prompt && !haveTickets ) { + acquire_tkt_send_msg(ctx, NULL, ccachename, NULL, ccname, cclen); + /* + * If the ticket manager returned an alternative credential cache + * remember it as the default for this process. + */ + if ( ccname && ccname[0] && strcmp(ccachename,ccname) ) { + SetEnvironmentVariable("KRB5CCNAME",ccname); + } + + } else if (ccachename[0] && ccname) { + strncpy(ccname, ccachename, cclen); + ccname[cclen-1] = '\0'; + } + if ( !context ) + pkrb5_free_context(ctx); +} + + +static void +acquire_tkt_for_princ(krb5_context ctx, krb5_principal desiredPrincipal, + char * ccname, int cclen) +{ + DWORD gle; + char ccachename[272]=""; + char loginenv[16]; + BOOL prompt; + + GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv)); + prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND); + + SetLastError(0); + GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename)); + gle = GetLastError(); + if ((gle == ERROR_ENVVAR_NOT_FOUND || !ccachename[0]) && ctx != NULL) { + const char * ccdef = pkrb5_cc_default_name(ctx); + SetEnvironmentVariable("KRB5CCNAME", ccdef ? ccdef : NULL); + GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename)); + } + if (!cccol_have_tickets_for_princ(ctx, desiredPrincipal, ccname, cclen)) { + if (prompt) { + acquire_tkt_send_msg(ctx, NULL, + ccachename, desiredPrincipal, ccname, cclen); + /* + * If the ticket manager returned an alternative credential cache + * remember it as the default for this process. + */ + if (ccname != NULL && ccname[0] && + strcmp(ccachename, ccname)) { + SetEnvironmentVariable("KRB5CCNAME",ccname); + } + } + } +} + + +void FAR +not_an_API_Leash_AcquireInitialTicketsIfNeeded(krb5_context context, + krb5_principal desiredKrb5Principal, + char * ccname, int cclen) +{ + if (!desiredKrb5Principal) { + acquire_tkt_no_princ(context, ccname, cclen); + } else { + acquire_tkt_for_princ(context, desiredKrb5Principal, ccname, cclen); + } + return; +} diff --git a/src/windows/leashdll/lshutil.cpp b/src/windows/leashdll/lshutil.cpp new file mode 100644 index 000000000000..37c0723f3b2e --- /dev/null +++ b/src/windows/leashdll/lshutil.cpp @@ -0,0 +1,608 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* prototype/prototype.c - <<< One-line description of file >>> */ +/* leashdll/lshutil.cpp - text maniuplation for principal entry */ +/* + * Copyright (C) 2012 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * 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, 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 and/or other materials provided with the + * distribution. + * + * 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * + * Leash Principal Edit Control + * + * Edit control customized to enter a principal. + * -Autocomplete functionality using history of previously successful + * authentications + * -Option to automatically convert realm to uppercase as user types + * -Suggest default realm when no matches available from history + */ + +#include <windows.h> +#include <wtypes.h> // LPOLESTR +#include <Shldisp.h> // IAutoComplete +#include <ShlGuid.h> // CLSID_AutoComplete +#include <shobjidl.h> // IAutoCompleteDropDown +#include <objbase.h> // CoCreateInstance +#include <tchar.h> +#include <map> +#include <vector> + +#include "leashwin.h" +#include "leashdll.h" + +#pragma comment(lib, "ole32.lib") // CoCreateInstance + +// +// DynEnumString: +// IEnumString implementation that can be dynamically updated after creation. +// +class DynEnumString : public IEnumString +{ +public: + // IUnknown + STDMETHODIMP_(ULONG) AddRef() + { + return ++m_refcount; + } + + STDMETHODIMP_(ULONG) Release() + { + ULONG refcount = --m_refcount; + if (refcount == 0) + delete this; + return refcount; + } + + STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject) + { + IUnknown *punk = NULL; + if (riid == IID_IUnknown) + punk = static_cast<IUnknown*>(this); + else if (riid == IID_IEnumString) + punk = static_cast<IEnumString*>(this); + *ppvObject = punk; + if (punk == NULL) + return E_NOINTERFACE; + punk->AddRef(); + return S_OK; + } + + // IEnumString +public: + STDMETHODIMP Clone(IEnumString **ppclone) + { + LPTSTR *data = m_aStrings.data(); + ULONG count = m_aStrings.size(); + *ppclone = new DynEnumString(count, data); + return S_OK; + } + + STDMETHODIMP Next(ULONG count, LPOLESTR *elements, ULONG *pFetched) + { + ULONG fetched = 0; + while (fetched < count) { + if (m_iter == m_aStrings.end()) + break; + LPTSTR src = *m_iter++; + // @TODO: add _UNICODE version + DWORD nLengthW = ::MultiByteToWideChar(CP_ACP, + 0, &src[0], -1, NULL, 0); + LPOLESTR copy = + (LPOLESTR )::CoTaskMemAlloc(sizeof(OLECHAR) * nLengthW); + if (copy != NULL) { + if (::MultiByteToWideChar(CP_ACP, + 0, &src[0], -1, copy, nLengthW)) { + elements[fetched++] = copy; + } else { + // failure... + // TODO: debug spew + ::CoTaskMemFree(copy); + copy = NULL; + } + } + } + *pFetched = fetched; + + return fetched == count ? S_OK : S_FALSE; + } + + STDMETHODIMP Reset() + { + m_iter = m_aStrings.begin(); + return S_OK; + } + + STDMETHODIMP Skip(ULONG count) + { + for (ULONG i=0; i<count; i++) { + if (m_iter == m_aStrings.end()) { + m_iter = m_aStrings.begin(); + break; + } + m_iter++; + } + return S_OK; + } + + // Custom interface + DynEnumString(ULONG count, LPTSTR *strings) + { + m_aStrings.reserve(count + 1); + for (ULONG i = 0; i < count; i++) { + AddString(strings[i]); + } + m_iter = m_aStrings.begin(); + m_refcount = 1; + } + + virtual ~DynEnumString() + { + RemoveAll(); + } + + void RemoveAll() + { + for (m_iter = m_aStrings.begin(); + m_iter != m_aStrings.end(); + m_iter++) + delete[] (*m_iter); + m_aStrings.erase(m_aStrings.begin(), m_aStrings.end()); + } + + void AddString(LPTSTR str) + { + LPTSTR copy = NULL; + if (str) { + copy = _tcsdup(str); + if (copy) + m_aStrings.push_back(copy); + } + } + + + void RemoveString(LPTSTR str) + { + std::vector<LPTSTR>::const_iterator i; + for (i = m_aStrings.begin(); i != m_aStrings.end(); i++) { + if (_tcscmp(*i, str) == 0) { + delete[] (*i); + m_aStrings.erase(i); + break; + } + } + } + +private: + ULONG m_refcount; + std::vector<LPTSTR>::iterator m_iter; + std::vector<LPTSTR> m_aStrings; +}; + +// Registry key to store history of successfully authenticated principals +#define LEASH_REGISTRY_PRINCIPALS_KEY_NAME "Software\\MIT\\Leash\\Principals" + +// Free principal list obtained by getPrincipalList() +static void freePrincipalList(LPTSTR *princs, int count) +{ + int i; + if (count) { + for (i = 0; i < count; i++) + if (princs[i]) + free(princs[i]); + delete[] princs; + } +} + +// Retrieve history of successfully authenticated principals from registry +static void getPrincipalList(LPTSTR **outPrincs, int *outPrincCount) +{ + DWORD count = 0; + DWORD valCount = 0; + DWORD maxLen = 0; + LPTSTR tempValName = NULL; + LPTSTR *princs = NULL; + *outPrincs = NULL; + HKEY hKey = NULL; + unsigned long rc = RegCreateKeyEx(HKEY_CURRENT_USER, + LEASH_REGISTRY_PRINCIPALS_KEY_NAME, 0, 0, + 0, KEY_READ, 0, &hKey, 0); + if (rc == S_OK) { + // get string count + rc = RegQueryInfoKey( + hKey, + NULL, // __out_opt LPTSTR lpClass, + NULL, // __inout_opt LPDWORD lpcClass, + NULL, // __reserved LPDWORD lpReserved, + NULL, // __out_opt LPDWORD lpcSubKeys, + NULL, // __out_opt LPDWORD lpcMaxSubKeyLen, + NULL, // __out_opt LPDWORD lpcMaxClassLen, + &valCount, //__out_opt LPDWORD lpcValues, + &maxLen, // __out_opt LPDWORD lpcMaxValueNameLen, + NULL, // __out_opt LPDWORD lpcMaxValueLen, + NULL, // __out_opt LPDWORD lpcbSecurityDescriptor, + NULL // __out_opt PFILETIME lpftLastWriteTime + ); + } + if (valCount == 0) + goto cleanup; + + princs = new LPTSTR[valCount]; + if (princs == NULL) + goto cleanup; + + tempValName = new TCHAR[maxLen+1]; + if (tempValName == NULL) + goto cleanup; + + // enumerate values... + for (DWORD iReg = 0; iReg < valCount; iReg++) { + LPTSTR princ = NULL; + DWORD size = maxLen+1; + rc = RegEnumValue(hKey, iReg, tempValName, &size, + NULL, NULL, NULL, NULL); + if (rc == ERROR_SUCCESS) + princ = _tcsdup(tempValName); + if (princ != NULL) + princs[count++] = princ; + } + + *outPrincCount = count; + count = 0; + *outPrincs = princs; + princs = NULL; + +cleanup: + if (tempValName) + delete[] tempValName; + if (princs) + freePrincipalList(princs, count); + if (hKey) + RegCloseKey(hKey); + return; +} + + +// HookWindow +// Utility class to process messages relating to the specified hwnd +class HookWindow +{ +public: + typedef std::pair<HWND, HookWindow*> map_elem; + typedef std::map<HWND, HookWindow*> map; + + HookWindow(HWND in_hwnd) : m_hwnd(in_hwnd) + { + // add 'this' to static hash + m_ctrl_id = GetDlgCtrlID(in_hwnd); + m_parent = ::GetParent(m_hwnd); + sm_map.insert(map_elem(m_parent, this)); + // grab current window proc and replace with our wndproc + m_parent_wndproc = SetWindowLongPtr(m_parent, + GWLP_WNDPROC, + (ULONG_PTR)(&sWindowProc)); + } + + virtual ~HookWindow() + { + // unhook hwnd and restore old wndproc + SetWindowLongPtr(m_parent, GWLP_WNDPROC, m_parent_wndproc); + sm_map.erase(m_parent); + } + + // Process a message + // return 'false' to forward message to parent wndproc + virtual bool WindowProc(UINT msg, WPARAM wParam, LPARAM lParam, + LRESULT *lr) = 0; + +protected: + static LRESULT sWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, + LPARAM lParam); + + HWND m_hwnd; + HWND m_parent; + ULONG_PTR m_parent_wndproc; + int m_ctrl_id; + + static map sm_map; +}; + +HookWindow::map HookWindow::sm_map; + +LRESULT HookWindow::sWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, + LPARAM lParam) +{ + LRESULT result; + // hash hwnd to get object and call actual window proc, + // then parent window proc as necessary + HookWindow::map::const_iterator iter = sm_map.find(hwnd); + if (iter != sm_map.end()) { + if (!iter->second->WindowProc(uMsg, wParam, lParam, &result)) + result = CallWindowProc((WNDPROC )iter->second->m_parent_wndproc, + hwnd, uMsg, wParam, lParam); + } else { + result = ::DefWindowProc(hwnd, uMsg, wParam, lParam); + } + return result; +} + +// +class PrincipalEditControl : public HookWindow +{ +public: + PrincipalEditControl(HWND hwnd, bool bUpperCaseRealm) : HookWindow(hwnd) + ,m_ignore_change(0) + ,m_bUpperCaseRealm(bUpperCaseRealm) + ,m_defaultRealm(NULL) + ,m_ctx(0) + ,m_enumString(NULL) + ,m_acdd(NULL) + ,m_princStr(NULL) + { + pkrb5_init_context(&m_ctx); + GetDefaultRealm(); + InitAutocomplete(); + } + + ~PrincipalEditControl() + { + DestroyAutocomplete(); + if (m_princStr) + delete[] m_princStr; + if (m_ctx && m_defaultRealm) + pkrb5_free_default_realm(m_ctx, m_defaultRealm); + if (m_ctx) + pkrb5_free_context(m_ctx); + } + + void ClearHistory() + { + if (m_enumString != NULL) + m_enumString->RemoveAll(); + if (m_acdd != NULL) + m_acdd->ResetEnumerator(); + if (m_princStr != NULL) { + delete[] m_princStr; + m_princStr = NULL; + } + } + +protected: + // Convert str to upper case + // This should be more-or-less _UNICODE-agnostic + static bool StrToUpper(LPTSTR str) + { + bool bChanged = false; + int c; + if (str != NULL) { + while ((c = *str) != NULL) { + if (__isascii(c) && islower(c)) { + bChanged = true; + *str = _toupper(c); + } + str++; + } + } + return bChanged; + } + + void GetDefaultRealm() + { + // @TODO: _UNICODE support here + if ((m_defaultRealm == NULL) && m_ctx) { + pkrb5_get_default_realm(m_ctx, &m_defaultRealm); + } + } + + // Append default realm to user and add to the autocomplete enum string + void SuggestDefaultRealm(LPTSTR user) + { + if (m_defaultRealm == NULL) + return; + + int princ_len = _tcslen(user) + _tcslen(m_defaultRealm) + 1; + LPTSTR princStr = new TCHAR[princ_len]; + if (princStr) { + _sntprintf_s(princStr, princ_len, _TRUNCATE, "%s%s", user, + m_defaultRealm); + if (m_princStr != NULL && (_tcscmp(princStr, m_princStr) == 0)) { + // this string is already added, ok to just bail + delete[] princStr; + } else { + if (m_princStr != NULL) { + // get rid of the old suggestion + m_enumString->RemoveString(m_princStr); + delete[] m_princStr; + } + // add the new one + m_enumString->AddString(princStr); + if (m_acdd != NULL) + m_acdd->ResetEnumerator(); + m_princStr = princStr; + } + } + } + + bool AdjustRealmCase(LPTSTR princStr, LPTSTR realmStr) + { + bool bChanged = StrToUpper(realmStr); + if (bChanged) { + DWORD selStart, selEnd; + ::SendMessage(m_hwnd, EM_GETSEL, (WPARAM)&selStart, + (LPARAM)&selEnd); + ::SetWindowText(m_hwnd, princStr); + ::SendMessage(m_hwnd, EM_SETSEL, (WPARAM)selStart, (LPARAM)selEnd); + } + return bChanged; + } + + bool ProcessText() + { + bool bChanged = false; + int text_len = GetWindowTextLength(m_hwnd); + if (text_len > 0) { + LPTSTR str = new TCHAR [++text_len]; + if (str != NULL) { + GetWindowText(m_hwnd, str, text_len); + LPTSTR realmStr = strchr(str, '@'); + if (realmStr != NULL) { + ++realmStr; + if (*realmStr == 0) { + SuggestDefaultRealm(str); + } + else if (m_bUpperCaseRealm) { + AdjustRealmCase(str, realmStr); + bChanged = true; + } + } + delete[] str; + } + } + return bChanged; + } + + virtual bool WindowProc(UINT msg, WPARAM wp, LPARAM lp, LRESULT *lr) + { + bool bChanged = false; + switch (msg) { + case WM_COMMAND: + if ((LOWORD(wp)==m_ctrl_id) && + (HIWORD(wp)==EN_CHANGE)) { + if ((!m_ignore_change++) && ProcessText()) { + bChanged = true; + *lr = 0; + } + m_ignore_change--; + } + default: + break; + } + return bChanged; + } + + void InitAutocomplete() + { + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + // read strings from registry + LPTSTR *princs = NULL; + int count = 0; + getPrincipalList(&princs, &count); + + // Create our custom IEnumString implementation + HRESULT hRes; + DynEnumString *pEnumString = new DynEnumString(count, princs); + if (princs) + freePrincipalList(princs, count); + + m_enumString = pEnumString; + + // Create and initialize IAutoComplete object using IEnumString + IAutoComplete *pac = NULL; + hRes = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&pac)); + if (pac != NULL) { + pac->Init(m_hwnd, pEnumString, NULL, NULL); + + IAutoCompleteDropDown* pacdd = NULL; + hRes = pac->QueryInterface(IID_IAutoCompleteDropDown, (LPVOID*)&pacdd); + pac->Release(); + + // @TODO: auto-suggest; other advanced options? +#if 0 + IAutoComplete2 *pac2; + + if (SUCCEEDED(pac->QueryInterface(IID_IAutoComplete2, + (LPVOID*)&pac2))) { + pac2->SetOptions(ACO_AUTOSUGGEST); + pac2->Release(); + } +#endif + m_acdd = pacdd; + } + } + + void DestroyAutocomplete() + { + if (m_acdd != NULL) + m_acdd->Release(); + if (m_enumString != NULL) + m_enumString->Release(); + } + + int m_ignore_change; + bool m_bUpperCaseRealm; + LPTSTR m_defaultRealm; + LPTSTR m_princStr; + krb5_context m_ctx; + DynEnumString *m_enumString; + IAutoCompleteDropDown *m_acdd; +}; + + + +extern "C" void Leash_pec_add_principal(char *principal) +{ + // write princ to registry + HKEY hKey; + unsigned long rc = RegCreateKeyEx(HKEY_CURRENT_USER, + LEASH_REGISTRY_PRINCIPALS_KEY_NAME, + 0, 0, 0, KEY_WRITE, 0, &hKey, 0); + if (rc) { + // TODO: log failure + return; + } + rc = RegSetValueEx(hKey, principal, 0, REG_NONE, NULL, 0); + if (rc) { + // TODO: log failure + } + if (hKey) + RegCloseKey(hKey); +} + +extern "C" void Leash_pec_clear_history(void *pec) +{ + // clear princs from registry + RegDeleteKey(HKEY_CURRENT_USER, + LEASH_REGISTRY_PRINCIPALS_KEY_NAME); + // ...and from the specified widget + static_cast<PrincipalEditControl *>(pec)->ClearHistory(); +} + + +extern "C" void *Leash_pec_create(HWND hEdit) +{ + return new PrincipalEditControl( + hEdit, + Leash_get_default_uppercaserealm() ? true : false); +} + +extern "C" void Leash_pec_destroy(void *pec) +{ + if (pec != NULL) + delete ((PrincipalEditControl *)pec); +} diff --git a/src/windows/leashdll/registry.c b/src/windows/leashdll/registry.c new file mode 100644 index 000000000000..7113d056e05d --- /dev/null +++ b/src/windows/leashdll/registry.c @@ -0,0 +1,105 @@ +#include <windows.h> +#include "leash-int.h" + +static +LONG +write_registry_setting_ex( + HKEY hRoot, + char* setting, + DWORD type, + void* buffer, + size_t size + ) +{ + HKEY hKey = 0; + LONG rc = 0; + + if (rc = RegCreateKeyEx(hRoot, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, 0, 0, + KEY_ALL_ACCESS, 0, &hKey, 0)) + goto cleanup; + + rc = RegSetValueEx(hKey, setting, 0, type, (LPBYTE)buffer, size); + cleanup: + if (hKey) + RegCloseKey(hKey); + return rc; +} + +LONG +write_registry_setting( + char* setting, + DWORD type, + void* buffer, + size_t size + ) +{ + return write_registry_setting_ex(HKEY_CURRENT_USER, + setting, + type, + buffer, + size); +} + +static +LONG +read_registry_setting_ex( + HKEY hRoot, + char* setting, + void* buffer, + size_t size + ) +{ + HKEY hKey = 0; + LONG rc = 0; + DWORD dwType; + DWORD dwCount; + + if (rc = RegOpenKeyEx(hRoot, + LEASH_SETTINGS_REGISTRY_KEY_NAME, + 0, KEY_QUERY_VALUE, &hKey)) + goto cleanup; + + memset(buffer, 0, size); + dwCount = size; + rc = RegQueryValueEx(hKey, setting, NULL, &dwType, (LPBYTE)buffer, + &dwCount); + cleanup: + if (hKey) + RegCloseKey(hKey); + return rc; +} + +LONG +read_registry_setting_user( + char* setting, + void* buffer, + size_t size + ) +{ + return read_registry_setting_ex(HKEY_CURRENT_USER, setting, buffer, size); +} + +static +LONG +read_registry_setting_machine( + char* setting, + void* buffer, + size_t size + ) +{ + return read_registry_setting_ex(HKEY_LOCAL_MACHINE, setting, buffer, size); +} + +LONG +read_registry_setting( + char* setting, + void* buffer, + size_t size + ) +{ + LONG rc; + rc = read_registry_setting_user(setting, buffer, size); + if (!rc) return rc; + rc = read_registry_setting_machine(setting, buffer, size); + return rc; +} diff --git a/src/windows/leashdll/reminder.h b/src/windows/leashdll/reminder.h new file mode 100644 index 000000000000..05dd4bdddad9 --- /dev/null +++ b/src/windows/leashdll/reminder.h @@ -0,0 +1,12 @@ +#ifndef __REMINDER_H__ +#define __REMINDER_H__ + +#define Stringize( L ) #L +#define MakeString( M, L ) M(L) +#define $LINE MakeString( Stringize, __LINE__ ) +#define Reminder __FILE__ "(" $LINE ") : Reminder: " + +#endif + +//Put this in your .cpp file where ever you need it (NOTE: Don't end this statement with a ';' char) +//i.e. -->> #pragma message(Reminder "Your message reminder here!!!") diff --git a/src/windows/leashdll/res/islogo.bmp b/src/windows/leashdll/res/islogo.bmp Binary files differnew file mode 100644 index 000000000000..c4af48f2337e --- /dev/null +++ b/src/windows/leashdll/res/islogo.bmp diff --git a/src/windows/leashdll/res/leash.ico b/src/windows/leashdll/res/leash.ico Binary files differnew file mode 100644 index 000000000000..235c6f445dae --- /dev/null +++ b/src/windows/leashdll/res/leash.ico diff --git a/src/windows/leashdll/resource.h b/src/windows/leashdll/resource.h new file mode 100644 index 000000000000..637c93878b38 --- /dev/null +++ b/src/windows/leashdll/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by lsh_pwd.rc +// +#define IDOK2 5 +#define IDCANCEL2 6 +#define LEASHICON 100 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/windows/leashdll/timesync.c b/src/windows/leashdll/timesync.c new file mode 100644 index 000000000000..32ab5e628211 --- /dev/null +++ b/src/windows/leashdll/timesync.c @@ -0,0 +1,304 @@ +/* timesync stuff for leash - 7/28/94 - evanr */ + +#include <windows.h> +#include "leashdll.h" + +#include <time.h> +#include <sys\timeb.h> +#include <stdlib.h> +#include <string.h> + +#ifndef NO_KRB4 +#include <winkrbid.h> +#endif + +#ifdef WSHELPER +#include <wshelper.h> +#else +#include <winsock2.h> +#endif + +#include <stdio.h> +#include "leasherr.h" +#include "leashids.h" + +int ProcessTimeSync(char *, int, char *); + +#define TM_OFFSET 2208988800 + +/* timezone.h has a winsock.h conflict */ +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +/************************************/ +/* settimeofday(): */ +/************************************/ +int +settimeofday( + struct timeval *tv, + struct timezone *tz + ) +{ + SYSTEMTIME systime; + struct tm *newtime; + + newtime = gmtime((time_t *)&(tv->tv_sec)); + systime.wYear = 1900+newtime->tm_year; + systime.wMonth = 1+newtime->tm_mon; + systime.wDay = newtime->tm_mday; + systime.wHour = newtime->tm_hour; + systime.wMinute = newtime->tm_min; + systime.wSecond = newtime->tm_sec; + systime.wMilliseconds = 0; + return SetSystemTime(&systime); +} + +/************************************/ +/* gettimeofday(): */ +/************************************/ +int +gettimeofday( + struct timeval *tv, + struct timezone *tz + ) +{ + struct _timeb tb; + _tzset(); + _ftime(&tb); + if (tv) { + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000; + } + if (tz) { + tz->tz_minuteswest = tb.timezone; + tz->tz_dsttime = tb.dstflag; + } + return 0; +} + + +LONG +not_an_API_LeashGetTimeServerName( + char *timeServerName, + const char *valueName + ) +{ + HMODULE hmLeash; + char hostname[128]; + char value[80]; + DWORD dwType; + DWORD dwCount; + int check = 0; + HKEY hKey; + HKEY rKey1; + HKEY rKey2; + LONG lResult; + BOOL bEnv; + + memset(value, '\0', sizeof(value)); + memset(hostname, '\0', sizeof(hostname)); + + GetEnvironmentVariable("TIMEHOST", hostname, sizeof(hostname)); + bEnv = (GetLastError() == ERROR_ENVVAR_NOT_FOUND); + + if (!(bEnv && hostname[0])) + { + // Check registry for TIMEHOST + rKey1 = HKEY_CURRENT_USER; + rKey2 = HKEY_LOCAL_MACHINE; + + for (check = 0; check < 2; check++) + { + if (ERROR_SUCCESS == RegOpenKeyEx(check == 0 ? rKey1 : rKey2, + "Software\\MIT\\Leash32\\Settings", + 0, KEY_QUERY_VALUE, &hKey)) + { + memset(value, '\0', sizeof(value)); + lResult = RegQueryValueEx(hKey, (LPTSTR)valueName, NULL, + &dwType, NULL, &dwCount); + if (lResult == ERROR_SUCCESS) + { + lResult = RegQueryValueEx(hKey, (LPTSTR)valueName, + NULL, &dwType, + (LPTSTR)value, &dwCount); + if (lResult == ERROR_SUCCESS && *value) + { + // found + strcpy(hostname, value); + break; + } + } + } + } + + if (!*hostname) + { + // Check resource string for TIMEHOST + if ((hmLeash = GetModuleHandle(LEASH_DLL)) != NULL) + { + if (!LoadString(hmLeash, LSH_TIME_HOST, hostname, + sizeof(hostname))) + memset(hostname, '\0', sizeof(hostname)); + } + } + if (!*hostname) + { + // OK, _Default_ it will be! :) + strcpy(hostname, "time"); + } + } + strcpy(timeServerName, hostname); + return 0; +} + +/************************************/ +/* Leash_timesync(): */ +/************************************/ +LONG Leash_timesync(int MessageP) +{ + char tmpstr[2048]; + char hostname[128]; + int Port; + int rc; + struct servent *sp; + WORD wVersionRequested; + WSADATA wsaData; + char name[80]; + + if ((pkrb5_init_context == NULL) +#ifndef NO_KRB4 + && (ptkt_string == NULL) +#endif + ) + return(0); + + wVersionRequested = 0x0101; + memset(name, '\0', sizeof(name)); + memset(hostname, '\0', sizeof(hostname)); + memset(tmpstr, '\0', sizeof(tmpstr)); + + if ((rc = WSAStartup(wVersionRequested, &wsaData))) + { + wsprintf(tmpstr, "Couldn't initialize WinSock to synchronize time\n\rError Number: %d", rc); + WSACleanup(); + return(LSH_BADWINSOCK); + } + + sp = getservbyname("time", "udp"); + if (sp == 0) + Port = htons(IPPORT_TIMESERVER); + else + Port = sp->s_port; + + not_an_API_LeashGetTimeServerName(hostname, TIMEHOST); + + rc = ProcessTimeSync(hostname, Port, tmpstr); + +#ifdef USE_MESSAGE_BOX + if(MessageP != 0) + { + if (rc && !*tmpstr) + { + strcpy(tmpstr, "Unable to syncronize time!\n\n"); + if (*hostname) + { + char tmpstr1[2048]; + + memset(tmpstr1, '\0', sizeof(tmpstr1)); + sprintf(tmpstr1, "Unreachable server: %s\n", hostname); + strcat(tmpstr, tmpstr1); + } + } + + MessageBox(NULL, tmpstr, "Time Server", + MB_ICONERROR | MB_OK); + } +#endif /* USE_MESSAGE_BOX */ + WSACleanup(); + return(rc); +} + + +/************************************/ +/* ProcessTimeSync(): */ +/************************************/ +int ProcessTimeSync(char *hostname, int Port, char *tmpstr) +{ + char buffer[512]; + int cc; + register long *nettime; + register int s; + long hosttime; + struct hostent *host; + struct timeval tv; + struct timezone tz; + u_long argp; + struct sockaddr_in sin; + int i; + + if ((host = gethostbyname(hostname)) == NULL) + return(LSH_BADTIMESERV); + + sin.sin_port = (short)Port; + sin.sin_family = host->h_addrtype; + memcpy((struct sockaddr *)&sin.sin_addr, host->h_addr, host->h_length); + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + return(LSH_NOSOCKET); + } + + argp = 1; + if (ioctlsocket(s, FIONBIO, &argp) != 0) + { + closesocket(s); + return(LSH_NOCONNECT); + } + + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) + { + closesocket(s); + return(LSH_NOCONNECT); + } + send(s, buffer, 40, 0); + if (gettimeofday (&tv, &tz) < 0) + { + closesocket(s); + return(LSH_GETTIMEOFDAY); + } + + for (i = 0; i < 4; i++) + { + if ((cc = recv(s, buffer, 512, 0)) > 0) + break; + Sleep(500); + } + if (i == 4) + { + closesocket(s); + return(LSH_RECVTIME); + } + + if (cc != 4) + { + closesocket(s); + return(LSH_RECVBYTES); + } + + nettime = (long *)buffer; + hosttime = (long) ntohl (*nettime) - TM_OFFSET; + (&tv)->tv_sec = hosttime; + if (settimeofday(&tv, &tz) < 0) + { + closesocket(s); + return(LSH_SETTIMEOFDAY); + } + + sprintf(tmpstr, "The time has been syncronized with the server: %s\n\n", hostname); + strcat(tmpstr, "To be able to use the Kerberos server, it was necessary to \nset the system time to: ") ; + strcat(tmpstr, ctime((time_t *)&hosttime)); + strcat(tmpstr, "\n"); + closesocket(s); + return(0); +} diff --git a/src/windows/leashdll/ver.rc b/src/windows/leashdll/ver.rc new file mode 100644 index 000000000000..88bb7d9431a2 --- /dev/null +++ b/src/windows/leashdll/ver.rc @@ -0,0 +1,4 @@ +#define VER_FILEDESCRIPTION_STR "Leash Helper DLL" + +#include <kerberos.ver> +#include <ver.inc> diff --git a/src/windows/leashdll/winerr.c b/src/windows/leashdll/winerr.c new file mode 100644 index 000000000000..e624fc085fad --- /dev/null +++ b/src/windows/leashdll/winerr.c @@ -0,0 +1,125 @@ +/* WINERR.C + + Jason Hunter + 8/2/94 + DCNS/IS MIT + + + Contains the error functions for leash and kerberos. Prints out keen windows + error messages in english. + +*/ + +#include <stdio.h> +#include "conf.h" + +// Private Include files +#include "leashdll.h" +#include <leashwin.h> + +// Global Variables. +static long lsh_errno; +static char *err_context; /* error context */ +extern int (*Lcom_err)(LPSTR,long,LPSTR,...); +extern LPSTR (*Lerror_message)(long); +extern LPSTR (*Lerror_table_name)(long); + +#ifdef WIN16 +#define UNDERSCORE "_" +#else +#define UNDERSCORE +#endif + +HWND GetRootParent (HWND Child) +{ + HWND Last; + while (Child) + { + Last = Child; + Child = GetParent (Child); + } + return Last; +} + + +LPSTR err_describe(LPSTR buf, long code) +{ + LPSTR cp, com_err_msg; + int offset; + long table_num; + char *etype; + + offset = (int) (code & 255); + table_num = code - offset; + com_err_msg = Lerror_message(code); + + lstrcpy(buf, com_err_msg); + return buf; + + +////Is this needed at all after the return above? + cp = buf; + if(com_err_msg != buf) + lstrcpy(buf, com_err_msg); + cp = buf + lstrlen(buf); + *cp++ = '\n'; + etype = Lerror_table_name(table_num); + wsprintf((LPSTR) cp, (LPSTR) "(%s error %d" +#ifdef DEBUG_COM_ERR + " (absolute error %ld)" +#endif + ")", etype, offset + //")\nPress F1 for help on this error.", etype, offset +#ifdef DEBUG_COM_ERR + , code +#endif + ); + + return (LPSTR)buf; +} + +int _export lsh_com_err_proc (LPSTR whoami, long code, + LPSTR fmt, va_list args) +{ +#ifdef USE_MESSAGE_BOX + int retval; + HWND hOldFocus; + char buf[1024], *cp; /* changed to 512 by jms 8/23/93 */ + WORD mbformat = MB_OK | MB_ICONEXCLAMATION; + + cp = buf; + memset(buf, '\0', sizeof(buf)); + cp[0] = '\0'; + + if (code) + { + err_describe(buf, code); + while (*cp) + cp++; + } + + if (fmt) + { + if (fmt[0] == '%' && fmt[1] == 'b') + { + fmt += 2; + mbformat = va_arg(args, WORD); + /* if the first arg is a %b, we use it for the message + box MB_??? flags. */ + } + if (code) + { + *cp++ = '\n'; + *cp++ = '\n'; + } + wvsprintf((LPSTR)cp, fmt, args); + } + hOldFocus = GetFocus(); + retval = MessageBox(/*GetRootParent(hOldFocus)*/NULL, buf, whoami, + mbformat | MB_ICONHAND | MB_TASKMODAL); + SetFocus(hOldFocus); + return retval; +#else + return IDOK; +#endif /* USE_MESSAGE_BOX */ +} diff --git a/src/windows/leashdll/winutil.c b/src/windows/leashdll/winutil.c new file mode 100644 index 000000000000..65609bcdf052 --- /dev/null +++ b/src/windows/leashdll/winutil.c @@ -0,0 +1,138 @@ +#include <windows.h> +#include "leash-int.h" + +//#include <string.h> + +static ATOM sAtom = 0; +static HINSTANCE shInstance = 0; + +/* Callback for the MITPasswordControl +This is a replacement for the normal edit control. It does not show the +annoying password char in the edit box so that the number of chars in the +password are not known. +*/ + +#define PASSWORDCHAR '#' +#define DLGHT(ht) (HIWORD(GetDialogBaseUnits())*(ht)/8) +#define DLGWD(wd) (LOWORD(GetDialogBaseUnits())*(wd)/4) + +static +LRESULT +CALLBACK +MITPasswordEditProc( + HWND hWnd, + UINT message, + WPARAM wParam, + LPARAM lParam + ) +{ + static SIZE pwdcharsz; + BOOL pass_the_buck = FALSE; + + if (message > WM_USER && message < 0x7FFF) + pass_the_buck = TRUE; + + switch(message) + { + case WM_GETTEXT: + case WM_GETTEXTLENGTH: + case WM_SETTEXT: + pass_the_buck = TRUE; + break; + case WM_PAINT: + { + HDC hdc; + PAINTSTRUCT ps; + RECT r; + + hdc = BeginPaint(hWnd, &ps); + GetClientRect(hWnd, &r); + Rectangle(hdc, 0, 0, r.right, r.bottom); + EndPaint(hWnd, &ps); + } + break; + case WM_SIZE: + { + MoveWindow(GetDlgItem(hWnd, 1), DLGWD(2), DLGHT(2), + pwdcharsz.cx / 2, pwdcharsz.cy, TRUE); + } + break; + case WM_LBUTTONDOWN: + case WM_SETFOCUS: + { + SetFocus(GetDlgItem(hWnd, 1)); + } + break; + case WM_CREATE: + { + HWND heditchild; + char pwdchar = PASSWORDCHAR; + HDC hdc; + /* Create a child window of this control for default processing. */ + hdc = GetDC(hWnd); + GetTextExtentPoint32(hdc, &pwdchar, 1, &pwdcharsz); + ReleaseDC(hWnd, hdc); + + heditchild = + CreateWindow("edit", "", WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | + ES_LEFT | ES_PASSWORD | WS_TABSTOP, + 0, 0, 0, 0, + hWnd, + (HMENU)1, + ((LPCREATESTRUCT)lParam)->hInstance, + NULL); + SendMessage(heditchild, EM_SETPASSWORDCHAR, PASSWORDCHAR, 0L); + } + break; + } + + if (pass_the_buck) + return SendMessage(GetDlgItem(hWnd, 1), message, wParam, lParam); + return DefWindowProc(hWnd, message, wParam, lParam); +} + +BOOL +Register_MITPasswordEditControl( + HINSTANCE hInst + ) +{ + if (!sAtom) { + WNDCLASS wndclass; + + memset(&wndclass, 0, sizeof(WNDCLASS)); + + shInstance = hInst; + + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = (WNDPROC)MITPasswordEditProc; + wndclass.cbClsExtra = sizeof(HWND); + wndclass.cbWndExtra = 0; + wndclass.hInstance = shInstance; + wndclass.hbrBackground = (void *)(COLOR_WINDOW + 1); + wndclass.lpszClassName = MIT_PWD_DLL_CLASS; + wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_IBEAM); + + sAtom = RegisterClass(&wndclass); + } + return sAtom ? TRUE : FALSE; +} + +BOOL +Unregister_MITPasswordEditControl( + HINSTANCE hInst + ) +{ + BOOL result = TRUE; + + if ((hInst != shInstance) || !sAtom) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + result = UnregisterClass(MIT_PWD_DLL_CLASS, hInst); + if (result) { + sAtom = 0; + shInstance = 0; + } + return result; +} |
