summaryrefslogtreecommitdiff
path: root/src/windows/leashdll
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/leashdll')
-rw-r--r--src/windows/leashdll/AFSroutines.c833
-rw-r--r--src/windows/leashdll/Makefile.in84
-rw-r--r--src/windows/leashdll/include/krb4/conf-pc.h108
-rw-r--r--src/windows/leashdll/include/krb4/conf.h74
-rw-r--r--src/windows/leashdll/include/krb4/osconf.h59
-rw-r--r--src/windows/leashdll/krb5routines.c1066
-rw-r--r--src/windows/leashdll/leash-int.h359
-rw-r--r--src/windows/leashdll/leashdll.c373
-rw-r--r--src/windows/leashdll/leashdll.h272
-rw-r--r--src/windows/leashdll/leasherr.c105
-rw-r--r--src/windows/leashdll/leasherr.et22
-rw-r--r--src/windows/leashdll/leashids.h117
-rw-r--r--src/windows/leashdll/leashw32.def107
-rw-r--r--src/windows/leashdll/lsh_pwd.c1991
-rw-r--r--src/windows/leashdll/lsh_pwd.rc251
-rw-r--r--src/windows/leashdll/lshcallb.c14
-rw-r--r--src/windows/leashdll/lshfunc.c3145
-rw-r--r--src/windows/leashdll/lshutil.cpp608
-rw-r--r--src/windows/leashdll/registry.c105
-rw-r--r--src/windows/leashdll/reminder.h12
-rw-r--r--src/windows/leashdll/res/islogo.bmpbin0 -> 20118 bytes
-rw-r--r--src/windows/leashdll/res/leash.icobin0 -> 9662 bytes
-rw-r--r--src/windows/leashdll/resource.h19
-rw-r--r--src/windows/leashdll/timesync.c304
-rw-r--r--src/windows/leashdll/ver.rc4
-rw-r--r--src/windows/leashdll/winerr.c125
-rw-r--r--src/windows/leashdll/winutil.c138
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
new file mode 100644
index 000000000000..c4af48f2337e
--- /dev/null
+++ b/src/windows/leashdll/res/islogo.bmp
Binary files differ
diff --git a/src/windows/leashdll/res/leash.ico b/src/windows/leashdll/res/leash.ico
new file mode 100644
index 000000000000..235c6f445dae
--- /dev/null
+++ b/src/windows/leashdll/res/leash.ico
Binary files differ
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;
+}