0618fafec4d6616123418728aad44ed6664a5114
[krb5.git] / src / windows / leashdll / lshfunc.c
1 #include <windows.h>
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <winsock2.h>
5 #include "leashdll.h"
6 #ifndef NO_KRB4
7 #include <KerberosIV/krb.h>
8 #include <prot.h>
9 #else
10 /* General definitions */
11 #define         KSUCCESS        0
12 #define         KFAILURE        255
13 #endif
14 #include <time.h>
15
16 #include <leashwin.h>
17 #include "leasherr.h"
18 #include "leash-int.h"
19 #include "leashids.h"
20
21 #include <mitwhich.h>
22
23 #include "reminder.h"
24
25 static char FAR *err_context;
26
27 char KRB_HelpFile[_MAX_PATH] =  HELPFILE;
28
29 #define LEN     64                /* Maximum Hostname Length */
30
31 #define LIFE    DEFAULT_TKT_LIFE  /* lifetime of ticket in 5-minute units */
32
33 static
34 char*
35 clean_string(
36     char* s
37     )
38 {
39     char* p = s;
40     char* b = s;
41
42     if (!s) return s;
43
44     for (p = s; *p; p++) {
45         switch (*p) {
46         case '\007':
47             /* Add more cases here */
48             break;
49         default:
50             *b = *p;
51             b++;
52         }
53     }
54     *b = *p;
55     return s;
56 }
57
58 static
59 int
60 leash_error_message(
61     const char *error,
62     int rcL,
63     int rc5,
64     int rcA,
65     char* result_string,
66     int  displayMB
67     )
68 {
69     char message[2048];
70     char *p = message;
71     int size = sizeof(message);
72     int n;
73
74     // XXX: ignore AFS for now.
75
76     if (!rc5 && !rcL)
77         return 0;
78
79     n = _snprintf(p, size, "%s\n\n", error);
80     p += n;
81     size -= n;
82
83     if (rc5 && !result_string)
84     {
85         n = _snprintf(p, size,
86                       "Kerberos 5: %s (error %ld)\n",
87                       perror_message(rc5),
88                       rc5 & 255 // XXX: & 255??!!!
89             );
90         p += n;
91         size -= n;
92     }
93     if (rcL)
94     {
95         char buffer[1024];
96         n = _snprintf(p, size,
97                       "\n%s\n",
98                       err_describe(buffer, rcL)
99             );
100         p += n;
101         size -= n;
102     }
103     if (result_string)
104     {
105         n = _snprintf(p, size,
106                       "%s\n",
107                       result_string);
108         p += n;
109         size -= n;
110     }
111 #ifdef USE_MESSAGE_BOX
112     if ( displayMB )
113         MessageBox(NULL, message, "Leash", MB_OK | MB_ICONERROR | MB_TASKMODAL |
114                     MB_SETFOREGROUND);
115 #endif /* USE_MESSAGE_BOX */
116     if (rc5) return rc5;
117     if (rcL) return rcL;
118     return 0;
119 }
120
121
122 static
123 char *
124 make_postfix(
125     const char * base,
126     const char * postfix,
127     char ** rcopy
128     )
129 {
130     int base_size;
131     int ret_size;
132     char * copy = 0;
133     char * ret = 0;
134
135     base_size = strlen(base) + 1;
136     ret_size = base_size + strlen(postfix) + 1;
137     copy = malloc(base_size);
138     ret = malloc(ret_size);
139
140     if (!copy || !ret)
141         goto cleanup;
142
143     strncpy(copy, base, base_size);
144     copy[base_size - 1] = 0;
145
146     strncpy(ret, base, base_size);
147     strncpy(ret + (base_size - 1), postfix, ret_size - (base_size - 1));
148     ret[ret_size - 1] = 0;
149
150  cleanup:
151     if (!copy || !ret) {
152         if (copy)
153             free(copy);
154         if (ret)
155             free(ret);
156         copy = ret = 0;
157     }
158     // INVARIANT: (ret ==> copy) && (copy ==> ret)
159     *rcopy = copy;
160     return ret;
161 }
162
163 static
164 long
165 make_temp_cache_v5(
166     const char * postfix,
167     krb5_context * pctx
168     )
169 {
170     static krb5_context ctx = 0;
171     static char * old_cache = 0;
172
173     // INVARIANT: old_cache ==> ctx && ctx ==> old_cache
174
175     if (pctx)
176         *pctx = 0;
177
178     if (!pkrb5_init_context || !pkrb5_free_context || !pkrb5_cc_resolve ||
179         !pkrb5_cc_default_name || !pkrb5_cc_set_default_name)
180         return 0;
181
182     if (old_cache) {
183         krb5_ccache cc = 0;
184         if (!pkrb5_cc_resolve(ctx, pkrb5_cc_default_name(ctx), &cc))
185             pkrb5_cc_destroy(ctx, cc);
186         pkrb5_cc_set_default_name(ctx, old_cache);
187         free(old_cache);
188         old_cache = 0;
189     }
190     if (ctx) {
191         pkrb5_free_context(ctx);
192         ctx = 0;
193     }
194
195     if (postfix)
196     {
197         char * tmp_cache = 0;
198         krb5_error_code rc = 0;
199
200         rc = pkrb5_init_context(&ctx);
201         if (rc) goto cleanup;
202
203         tmp_cache = make_postfix(pkrb5_cc_default_name(ctx), postfix,
204                                  &old_cache);
205
206         if (!tmp_cache) {
207             rc = ENOMEM;
208             goto cleanup;
209         }
210
211         rc = pkrb5_cc_set_default_name(ctx, tmp_cache);
212
213     cleanup:
214         if (rc && ctx) {
215             pkrb5_free_context(ctx);
216             ctx = 0;
217         }
218         if (tmp_cache)
219             free(tmp_cache);
220         if (pctx)
221             *pctx = ctx;
222         return rc;
223     }
224     return 0;
225 }
226
227 long
228 Leash_checkpwd(
229     char *principal,
230     char *password
231     )
232 {
233     return Leash_int_checkpwd(principal, password, 0);
234 }
235
236 long
237 Leash_int_checkpwd(
238     char * principal,
239     char * password,
240     int    displayErrors
241     )
242 {
243     long rc = 0;
244         krb5_context ctx = 0;   // statically allocated in make_temp_cache_v5
245     // XXX - we ignore errors in make_temp_cache_v?  This is BAD!!!
246     make_temp_cache_v5("_checkpwd", &ctx);
247     rc = Leash_int_kinit_ex( ctx, 0,
248                                                          principal, password, 0, 0, 0, 0,
249                                                          Leash_get_default_noaddresses(),
250                                                          Leash_get_default_publicip(),
251                              displayErrors
252                                                          );
253     make_temp_cache_v5(0, &ctx);
254     return rc;
255 }
256
257 static
258 long
259 Leash_changepwd_v5(
260     char * principal,
261     char * password,
262     char * newpassword,
263     char** error_str
264     )
265 {
266     krb5_error_code rc = 0;
267     int result_code;
268     krb5_data result_code_string, result_string;
269     krb5_context context = 0;
270     krb5_principal princ = 0;
271     krb5_get_init_creds_opt opts;
272     krb5_creds creds;
273     DWORD addressless = 0;
274
275     result_string.data = 0;
276     result_code_string.data = 0;
277
278     if ( !pkrb5_init_context )
279         goto cleanup;
280
281    if (rc = pkrb5_init_context(&context)) {
282 #if 0
283        com_err(argv[0], ret, "initializing kerberos library");
284 #endif
285        goto cleanup;
286    }
287
288    if (rc = pkrb5_parse_name(context, principal, &princ)) {
289 #if 0
290        com_err(argv[0], ret, "parsing client name");
291 #endif
292        goto cleanup;
293    }
294
295    pkrb5_get_init_creds_opt_init(&opts);
296    pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
297    pkrb5_get_init_creds_opt_set_renew_life(&opts, 0);
298    pkrb5_get_init_creds_opt_set_forwardable(&opts, 0);
299    pkrb5_get_init_creds_opt_set_proxiable(&opts, 0);
300
301    addressless = Leash_get_default_noaddresses();
302    if (addressless)
303        pkrb5_get_init_creds_opt_set_address_list(&opts,NULL);
304
305
306    if (rc = pkrb5_get_init_creds_password(context, &creds, princ, password,
307                                           0, 0, 0, "kadmin/changepw", &opts)) {
308        if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
309 #if 0
310            com_err(argv[0], 0,
311                    "Password incorrect while getting initial ticket");
312 #endif
313        }
314        else {
315 #if 0
316            com_err(argv[0], ret, "getting initial ticket");
317 #endif
318        }
319        goto cleanup;
320    }
321
322    if (rc = pkrb5_change_password(context, &creds, newpassword,
323                                   &result_code, &result_code_string,
324                                   &result_string)) {
325 #if 0
326        com_err(argv[0], ret, "changing password");
327 #endif
328        goto cleanup;
329    }
330
331    if (result_code) {
332        int len = result_code_string.length +
333            (result_string.length ? (sizeof(": ") - 1) : 0) +
334            result_string.length;
335        if (len && error_str) {
336            *error_str = malloc(len + 1);
337            if (*error_str)
338                _snprintf(*error_str, len + 1,
339                          "%.*s%s%.*s",
340                          result_code_string.length, result_code_string.data,
341                          result_string.length?": ":"",
342                          result_string.length, result_string.data);
343        }
344       rc = result_code;
345       goto cleanup;
346    }
347
348  cleanup:
349    if (result_string.data)
350        pkrb5_free_data_contents(context, &result_string);
351
352    if (result_code_string.data)
353        pkrb5_free_data_contents(context, &result_code_string);
354
355    if (princ)
356        pkrb5_free_principal(context, princ);
357
358    if (context)
359        pkrb5_free_context(context);
360
361    return rc;
362 }
363
364 /*
365  * Leash_changepwd
366  *
367  * Try to change the password using krb5.
368  */
369 long
370 Leash_changepwd(
371     char * principal,
372     char * password,
373     char * newpassword,
374     char** result_string
375     )
376 {
377     return Leash_int_changepwd(principal, password, newpassword, result_string, 0);
378 }
379
380 long
381 Leash_int_changepwd(
382     char * principal,
383     char * password,
384     char * newpassword,
385     char** result_string,
386     int    displayErrors
387     )
388 {
389     char* v5_error_str = 0;
390     char* error_str = 0;
391     int rc5 = 0;
392     int rc = 0;
393     if (hKrb5)
394         rc = rc5 = Leash_changepwd_v5(principal, password, newpassword,
395                                       &v5_error_str);
396     if (!rc)
397         return 0;
398     if (v5_error_str) {
399         int len = 0;
400         char v5_prefix[] = "Kerberos 5: ";
401         char sep[] = "\n";
402
403         clean_string(v5_error_str);
404
405         if (v5_error_str)
406             len += sizeof(sep) + sizeof(v5_prefix) + strlen(v5_error_str) +
407                 sizeof(sep);
408         error_str = malloc(len + 1);
409         if (error_str) {
410             char* p = error_str;
411             int size = len + 1;
412             int n;
413             if (v5_error_str) {
414                 n = _snprintf(p, size, "%s%s%s%s",
415                               sep, v5_prefix, v5_error_str, sep);
416                 p += n;
417                 size -= n;
418             }
419             if (result_string)
420                 *result_string = error_str;
421         }
422     }
423     return leash_error_message("Error while changing password.",
424                                0, rc5, 0, error_str,
425                                displayErrors
426                                );
427 }
428
429 int (*Lcom_err)(LPSTR,long,LPSTR,...);
430 LPSTR (*Lerror_message)(long);
431 LPSTR (*Lerror_table_name)(long);
432
433
434 long
435 Leash_kinit(
436     char * principal,
437     char * password,
438     int lifetime
439     )
440 {
441     return Leash_int_kinit_ex( 0, 0,
442                                principal,
443                                password,
444                                lifetime,
445                                Leash_get_default_forwardable(),
446                                Leash_get_default_proxiable(),
447                                Leash_get_default_renew_till(),
448                                Leash_get_default_noaddresses(),
449                                Leash_get_default_publicip(),
450                                0
451                                );
452 }
453
454 long
455 Leash_kinit_ex(
456     char * principal,
457     char * password,
458     int lifetime,
459     int forwardable,
460     int proxiable,
461     int renew_life,
462     int addressless,
463     unsigned long publicip
464     )
465 {
466     return Leash_int_kinit_ex( 0, /* krb5 context */
467                                0, /* parent window */
468                                principal,
469                                password,
470                                lifetime,
471                                forwardable,
472                                proxiable,
473                                renew_life,
474                                addressless,
475                                publicip,
476                                0
477                                );
478 }
479
480 long
481 Leash_int_kinit_ex(
482     krb5_context ctx,
483     HWND hParent,
484     char * principal,
485     char * password,
486     int lifetime,
487     int forwardable,
488     int proxiable,
489     int renew_life,
490     int addressless,
491     unsigned long publicip,
492     int displayErrors
493     )
494 {
495     char    aname[ANAME_SZ];
496     char    inst[INST_SZ];
497     char    realm[REALM_SZ];
498     char    first_part[256];
499     char    second_part[256];
500     char    temp[1024];
501     int     count;
502     int     i;
503     int rc5 = 0;
504     int rcA = 0;
505     int rcB = 0;
506     int rcL = 0;
507
508     if (lifetime < 5)
509         lifetime = 1;
510     else
511         lifetime /= 5;
512
513     if (renew_life > 0 && renew_life < 5)
514         renew_life = 1;
515     else
516         renew_life /= 5;
517
518     /* This should be changed if the maximum ticket lifetime */
519     /* changes */
520
521     if (lifetime > 255)
522         lifetime = 255;
523
524     err_context = "parsing principal";
525
526     memset(temp, '\0', sizeof(temp));
527     memset(inst, '\0', sizeof(inst));
528     memset(realm, '\0', sizeof(realm));
529     memset(first_part, '\0', sizeof(first_part));
530     memset(second_part, '\0', sizeof(second_part));
531
532     sscanf(principal, "%[/0-9a-zA-Z._-]@%[/0-9a-zA-Z._-]", first_part, second_part);
533     strcpy(temp, first_part);
534     strcpy(realm, second_part);
535     memset(first_part, '\0', sizeof(first_part));
536     memset(second_part, '\0', sizeof(second_part));
537     if (sscanf(temp, "%[@0-9a-zA-Z._-]/%[@0-9a-zA-Z._-]", first_part, second_part) == 2)
538     {
539         strcpy(aname, first_part);
540         strcpy(inst, second_part);
541     }
542     else
543     {
544         count = 0;
545         i = 0;
546         for (i = 0; temp[i]; i++)
547         {
548             if (temp[i] == '.')
549                 ++count;
550         }
551         if (count > 1)
552         {
553             strcpy(aname, temp);
554         }
555         else
556         {
557             {
558                 strcpy(aname, temp);
559             }
560         }
561     }
562
563     memset(temp, '\0', sizeof(temp));
564     strcpy(temp, aname);
565     if (strlen(inst) != 0)
566     {
567         strcat(temp, "/");
568         strcat(temp, inst);
569     }
570     if (strlen(realm) != 0)
571     {
572         strcat(temp, "@");
573         strcat(temp, realm);
574     }
575
576     rc5 = Leash_krb5_kinit(ctx, hParent,
577                             temp, password, lifetime,
578                             forwardable,
579                             proxiable,
580                             renew_life,
581                             addressless,
582                             publicip
583                             );
584 #ifndef NO_AFS
585     if ( !rc5 ) {
586         char c;
587         char *r;
588         char *t;
589         for ( r=realm, t=temp; c=*r; r++,t++ )
590             *t = isupper(c) ? tolower(c) : c;
591         *t = '\0';
592
593         rcA = Leash_afs_klog("afs", temp, "", lifetime);
594         rcB = Leash_afs_klog("afs", "", "", lifetime);
595         if (!(rcA && rcB))
596             rcA = 0;
597         else if (!rcA)
598             rcA = rcB;
599     }
600 #endif /* NO_AFS */
601
602     return leash_error_message("Ticket initialization failed.",
603                                rcL,
604                                rc5, rcA, 0,
605                                displayErrors);
606 }
607
608 long FAR
609 Leash_renew(void)
610 {
611     if ( hKrb5 && !LeashKRB5_renew() ) {
612         int lifetime;
613         lifetime = Leash_get_default_lifetime() / 5;
614 #ifndef NO_AFS
615         {
616             TicketList * list = NULL, * token;
617             not_an_API_LeashAFSGetToken(NULL,&list,NULL);
618             for ( token = list ; token ; token = token->next )
619                 Leash_afs_klog("afs", token->realm, "", lifetime);
620             not_an_API_LeashFreeTicketList(&list);
621         }
622 #endif /* NO_AFS */
623         return 1;
624     }
625     return 0;
626 }
627
628 BOOL
629 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
630 {
631     NTSTATUS Status = 0;
632     HANDLE  TokenHandle;
633     TOKEN_STATISTICS Stats;
634     DWORD   ReqLen;
635     BOOL    Success;
636     PSECURITY_LOGON_SESSION_DATA pSessionData;
637
638     if (!ppSessionData)
639         return FALSE;
640     *ppSessionData = NULL;
641
642     Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
643     if ( !Success )
644         return FALSE;
645
646     Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
647     CloseHandle( TokenHandle );
648     if ( !Success )
649         return FALSE;
650
651     Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, &pSessionData );
652     if ( FAILED(Status) || !pSessionData )
653         return FALSE;
654
655         *ppSessionData = pSessionData;
656     return TRUE;
657 }
658
659 // IsKerberosLogon() does not validate whether or not there are valid tickets in the
660 // cache.  It validates whether or not it is reasonable to assume that if we
661 // attempted to retrieve valid tickets we could do so.  Microsoft does not
662 // automatically renew expired tickets.  Therefore, the cache could contain
663 // expired or invalid tickets.  Microsoft also caches the user's password
664 // and will use it to retrieve new TGTs if the cache is empty and tickets
665 // are requested.
666
667 BOOL
668 IsKerberosLogon(VOID)
669 {
670     PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
671     BOOL    Success = FALSE;
672
673     if ( GetSecurityLogonSessionData(&pSessionData) ) {
674         if ( pSessionData->AuthenticationPackage.Buffer ) {
675             WCHAR buffer[256];
676             WCHAR *usBuffer;
677             int usLength;
678
679             Success = FALSE;
680             usBuffer = (pSessionData->AuthenticationPackage).Buffer;
681             usLength = (pSessionData->AuthenticationPackage).Length;
682             if (usLength < 256)
683             {
684                 lstrcpynW (buffer, usBuffer, usLength);
685                 lstrcatW (buffer,L"");
686                 if ( !lstrcmpW(L"Kerberos",buffer) )
687                     Success = TRUE;
688             }
689         }
690         pLsaFreeReturnBuffer(pSessionData);
691     }
692     return Success;
693 }
694
695 static BOOL
696 IsWindowsVista (void)
697 {
698     static BOOL fChecked = FALSE;
699     static BOOL fIsVista = FALSE;
700
701     if (!fChecked)
702     {
703         OSVERSIONINFO Version;
704
705         memset (&Version, 0x00, sizeof(Version));
706         Version.dwOSVersionInfoSize = sizeof(Version);
707
708         if (GetVersionEx (&Version))
709         {
710             if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT && Version.dwMajorVersion >= 6)
711                 fIsVista = TRUE;
712         }
713         fChecked = TRUE;
714     }
715
716     return fIsVista;
717 }
718
719 static BOOL
720 IsProcessUacLimited (void)
721 {
722     static BOOL fChecked = FALSE;
723     static BOOL fIsUAC = FALSE;
724
725     if (!fChecked)
726     {
727         NTSTATUS Status = 0;
728         HANDLE  TokenHandle;
729         DWORD   ElevationLevel;
730         DWORD   ReqLen;
731         BOOL    Success;
732
733         if (IsWindowsVista()) {
734             Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
735             if ( Success ) {
736                 Success = GetTokenInformation( TokenHandle,
737                                                TokenOrigin+1 /* ElevationLevel */,
738                                                &ElevationLevel, sizeof(DWORD), &ReqLen );
739                 CloseHandle( TokenHandle );
740                 if ( Success && ElevationLevel == 3 /* Limited */ )
741                     fIsUAC = TRUE;
742             }
743         }
744         fChecked = TRUE;
745     }
746     return fIsUAC;
747
748 }
749
750 // This looks really ugly because it is.  The result of IsKerberosLogon()
751 // does not prove whether or not there are Kerberos tickets available to
752 // be imported.  Only the call to Leash_ms2mit() which actually attempts
753 // to import tickets can do that.  However, calling Leash_ms2mit() can
754 // result in a TGS_REQ being sent to the KDC and since Leash_importable()
755 // is called quite often we want to avoid this if at all possible.
756 // Unfortunately, we have be shown at least one case in which the primary
757 // authentication package was not Kerberos and yet there were Kerberos
758 // tickets available.  Therefore, if IsKerberosLogon() is not TRUE we
759 // must call Leash_ms2mit() but we still do not want to call it in a
760 // tight loop so we cache the response and assume it won't change.
761
762 // 2007-03-21
763 // And the nightmare goes on.  On Vista the Lsa call we use to determine
764 // whether or not Kerberos was used for logon fails to return and worse
765 // corrupts the stack.  Therefore, we must now test to see if the
766 // operating system is Vista and skip the call to IsKerberosLogon()
767 // if it is.
768 long FAR
769 Leash_importable(void)
770 {
771     if (IsProcessUacLimited())
772         return FALSE;
773
774     if ( !IsWindowsVista() && IsKerberosLogon() )
775         return TRUE;
776     else {
777         static int response = -1;
778         if (response == -1) {
779             response = Leash_ms2mit(0);
780         }
781         return response;
782     }
783 }
784
785 long FAR
786 Leash_import(void)
787 {
788     if ( Leash_ms2mit(1) ) {
789         int lifetime;
790         lifetime = Leash_get_default_lifetime() / 5;
791 #ifndef NO_AFS
792         {
793             char c;
794             char *r;
795             char *t;
796             char  cell[256];
797             char  realm[256];
798             int   i = 0;
799             int   rcA = 0;
800             int   rcB = 0;
801
802             krb5_context ctx = 0;
803             krb5_error_code code = 0;
804             krb5_ccache cc = 0;
805             krb5_principal me = 0;
806
807             if ( !pkrb5_init_context )
808                 goto cleanup;
809
810             code = pkrb5_init_context(&ctx);
811             if (code) goto cleanup;
812
813             code = pkrb5_cc_default(ctx, &cc);
814             if (code) goto cleanup;
815
816             if (code = pkrb5_cc_get_principal(ctx, cc, &me))
817                 goto cleanup;
818
819             for ( r=realm, t=cell, i=0; i<krb5_princ_realm(ctx, me)->length; r++,t++,i++ ) {
820                 c = krb5_princ_realm(ctx, me)->data[i];
821                 *r = c;
822                 *t = isupper(c) ? tolower(c) : c;
823             }
824             *r = *t = '\0';
825
826             rcA = Leash_afs_klog("afs", cell, "", lifetime);
827             rcB = Leash_afs_klog("afs", "", "", lifetime);
828             if (!(rcA && rcB))
829                 rcA = 0;
830             else if (!rcA)
831                 rcA = rcB;
832
833           cleanup:
834             if (me)
835                 pkrb5_free_principal(ctx, me);
836             if (cc)
837                 pkrb5_cc_close(ctx, cc);
838             if (ctx)
839                 pkrb5_free_context(ctx);
840         }
841 #endif /* NO_AFS */
842         return 1;
843     }
844     return 0;
845 }
846
847 long
848 Leash_kdestroy(void)
849 {
850     return 0;
851 }
852
853 long FAR
854 not_an_API_LeashFreeTicketList(TicketList** ticketList)
855 {
856     TicketList* tempList = *ticketList, *killList;
857
858     //if (tempList == NULL)
859     //return -1;
860
861     while (tempList)
862     {
863         killList = tempList;
864
865         tempList = (TicketList*)tempList->next;
866         free(killList->theTicket);
867         if (killList->tktEncType)
868             free(killList->tktEncType);
869         if (killList->keyEncType)
870             free(killList->keyEncType);
871         if (killList->addrCount) {
872             int n;
873             for ( n=0; n<killList->addrCount; n++) {
874                 if (killList->addrList[n])
875                     free(killList->addrList[n]);
876             }
877         }
878         if (killList->addrList)
879             free(killList->addrList);
880         if (killList->name)
881             free(killList->name);
882         if (killList->inst)
883             free(killList->inst);
884         if (killList->realm)
885             free(killList->realm);
886         free(killList);
887     }
888
889     *ticketList = NULL;
890     return 0;
891 }
892
893 long
894 not_an_API_LeashKRB4GetTickets(TICKETINFO FAR* ticketinfo,
895                                TicketList** ticketList)
896 {
897     return(KFAILURE);
898 }
899
900 long FAR Leash_klist(HWND hlist, TICKETINFO FAR *ticketinfo)
901 {
902     return(KFAILURE);
903 }
904
905
906 // This function can be used to set the help file that will be
907 // referenced the DLL's PasswordProcDLL function and err_describe
908 // function.  Returns true if the help file has been set to the
909 // argument or the environment variable KERB_HELP. Returns FALSE if
910 // the default helpfile as defined in by HELPFILE in lsh_pwd.h is
911 // used.
912 BOOL Leash_set_help_file( char *szHelpFile )
913 {
914     char tmpHelpFile[256];
915     BOOL ret = 0;
916
917     if( szHelpFile == NULL ){
918         GetEnvironmentVariable("KERB_HELP", tmpHelpFile, sizeof(tmpHelpFile));
919     } else {
920         strcpy( KRB_HelpFile, szHelpFile );
921         ret++;
922     }
923
924     if( !ret && tmpHelpFile[0] ){
925         strcpy( KRB_HelpFile, tmpHelpFile );
926         ret++;
927     }
928
929     if( !ret){
930         strcpy( KRB_HelpFile, HELPFILE );
931     }
932
933     return(ret);
934 }
935
936
937
938 LPSTR Leash_get_help_file(void)
939 {
940     return( KRB_HelpFile);
941 }
942
943 int
944 Leash_debug(
945     int class,
946     int priority,
947     char* fmt, ...
948     )
949 {
950
951     return 0;
952 }
953
954
955 static int
956 get_profile_file(LPSTR confname, UINT szConfname)
957 {
958     char **configFile = NULL;
959     if (hKrb5) {
960         if (pkrb5_get_default_config_files(&configFile) || !configFile[0])
961         {
962             GetWindowsDirectory(confname,szConfname);
963             confname[szConfname-1] = '\0';
964             strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));
965             confname[szConfname-1] = '\0';
966             return FALSE;
967         }
968
969         *confname = 0;
970
971         if (configFile)
972         {
973             strncpy(confname, *configFile, szConfname);
974             confname[szConfname-1] = '\0';
975             pkrb5_free_config_files(configFile);
976         }
977     }
978
979     if (!*confname)
980     {
981         GetWindowsDirectory(confname,szConfname);
982         confname[szConfname-1] = '\0';
983         strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));
984         confname[szConfname-1] = '\0';
985     }
986
987     return FALSE;
988 }
989
990 static const char *const conf_yes[] = {
991     "y", "yes", "true", "t", "1", "on",
992     0,
993 };
994
995 static const char *const conf_no[] = {
996     "n", "no", "false", "nil", "0", "off",
997     0,
998 };
999
1000 int
1001 config_boolean_to_int(const char *s)
1002 {
1003     const char *const *p;
1004
1005     for(p=conf_yes; *p; p++) {
1006         if (!strcasecmp(*p,s))
1007             return 1;
1008     }
1009
1010     for(p=conf_no; *p; p++) {
1011         if (!strcasecmp(*p,s))
1012             return 0;
1013     }
1014
1015     /* Default to "no" */
1016     return 0;
1017 }
1018
1019 /*
1020  * Leash_get_default_lifetime:
1021  *
1022  * This function is used to get the default ticket lifetime for this
1023  * process in minutes.  A return value of 0 indicates no setting or
1024  * "default" setting obtained.
1025  *
1026  * Here is where we look in order:
1027  *
1028  * - LIFETIME environment variable
1029  * - HKCU\Software\MIT\Leash,lifetime
1030  * - HKLM\Software\MIT\Leash,lifetime
1031  * - string resource in the leash DLL
1032  */
1033
1034 BOOL
1035 get_DWORD_from_registry(
1036     HKEY hBaseKey,
1037     char * key,
1038     char * value,
1039     DWORD * result
1040     )
1041 {
1042     HKEY hKey;
1043     DWORD dwCount;
1044     LONG rc;
1045
1046     rc = RegOpenKeyEx(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey);
1047     if (rc)
1048         return FALSE;
1049
1050     dwCount = sizeof(DWORD);
1051     rc = RegQueryValueEx(hKey, value, 0, 0, (LPBYTE) result, &dwCount);
1052     RegCloseKey(hKey);
1053
1054     return rc?FALSE:TRUE;
1055 }
1056
1057 BOOL
1058 get_STRING_from_registry(
1059     HKEY hBaseKey,
1060     char * key,
1061     char * value,
1062     char * outbuf,
1063     DWORD  outlen
1064     )
1065 {
1066     HKEY hKey;
1067     DWORD dwCount;
1068     LONG rc;
1069
1070         if (!outbuf || outlen == 0)
1071                 return FALSE;
1072
1073     rc = RegOpenKeyEx(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey);
1074     if (rc)
1075         return FALSE;
1076
1077     dwCount = outlen;
1078     rc = RegQueryValueEx(hKey, value, 0, 0, (LPBYTE) outbuf, &dwCount);
1079     RegCloseKey(hKey);
1080
1081     return rc?FALSE:TRUE;
1082 }
1083
1084 static
1085 BOOL
1086 get_default_lifetime_from_registry(
1087     HKEY hBaseKey,
1088     DWORD * result
1089     )
1090 {
1091     return get_DWORD_from_registry(hBaseKey,
1092                                    LEASH_REGISTRY_KEY_NAME,
1093                                    LEASH_REGISTRY_VALUE_LIFETIME,
1094                                    result);
1095 }
1096
1097 DWORD
1098 Leash_reset_default_lifetime(
1099     )
1100 {
1101     HKEY hKey;
1102     LONG rc;
1103
1104     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1105     if (rc)
1106         return rc;
1107
1108     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFETIME);
1109     RegCloseKey(hKey);
1110
1111     return rc;
1112 }
1113
1114 DWORD
1115 Leash_set_default_lifetime(
1116     DWORD minutes
1117     )
1118 {
1119     HKEY hKey;
1120     LONG rc;
1121
1122     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1123                         0, 0, KEY_WRITE, 0, &hKey, 0);
1124     if (rc)
1125         return rc;
1126
1127     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFETIME, 0, REG_DWORD,
1128                        (LPBYTE) &minutes, sizeof(DWORD));
1129     RegCloseKey(hKey);
1130
1131     return rc;
1132 }
1133
1134 DWORD
1135 Leash_get_default_lifetime(
1136     )
1137 {
1138     HMODULE hmLeash;
1139     char env[32];
1140     DWORD result;
1141
1142
1143     if (GetEnvironmentVariable("LIFETIME",env,sizeof(env)))
1144     {
1145         return atoi(env);
1146     }
1147
1148
1149     if (get_default_lifetime_from_registry(HKEY_CURRENT_USER, &result) ||
1150         get_default_lifetime_from_registry(HKEY_LOCAL_MACHINE, &result))
1151     {
1152         return result;
1153     }
1154
1155     if ( hKrb5 ) {
1156         CHAR confname[MAX_PATH];
1157
1158         if (!get_profile_file(confname, sizeof(confname)))
1159         {
1160             profile_t profile;
1161             const char *filenames[2];
1162             long retval;
1163
1164             filenames[0] = confname;
1165             filenames[1] = NULL;
1166             if (!pprofile_init(filenames, &profile)) {
1167                 char * value = NULL;
1168
1169                 retval = pprofile_get_string(profile, "libdefaults", "ticket_lifetime", NULL, NULL, &value);
1170                 if (retval == 0 && value) {
1171                     krb5_deltat d;
1172
1173                     retval = pkrb5_string_to_deltat(value, &d);
1174
1175                     if (retval == KRB5_DELTAT_BADFORMAT) {
1176                         /* Historically some sites use relations of
1177                            the form 'ticket_lifetime = 24000' where
1178                            the unit is left out but is assumed to be
1179                            seconds. Then there are other sites which
1180                            use the form 'ticket_lifetime = 600' where
1181                            the unit is assumed to be minutes.  While
1182                            these are technically wrong (a unit needs
1183                            to be specified), we try to accomodate for
1184                            this using the safe assumption that the
1185                            unit is seconds and tack an 's' to the end
1186                            and see if that works. */
1187
1188                         /* Of course, Leash is one of the platforms
1189                            that historically assumed no units and minutes
1190                            so this change is going to break some people
1191                            but its better to be consistent. */
1192                         size_t cch;
1193                         char buf[256];
1194
1195                         do {
1196                             cch = strlen(value) + 2; /* NUL and new 's' */
1197                             if (cch > sizeof(buf))
1198                                 break;
1199
1200                             strcpy(buf, value);
1201                             strcat(buf, "s");
1202
1203                             retval = pkrb5_string_to_deltat(buf, &d);
1204
1205                             if (retval == 0) {
1206                                 result = d / 60;
1207                             }
1208                         } while(0);
1209                     } else if (retval == 0) {
1210                         result = d / 60;
1211                     }
1212
1213                     pprofile_release_string(value);
1214                 }
1215                 pprofile_release(profile);
1216                 /* value has been released but we can still use a check for
1217                  * non-NULL to see if we were able to read a value.
1218                  */
1219                 if (retval == 0 && value)
1220                     return result;
1221             }
1222         }
1223     }
1224
1225     hmLeash = GetModuleHandle(LEASH_DLL);
1226     if (hmLeash)
1227     {
1228         char lifetime[80];
1229         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_LIFE,
1230                        lifetime, sizeof(lifetime)))
1231         {
1232             lifetime[sizeof(lifetime) - 1] = 0;
1233             return atoi(lifetime);
1234         }
1235     }
1236     return 0;
1237 }
1238
1239 static
1240 BOOL
1241 get_default_renew_till_from_registry(
1242     HKEY hBaseKey,
1243     DWORD * result
1244     )
1245 {
1246     return get_DWORD_from_registry(hBaseKey,
1247                                    LEASH_REGISTRY_KEY_NAME,
1248                                    LEASH_REGISTRY_VALUE_RENEW_TILL,
1249                                    result);
1250 }
1251
1252 DWORD
1253 Leash_reset_default_renew_till(
1254     )
1255 {
1256     HKEY hKey;
1257     LONG rc;
1258
1259     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1260     if (rc)
1261         return rc;
1262
1263     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL);
1264     RegCloseKey(hKey);
1265
1266     return rc;
1267 }
1268
1269 DWORD
1270 Leash_set_default_renew_till(
1271     DWORD minutes
1272     )
1273 {
1274     HKEY hKey;
1275     LONG rc;
1276
1277     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1278                         0, 0, KEY_WRITE, 0, &hKey, 0);
1279     if (rc)
1280         return rc;
1281
1282     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL, 0, REG_DWORD,
1283                        (LPBYTE) &minutes, sizeof(DWORD));
1284     RegCloseKey(hKey);
1285
1286     return rc;
1287 }
1288
1289 DWORD
1290 Leash_get_default_renew_till(
1291     )
1292 {
1293     HMODULE hmLeash;
1294     char env[32];
1295     DWORD result;
1296
1297     if(GetEnvironmentVariable("RENEW_TILL",env,sizeof(env)))
1298     {
1299         return atoi(env);
1300     }
1301
1302     if (get_default_renew_till_from_registry(HKEY_CURRENT_USER, &result) ||
1303         get_default_renew_till_from_registry(HKEY_LOCAL_MACHINE, &result))
1304     {
1305         return result;
1306     }
1307
1308     if ( hKrb5 ) {
1309         CHAR confname[MAX_PATH];
1310         if (!get_profile_file(confname, sizeof(confname)))
1311         {
1312             profile_t profile;
1313             const char *filenames[2];
1314             int value=0;
1315             long retval;
1316             filenames[0] = confname;
1317             filenames[1] = NULL;
1318
1319             if (!pprofile_init(filenames, &profile)) {
1320                 char * value = NULL;
1321
1322                 retval = pprofile_get_string(profile, "libdefaults", "renew_lifetime", NULL, NULL, &value);
1323                 if (retval == 0 && value) {
1324                     krb5_deltat d;
1325
1326                     retval = pkrb5_string_to_deltat(value, &d);
1327                     if (retval == KRB5_DELTAT_BADFORMAT) {
1328                         /* Historically some sites use relations of
1329                            the form 'ticket_lifetime = 24000' where
1330                            the unit is left out but is assumed to be
1331                            seconds. Then there are other sites which
1332                            use the form 'ticket_lifetime = 600' where
1333                            the unit is assumed to be minutes.  While
1334                            these are technically wrong (a unit needs
1335                            to be specified), we try to accomodate for
1336                            this using the safe assumption that the
1337                            unit is seconds and tack an 's' to the end
1338                            and see if that works. */
1339
1340                         /* Of course, Leash is one of the platforms
1341                            that historically assumed no units and minutes
1342                            so this change is going to break some people
1343                            but its better to be consistent. */
1344                         size_t cch;
1345                         char buf[256];
1346                         do {
1347                             cch = strlen(value) + 2; /* NUL and new 's' */
1348                             if (cch > sizeof(buf))
1349                                 break;
1350
1351                             strcpy(buf, value);
1352                             strcat(buf, "s");
1353
1354                             retval = pkrb5_string_to_deltat(buf, &d);
1355                             if (retval == 0) {
1356                                 result = d / 60;
1357                             }
1358                         } while(0);
1359                     } else if (retval == 0) {
1360                         result = d / 60;
1361                     }
1362                     pprofile_release_string(value);
1363                 }
1364                 pprofile_release(profile);
1365                 /* value has been released but we can still use a check for
1366                  * non-NULL to see if we were able to read a value.
1367                  */
1368                 if (retval == 0 && value)
1369                     return result;
1370
1371                 pprofile_release(profile);
1372             }
1373         }
1374     }
1375
1376     hmLeash = GetModuleHandle(LEASH_DLL);
1377     if (hmLeash)
1378     {
1379         char renew_till[80];
1380         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW_TILL,
1381                        renew_till, sizeof(renew_till)))
1382         {
1383             renew_till[sizeof(renew_till) - 1] = 0;
1384             return atoi(renew_till);
1385         }
1386     }
1387     return 0;
1388 }
1389
1390 static
1391 BOOL
1392 get_default_forwardable_from_registry(
1393     HKEY hBaseKey,
1394     DWORD * result
1395     )
1396 {
1397     return get_DWORD_from_registry(hBaseKey,
1398                                    LEASH_REGISTRY_KEY_NAME,
1399                                    LEASH_REGISTRY_VALUE_FORWARDABLE,
1400                                    result);
1401 }
1402
1403 DWORD
1404 Leash_reset_default_forwardable(
1405     )
1406 {
1407     HKEY hKey;
1408     LONG rc;
1409
1410     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1411     if (rc)
1412         return rc;
1413
1414     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE);
1415     RegCloseKey(hKey);
1416
1417     return rc;
1418 }
1419
1420 DWORD
1421 Leash_set_default_forwardable(
1422     DWORD minutes
1423     )
1424 {
1425     HKEY hKey;
1426     LONG rc;
1427
1428     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1429                         0, 0, KEY_WRITE, 0, &hKey, 0);
1430     if (rc)
1431         return rc;
1432
1433     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE, 0, REG_DWORD,
1434                        (LPBYTE) &minutes, sizeof(DWORD));
1435     RegCloseKey(hKey);
1436
1437     return rc;
1438 }
1439
1440 DWORD
1441 Leash_get_default_forwardable(
1442     )
1443 {
1444     HMODULE hmLeash;
1445
1446     char env[32];
1447     DWORD result;
1448
1449     if(GetEnvironmentVariable("FORWARDABLE",env,sizeof(env)))
1450     {
1451         return atoi(env);
1452     }
1453
1454     if (get_default_forwardable_from_registry(HKEY_CURRENT_USER, &result) ||
1455         get_default_forwardable_from_registry(HKEY_LOCAL_MACHINE, &result))
1456     {
1457         return result;
1458     }
1459
1460     if ( hKrb5 ) {
1461         CHAR confname[MAX_PATH];
1462         if (!get_profile_file(confname, sizeof(confname)))
1463         {
1464             profile_t profile;
1465             const char *filenames[2];
1466             char *value=0;
1467             long retval;
1468             filenames[0] = confname;
1469             filenames[1] = NULL;
1470             if (!pprofile_init(filenames, &profile)) {
1471                 retval = pprofile_get_string(profile, "libdefaults","forwardable", 0, 0, &value);
1472                 if ( value ) {
1473                     result = config_boolean_to_int(value);
1474                     pprofile_release_string(value);
1475                     pprofile_release(profile);
1476                     return result;
1477                 }
1478                 pprofile_release(profile);
1479             }
1480         }
1481     }
1482
1483     hmLeash = GetModuleHandle(LEASH_DLL);
1484     if (hmLeash)
1485     {
1486         char forwardable[80];
1487         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_FORWARD,
1488                        forwardable, sizeof(forwardable)))
1489         {
1490             forwardable[sizeof(forwardable) - 1] = 0;
1491             return atoi(forwardable);
1492         }
1493     }
1494     return 0;
1495 }
1496
1497 static
1498 BOOL
1499 get_default_renewable_from_registry(
1500     HKEY hBaseKey,
1501     DWORD * result
1502     )
1503 {
1504     return get_DWORD_from_registry(hBaseKey,
1505                                    LEASH_REGISTRY_KEY_NAME,
1506                                    LEASH_REGISTRY_VALUE_RENEWABLE,
1507                                    result);
1508 }
1509
1510 DWORD
1511 Leash_reset_default_renewable(
1512     )
1513 {
1514     HKEY hKey;
1515     LONG rc;
1516
1517     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1518     if (rc)
1519         return rc;
1520
1521     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEWABLE);
1522     RegCloseKey(hKey);
1523
1524     return rc;
1525 }
1526
1527 DWORD
1528 Leash_set_default_renewable(
1529     DWORD minutes
1530     )
1531 {
1532     HKEY hKey;
1533     LONG rc;
1534
1535     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1536                         0, 0, KEY_WRITE, 0, &hKey, 0);
1537     if (rc)
1538         return rc;
1539
1540     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEWABLE, 0, REG_DWORD,
1541                        (LPBYTE) &minutes, sizeof(DWORD));
1542     RegCloseKey(hKey);
1543
1544     return rc;
1545 }
1546
1547 DWORD
1548 Leash_get_default_renewable(
1549     )
1550 {
1551     HMODULE hmLeash;
1552     char env[32];
1553     DWORD result;
1554
1555     if(GetEnvironmentVariable("RENEWABLE",env,sizeof(env)))
1556     {
1557         return atoi(env);
1558     }
1559
1560     if (get_default_renewable_from_registry(HKEY_CURRENT_USER, &result) ||
1561         get_default_renewable_from_registry(HKEY_LOCAL_MACHINE, &result))
1562     {
1563         return result;
1564     }
1565
1566     if ( hKrb5 ) {
1567         CHAR confname[MAX_PATH];
1568         if (!get_profile_file(confname, sizeof(confname)))
1569         {
1570             profile_t profile;
1571             const char *filenames[2];
1572             char *value=0;
1573             long retval;
1574             filenames[0] = confname;
1575             filenames[1] = NULL;
1576             if (!pprofile_init(filenames, &profile)) {
1577                 retval = pprofile_get_string(profile, "libdefaults","renewable", 0, 0, &value);
1578                 if ( value ) {
1579                     result = config_boolean_to_int(value);
1580                     pprofile_release_string(value);
1581                     pprofile_release(profile);
1582                     return result;
1583                 }
1584                 pprofile_release(profile);
1585             }
1586         }
1587     }
1588
1589     hmLeash = GetModuleHandle(LEASH_DLL);
1590     if (hmLeash)
1591     {
1592         char renewable[80];
1593         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW,
1594                        renewable, sizeof(renewable)))
1595         {
1596             renewable[sizeof(renewable) - 1] = 0;
1597             return atoi(renewable);
1598         }
1599     }
1600     return 0;
1601 }
1602
1603 static
1604 BOOL
1605 get_default_noaddresses_from_registry(
1606     HKEY hBaseKey,
1607     DWORD * result
1608     )
1609 {
1610     return get_DWORD_from_registry(hBaseKey,
1611                                    LEASH_REGISTRY_KEY_NAME,
1612                                    LEASH_REGISTRY_VALUE_NOADDRESSES,
1613                                    result);
1614 }
1615
1616 DWORD
1617 Leash_reset_default_noaddresses(
1618     )
1619 {
1620     HKEY hKey;
1621     LONG rc;
1622
1623     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1624     if (rc)
1625         return rc;
1626
1627     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES);
1628     RegCloseKey(hKey);
1629
1630     return rc;
1631 }
1632
1633 DWORD
1634 Leash_set_default_noaddresses(
1635     DWORD minutes
1636     )
1637 {
1638     HKEY hKey;
1639     LONG rc;
1640
1641     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1642                         0, 0, KEY_WRITE, 0, &hKey, 0);
1643     if (rc)
1644         return rc;
1645
1646     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES, 0, REG_DWORD,
1647                        (LPBYTE) &minutes, sizeof(DWORD));
1648     RegCloseKey(hKey);
1649
1650     return rc;
1651 }
1652
1653 DWORD
1654 Leash_get_default_noaddresses(
1655     )
1656 {
1657     HMODULE hmLeash;
1658     char env[32];
1659     DWORD result;
1660
1661     if ( hKrb5 ) {
1662         // if the profile file cannot be opened then the value will be true
1663         // if the noaddresses name cannot be found then the value will be true
1664         // if true in the library, we can't alter it by other means
1665         CHAR confname[MAX_PATH];
1666         result = 1;
1667         if (!get_profile_file(confname, sizeof(confname)))
1668         {
1669             profile_t profile;
1670             const char *filenames[2];
1671             char *value=0;
1672             long retval;
1673             filenames[0] = confname;
1674             filenames[1] = NULL;
1675             if (!pprofile_init(filenames, &profile)) {
1676                 retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
1677                 if ( value ) {
1678                     result = config_boolean_to_int(value);
1679                     pprofile_release_string(value);
1680                 }
1681                 pprofile_release(profile);
1682             }
1683         }
1684
1685         if ( result )
1686             return 1;
1687     }
1688
1689     // The library default is false, check other locations
1690
1691     if(GetEnvironmentVariable("NOADDRESSES",env,sizeof(env)))
1692     {
1693         return atoi(env);
1694     }
1695
1696     if (get_default_noaddresses_from_registry(HKEY_CURRENT_USER, &result) ||
1697         get_default_noaddresses_from_registry(HKEY_LOCAL_MACHINE, &result))
1698     {
1699         return result;
1700     }
1701
1702     hmLeash = GetModuleHandle(LEASH_DLL);
1703     if (hmLeash)
1704     {
1705         char noaddresses[80];
1706         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_NOADDRESS,
1707                        noaddresses, sizeof(noaddresses)))
1708         {
1709             noaddresses[sizeof(noaddresses) - 1] = 0;
1710         }
1711     }
1712     return 1;
1713 }
1714
1715 static
1716 BOOL
1717 get_default_proxiable_from_registry(
1718     HKEY hBaseKey,
1719     DWORD * result
1720     )
1721 {
1722     return get_DWORD_from_registry(hBaseKey,
1723                                    LEASH_REGISTRY_KEY_NAME,
1724                                    LEASH_REGISTRY_VALUE_PROXIABLE,
1725                                    result);
1726 }
1727
1728 DWORD
1729 Leash_reset_default_proxiable(
1730     )
1731 {
1732     HKEY hKey;
1733     LONG rc;
1734
1735     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1736     if (rc)
1737         return rc;
1738
1739     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PROXIABLE);
1740     RegCloseKey(hKey);
1741
1742     return rc;
1743 }
1744
1745 DWORD
1746 Leash_set_default_proxiable(
1747     DWORD minutes
1748     )
1749 {
1750     HKEY hKey;
1751     LONG rc;
1752
1753     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1754                         0, 0, KEY_WRITE, 0, &hKey, 0);
1755     if (rc)
1756         return rc;
1757
1758     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PROXIABLE, 0, REG_DWORD,
1759                        (LPBYTE) &minutes, sizeof(DWORD));
1760     RegCloseKey(hKey);
1761
1762     return rc;
1763 }
1764
1765 DWORD
1766 Leash_get_default_proxiable(
1767     )
1768 {
1769     HMODULE hmLeash;
1770     char env[32];
1771     DWORD result;
1772
1773     if(GetEnvironmentVariable("PROXIABLE",env,sizeof(env)))
1774     {
1775         return atoi(env);
1776     }
1777
1778     if (get_default_proxiable_from_registry(HKEY_CURRENT_USER, &result) ||
1779         get_default_proxiable_from_registry(HKEY_LOCAL_MACHINE, &result))
1780     {
1781         return result;
1782     }
1783
1784     if ( hKrb5 ) {
1785         CHAR confname[MAX_PATH];
1786         if (!get_profile_file(confname, sizeof(confname)))
1787         {
1788             profile_t profile;
1789             const char *filenames[2];
1790             char *value=0;
1791             long retval;
1792             filenames[0] = confname;
1793             filenames[1] = NULL;
1794             if (!pprofile_init(filenames, &profile)) {
1795                 retval = pprofile_get_string(profile, "libdefaults","proxiable", 0, 0, &value);
1796                 if ( value ) {
1797                     result = config_boolean_to_int(value);
1798                     pprofile_release_string(value);
1799                     pprofile_release(profile);
1800                     return result;
1801                 }
1802                 pprofile_release(profile);
1803             }
1804         }
1805     }
1806
1807     hmLeash = GetModuleHandle(LEASH_DLL);
1808     if (hmLeash)
1809     {
1810         char proxiable[80];
1811         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PROXIABLE,
1812                        proxiable, sizeof(proxiable)))
1813         {
1814             proxiable[sizeof(proxiable) - 1] = 0;
1815             return atoi(proxiable);
1816         }
1817     }
1818     return 0;
1819 }
1820
1821 static
1822 BOOL
1823 get_default_publicip_from_registry(
1824     HKEY hBaseKey,
1825     DWORD * result
1826     )
1827 {
1828     return get_DWORD_from_registry(hBaseKey,
1829                                    LEASH_REGISTRY_KEY_NAME,
1830                                    LEASH_REGISTRY_VALUE_PUBLICIP,
1831                                    result);
1832 }
1833
1834 DWORD
1835 Leash_reset_default_publicip(
1836     )
1837 {
1838     HKEY hKey;
1839     LONG rc;
1840
1841     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1842     if (rc)
1843         return rc;
1844
1845     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PUBLICIP);
1846     RegCloseKey(hKey);
1847
1848     return rc;
1849 }
1850
1851 DWORD
1852 Leash_set_default_publicip(
1853     DWORD minutes
1854     )
1855 {
1856     HKEY hKey;
1857     LONG rc;
1858
1859     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1860                         0, 0, KEY_WRITE, 0, &hKey, 0);
1861     if (rc)
1862         return rc;
1863
1864     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PUBLICIP, 0, REG_DWORD,
1865                        (LPBYTE) &minutes, sizeof(DWORD));
1866     RegCloseKey(hKey);
1867
1868     return rc;
1869 }
1870
1871 DWORD
1872 Leash_get_default_publicip(
1873     )
1874 {
1875     HMODULE hmLeash;
1876     char env[32];
1877     DWORD result;
1878
1879     if(GetEnvironmentVariable("PUBLICIP",env,sizeof(env)))
1880     {
1881         return atoi(env);
1882     }
1883
1884     if (get_default_publicip_from_registry(HKEY_CURRENT_USER, &result) ||
1885         get_default_publicip_from_registry(HKEY_LOCAL_MACHINE, &result))
1886     {
1887         return result;
1888     }
1889
1890     hmLeash = GetModuleHandle(LEASH_DLL);
1891     if (hmLeash)
1892     {
1893         char publicip[80];
1894         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PUBLICIP,
1895                        publicip, sizeof(publicip)))
1896         {
1897             publicip[sizeof(publicip) - 1] = 0;
1898             return atoi(publicip);
1899         }
1900     }
1901     return 0;
1902 }
1903
1904 static
1905 BOOL
1906 get_default_use_krb4_from_registry(
1907     HKEY hBaseKey,
1908     DWORD * result
1909     )
1910 {
1911     return get_DWORD_from_registry(hBaseKey,
1912                                    LEASH_REGISTRY_KEY_NAME,
1913                                    LEASH_REGISTRY_VALUE_USEKRB4,
1914                                    result);
1915 }
1916
1917 DWORD
1918 Leash_reset_default_use_krb4(
1919     )
1920 {
1921     HKEY hKey;
1922     LONG rc;
1923
1924     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1925     if (rc)
1926         return rc;
1927
1928     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_USEKRB4);
1929     RegCloseKey(hKey);
1930
1931     return rc;
1932 }
1933
1934 DWORD
1935 Leash_set_default_use_krb4(
1936     DWORD minutes
1937     )
1938 {
1939     HKEY hKey;
1940     LONG rc;
1941
1942     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1943                         0, 0, KEY_WRITE, 0, &hKey, 0);
1944     if (rc)
1945         return rc;
1946
1947     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_USEKRB4, 0, REG_DWORD,
1948                        (LPBYTE) &minutes, sizeof(DWORD));
1949     RegCloseKey(hKey);
1950
1951     return rc;
1952 }
1953
1954 DWORD
1955 Leash_get_default_use_krb4(
1956     )
1957 {
1958     return 0;   /* don't use krb4 */
1959 }
1960
1961 static
1962 BOOL
1963 get_hide_kinit_options_from_registry(
1964     HKEY hBaseKey,
1965     DWORD * result
1966     )
1967 {
1968     return get_DWORD_from_registry(hBaseKey,
1969                                    LEASH_REGISTRY_KEY_NAME,
1970                                    LEASH_REGISTRY_VALUE_KINIT_OPT,
1971                                    result);
1972 }
1973
1974 DWORD
1975 Leash_reset_hide_kinit_options(
1976     )
1977 {
1978     HKEY hKey;
1979     LONG rc;
1980
1981     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1982     if (rc)
1983         return rc;
1984
1985     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT);
1986     RegCloseKey(hKey);
1987
1988     return rc;
1989 }
1990
1991 DWORD
1992 Leash_set_hide_kinit_options(
1993     DWORD minutes
1994     )
1995 {
1996     HKEY hKey;
1997     LONG rc;
1998
1999     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2000                         0, 0, KEY_WRITE, 0, &hKey, 0);
2001     if (rc)
2002         return rc;
2003
2004     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT, 0, REG_DWORD,
2005                        (LPBYTE) &minutes, sizeof(DWORD));
2006     RegCloseKey(hKey);
2007
2008     return rc;
2009 }
2010
2011 DWORD
2012 Leash_get_hide_kinit_options(
2013     )
2014 {
2015     HMODULE hmLeash;
2016     DWORD result;
2017
2018     if (get_hide_kinit_options_from_registry(HKEY_CURRENT_USER, &result) ||
2019         get_hide_kinit_options_from_registry(HKEY_LOCAL_MACHINE, &result))
2020     {
2021         return result;
2022     }
2023
2024     hmLeash = GetModuleHandle(LEASH_DLL);
2025     if (hmLeash)
2026     {
2027         char use_krb4[80];
2028         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_KINIT_OPT,
2029                        use_krb4, sizeof(use_krb4)))
2030         {
2031             use_krb4[sizeof(use_krb4) - 1] = 0;
2032             return atoi(use_krb4);
2033         }
2034     }
2035     return 0;   /* hide unless otherwise indicated */
2036 }
2037
2038
2039
2040 static
2041 BOOL
2042 get_default_life_min_from_registry(
2043     HKEY hBaseKey,
2044     DWORD * result
2045     )
2046 {
2047     return get_DWORD_from_registry(hBaseKey,
2048                                    LEASH_REGISTRY_KEY_NAME,
2049                                    LEASH_REGISTRY_VALUE_LIFE_MIN,
2050                                    result);
2051 }
2052
2053 DWORD
2054 Leash_reset_default_life_min(
2055     )
2056 {
2057     HKEY hKey;
2058     LONG rc;
2059
2060     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2061     if (rc)
2062         return rc;
2063
2064     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN);
2065     RegCloseKey(hKey);
2066
2067     return rc;
2068 }
2069
2070 DWORD
2071 Leash_set_default_life_min(
2072     DWORD minutes
2073     )
2074 {
2075     HKEY hKey;
2076     LONG rc;
2077
2078     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2079                         0, 0, KEY_WRITE, 0, &hKey, 0);
2080     if (rc)
2081         return rc;
2082
2083     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN, 0, REG_DWORD,
2084                        (LPBYTE) &minutes, sizeof(DWORD));
2085     RegCloseKey(hKey);
2086
2087     return rc;
2088 }
2089
2090 DWORD
2091 Leash_get_default_life_min(
2092     )
2093 {
2094     HMODULE hmLeash;
2095     DWORD result;
2096
2097     if (get_default_life_min_from_registry(HKEY_CURRENT_USER, &result) ||
2098         get_default_life_min_from_registry(HKEY_LOCAL_MACHINE, &result))
2099     {
2100         return result;
2101     }
2102
2103     hmLeash = GetModuleHandle(LEASH_DLL);
2104     if (hmLeash)
2105     {
2106         char use_krb4[80];
2107         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MIN,
2108                        use_krb4, sizeof(use_krb4)))
2109         {
2110             use_krb4[sizeof(use_krb4) - 1] = 0;
2111             return atoi(use_krb4);
2112         }
2113     }
2114     return 5;   /* 5 minutes */
2115 }
2116
2117 static
2118 BOOL
2119 get_default_life_max_from_registry(
2120     HKEY hBaseKey,
2121     DWORD * result
2122     )
2123 {
2124     return get_DWORD_from_registry(hBaseKey,
2125                                    LEASH_REGISTRY_KEY_NAME,
2126                                    LEASH_REGISTRY_VALUE_LIFE_MAX,
2127                                    result);
2128 }
2129
2130 DWORD
2131 Leash_reset_default_life_max(
2132     )
2133 {
2134     HKEY hKey;
2135     LONG rc;
2136
2137     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2138     if (rc)
2139         return rc;
2140
2141     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX);
2142     RegCloseKey(hKey);
2143
2144     return rc;
2145 }
2146
2147 DWORD
2148 Leash_set_default_life_max(
2149     DWORD minutes
2150     )
2151 {
2152     HKEY hKey;
2153     LONG rc;
2154
2155     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2156                         0, 0, KEY_WRITE, 0, &hKey, 0);
2157     if (rc)
2158         return rc;
2159
2160     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX, 0, REG_DWORD,
2161                        (LPBYTE) &minutes, sizeof(DWORD));
2162     RegCloseKey(hKey);
2163
2164     return rc;
2165 }
2166
2167 DWORD
2168 Leash_get_default_life_max(
2169     )
2170 {
2171     HMODULE hmLeash;
2172     DWORD result;
2173
2174     if (get_default_life_max_from_registry(HKEY_CURRENT_USER, &result) ||
2175         get_default_life_max_from_registry(HKEY_LOCAL_MACHINE, &result))
2176     {
2177         return result;
2178     }
2179
2180     hmLeash = GetModuleHandle(LEASH_DLL);
2181     if (hmLeash)
2182     {
2183         char use_krb4[80];
2184         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MAX,
2185                        use_krb4, sizeof(use_krb4)))
2186         {
2187             use_krb4[sizeof(use_krb4) - 1] = 0;
2188             return atoi(use_krb4);
2189         }
2190     }
2191     return 1440;
2192 }
2193
2194 static
2195 BOOL
2196 get_default_renew_min_from_registry(
2197     HKEY hBaseKey,
2198     DWORD * result
2199     )
2200 {
2201     return get_DWORD_from_registry(hBaseKey,
2202                                    LEASH_REGISTRY_KEY_NAME,
2203                                    LEASH_REGISTRY_VALUE_RENEW_MIN,
2204                                    result);
2205 }
2206
2207 DWORD
2208 Leash_reset_default_renew_min(
2209     )
2210 {
2211     HKEY hKey;
2212     LONG rc;
2213
2214     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2215     if (rc)
2216         return rc;
2217
2218     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN);
2219     RegCloseKey(hKey);
2220
2221     return rc;
2222 }
2223
2224 DWORD
2225 Leash_set_default_renew_min(
2226     DWORD minutes
2227     )
2228 {
2229     HKEY hKey;
2230     LONG rc;
2231
2232     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2233                         0, 0, KEY_WRITE, 0, &hKey, 0);
2234     if (rc)
2235         return rc;
2236
2237     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN, 0, REG_DWORD,
2238                        (LPBYTE) &minutes, sizeof(DWORD));
2239     RegCloseKey(hKey);
2240
2241     return rc;
2242 }
2243
2244 DWORD
2245 Leash_get_default_renew_min(
2246     )
2247 {
2248     HMODULE hmLeash;
2249     DWORD result;
2250
2251     if (get_default_renew_min_from_registry(HKEY_CURRENT_USER, &result) ||
2252         get_default_renew_min_from_registry(HKEY_LOCAL_MACHINE, &result))
2253     {
2254         return result;
2255     }
2256
2257     hmLeash = GetModuleHandle(LEASH_DLL);
2258     if (hmLeash)
2259     {
2260         char use_krb4[80];
2261         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MIN,
2262                        use_krb4, sizeof(use_krb4)))
2263         {
2264             use_krb4[sizeof(use_krb4) - 1] = 0;
2265             return atoi(use_krb4);
2266         }
2267     }
2268     return 600;         /* 10 hours */
2269 }
2270
2271 static
2272 BOOL
2273 get_default_renew_max_from_registry(
2274     HKEY hBaseKey,
2275     DWORD * result
2276     )
2277 {
2278     return get_DWORD_from_registry(hBaseKey,
2279                                    LEASH_REGISTRY_KEY_NAME,
2280                                    LEASH_REGISTRY_VALUE_RENEW_MAX,
2281                                    result);
2282 }
2283
2284 DWORD
2285 Leash_reset_default_renew_max(
2286     )
2287 {
2288     HKEY hKey;
2289     LONG rc;
2290
2291     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2292     if (rc)
2293         return rc;
2294
2295     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX);
2296     RegCloseKey(hKey);
2297
2298     return rc;
2299 }
2300
2301 DWORD
2302 Leash_set_default_renew_max(
2303     DWORD minutes
2304     )
2305 {
2306     HKEY hKey;
2307     LONG rc;
2308
2309     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2310                         0, 0, KEY_WRITE, 0, &hKey, 0);
2311     if (rc)
2312         return rc;
2313
2314     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX, 0, REG_DWORD,
2315                        (LPBYTE) &minutes, sizeof(DWORD));
2316     RegCloseKey(hKey);
2317
2318     return rc;
2319 }
2320
2321 DWORD
2322 Leash_get_default_renew_max(
2323     )
2324 {
2325     HMODULE hmLeash;
2326     DWORD result;
2327
2328     if (get_default_renew_max_from_registry(HKEY_CURRENT_USER, &result) ||
2329         get_default_renew_max_from_registry(HKEY_LOCAL_MACHINE, &result))
2330     {
2331         return result;
2332     }
2333
2334     hmLeash = GetModuleHandle(LEASH_DLL);
2335     if (hmLeash)
2336     {
2337         char use_krb4[80];
2338         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MAX,
2339                        use_krb4, sizeof(use_krb4)))
2340         {
2341             use_krb4[sizeof(use_krb4) - 1] = 0;
2342             return atoi(use_krb4);
2343         }
2344     }
2345     return 60 * 24 * 30;
2346 }
2347
2348 static
2349 BOOL
2350 get_lock_file_locations_from_registry(
2351     HKEY hBaseKey,
2352     DWORD * result
2353     )
2354 {
2355     return get_DWORD_from_registry(hBaseKey,
2356                                    LEASH_REGISTRY_KEY_NAME,
2357                                    LEASH_REGISTRY_VALUE_LOCK_LOCATION,
2358                                    result);
2359 }
2360
2361 DWORD
2362 Leash_reset_lock_file_locations(
2363     )
2364 {
2365     HKEY hKey;
2366     LONG rc;
2367
2368     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2369     if (rc)
2370         return rc;
2371
2372     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LOCK_LOCATION);
2373     RegCloseKey(hKey);
2374
2375     return rc;
2376 }
2377
2378 DWORD
2379 Leash_set_lock_file_locations(
2380     DWORD onoff
2381     )
2382 {
2383     HKEY hKey;
2384     LONG rc;
2385
2386     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2387                         0, 0, KEY_WRITE, 0, &hKey, 0);
2388     if (rc)
2389         return rc;
2390
2391     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LOCK_LOCATION, 0, REG_DWORD,
2392                        (LPBYTE) &onoff, sizeof(DWORD));
2393     RegCloseKey(hKey);
2394
2395     return rc;
2396 }
2397
2398 DWORD
2399 Leash_get_lock_file_locations(
2400     )
2401 {
2402     HMODULE hmLeash;
2403     DWORD result;
2404
2405     if (get_lock_file_locations_from_registry(HKEY_CURRENT_USER, &result) ||
2406         get_lock_file_locations_from_registry(HKEY_LOCAL_MACHINE, &result))
2407     {
2408         return result;
2409     }
2410
2411     hmLeash = GetModuleHandle(LEASH_DLL);
2412     if (hmLeash)
2413     {
2414         char lock_file_locations[80];
2415         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LOCK_LOCATION,
2416                        lock_file_locations, sizeof(lock_file_locations)))
2417         {
2418             lock_file_locations[sizeof(lock_file_locations) - 1] = 0;
2419             return atoi(lock_file_locations);
2420         }
2421     }
2422     return 0;
2423 }
2424
2425 static
2426 BOOL
2427 get_default_uppercaserealm_from_registry(
2428     HKEY hBaseKey,
2429     DWORD * result
2430     )
2431 {
2432     return get_DWORD_from_registry(hBaseKey,
2433                                    LEASH_SETTINGS_REGISTRY_KEY_NAME,
2434                                    LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM,
2435                                    result);
2436 }
2437
2438 DWORD
2439 Leash_reset_default_uppercaserealm(
2440     )
2441 {
2442     HKEY hKey;
2443     LONG rc;
2444
2445     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2446     if (rc)
2447         return rc;
2448
2449     rc = RegDeleteValue(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM);
2450     RegCloseKey(hKey);
2451
2452     return rc;
2453 }
2454
2455 DWORD
2456 Leash_set_default_uppercaserealm(
2457     DWORD onoff
2458     )
2459 {
2460     HKEY hKey;
2461     LONG rc;
2462
2463     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0,
2464                         0, 0, KEY_WRITE, 0, &hKey, 0);
2465     if (rc)
2466         return rc;
2467
2468     rc = RegSetValueEx(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM, 0, REG_DWORD,
2469                        (LPBYTE) &onoff, sizeof(DWORD));
2470     RegCloseKey(hKey);
2471
2472     return rc;
2473 }
2474
2475 DWORD
2476 Leash_get_default_uppercaserealm(
2477     )
2478 {
2479     HMODULE hmLeash;
2480     DWORD result;
2481
2482     if (get_default_uppercaserealm_from_registry(HKEY_CURRENT_USER, &result) ||
2483         get_default_uppercaserealm_from_registry(HKEY_LOCAL_MACHINE, &result))
2484     {
2485         return result;
2486     }
2487
2488     hmLeash = GetModuleHandle(LEASH_DLL);
2489     if (hmLeash)
2490     {
2491         char uppercaserealm[80];
2492         if (LoadString(hmLeash, LSH_DEFAULT_UPPERCASEREALM,
2493                        uppercaserealm, sizeof(uppercaserealm)))
2494         {
2495             uppercaserealm[sizeof(uppercaserealm) - 1] = 0;
2496             return atoi(uppercaserealm);
2497         }
2498     }
2499     return 1;
2500 }
2501
2502 static
2503 BOOL
2504 get_default_mslsa_import_from_registry(
2505     HKEY hBaseKey,
2506     DWORD * result
2507     )
2508 {
2509     return get_DWORD_from_registry(hBaseKey,
2510                                    LEASH_SETTINGS_REGISTRY_KEY_NAME,
2511                                    LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT,
2512                                    result);
2513 }
2514
2515 DWORD
2516 Leash_reset_default_mslsa_import(
2517     )
2518 {
2519     HKEY hKey;
2520     LONG rc;
2521
2522     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2523     if (rc)
2524         return rc;
2525
2526     rc = RegDeleteValue(hKey, LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT);
2527     RegCloseKey(hKey);
2528
2529     return rc;
2530 }
2531
2532 DWORD
2533 Leash_set_default_mslsa_import(
2534     DWORD onoffmatch
2535     )
2536 {
2537     HKEY hKey;
2538     LONG rc;
2539
2540     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0,
2541                         0, 0, KEY_WRITE, 0, &hKey, 0);
2542     if (rc)
2543         return rc;
2544
2545     rc = RegSetValueEx(hKey, LEASH_SETTINGS_REGISTRY_VALUE_MSLSA_IMPORT, 0, REG_DWORD,
2546                        (LPBYTE) &onoffmatch, sizeof(DWORD));
2547     RegCloseKey(hKey);
2548
2549     return rc;
2550 }
2551
2552 DWORD
2553 Leash_get_default_mslsa_import(
2554     )
2555 {
2556     HMODULE hmLeash;
2557     DWORD result;
2558
2559     if (get_default_mslsa_import_from_registry(HKEY_CURRENT_USER, &result) ||
2560         get_default_mslsa_import_from_registry(HKEY_LOCAL_MACHINE, &result))
2561     {
2562         return result;
2563     }
2564
2565     hmLeash = GetModuleHandle(LEASH_DLL);
2566     if (hmLeash)
2567     {
2568         char mslsa_import[80];
2569         if (LoadString(hmLeash, LSH_DEFAULT_MSLSA_IMPORT,
2570                        mslsa_import, sizeof(mslsa_import)))
2571         {
2572             mslsa_import[sizeof(mslsa_import) - 1] = 0;
2573             return atoi(mslsa_import);
2574         }
2575     }
2576     return 2;   /* import only when mslsa realm matches default */
2577 }
2578
2579
2580 static
2581 BOOL
2582 get_default_preserve_kinit_settings_from_registry(
2583     HKEY hBaseKey,
2584     DWORD * result
2585     )
2586 {
2587     return get_DWORD_from_registry(hBaseKey,
2588                                    LEASH_REGISTRY_KEY_NAME,
2589                                    LEASH_REGISTRY_VALUE_PRESERVE_KINIT,
2590                                    result);
2591 }
2592
2593 DWORD
2594 Leash_reset_default_preserve_kinit_settings(
2595     )
2596 {
2597     HKEY hKey;
2598     LONG rc;
2599
2600     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2601     if (rc)
2602         return rc;
2603
2604     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT);
2605     RegCloseKey(hKey);
2606
2607     return rc;
2608 }
2609
2610 DWORD
2611 Leash_set_default_preserve_kinit_settings(
2612     DWORD onoff
2613     )
2614 {
2615     HKEY hKey;
2616     LONG rc;
2617
2618     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2619                         0, 0, KEY_WRITE, 0, &hKey, 0);
2620     if (rc)
2621         return rc;
2622
2623     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT, 0, REG_DWORD,
2624                        (LPBYTE) &onoff, sizeof(DWORD));
2625     RegCloseKey(hKey);
2626
2627     return rc;
2628 }
2629
2630 DWORD
2631 Leash_get_default_preserve_kinit_settings(
2632     )
2633 {
2634     HMODULE hmLeash;
2635     DWORD result;
2636
2637     if (get_default_preserve_kinit_settings_from_registry(HKEY_CURRENT_USER, &result) ||
2638         get_default_preserve_kinit_settings_from_registry(HKEY_LOCAL_MACHINE, &result))
2639     {
2640         return result;
2641     }
2642
2643     hmLeash = GetModuleHandle(LEASH_DLL);
2644     if (hmLeash)
2645     {
2646         char preserve_kinit_settings[80];
2647         if (LoadString(hmLeash, LSH_DEFAULT_PRESERVE_KINIT,
2648                        preserve_kinit_settings, sizeof(preserve_kinit_settings)))
2649         {
2650             preserve_kinit_settings[sizeof(preserve_kinit_settings) - 1] = 0;
2651             return atoi(preserve_kinit_settings);
2652         }
2653     }
2654     return 1;
2655 }
2656
2657 void
2658 Leash_reset_defaults(void)
2659 {
2660     Leash_reset_default_lifetime();
2661     Leash_reset_default_renew_till();
2662     Leash_reset_default_renewable();
2663     Leash_reset_default_forwardable();
2664     Leash_reset_default_noaddresses();
2665     Leash_reset_default_proxiable();
2666     Leash_reset_default_publicip();
2667     Leash_reset_default_use_krb4();
2668     Leash_reset_hide_kinit_options();
2669     Leash_reset_default_life_min();
2670     Leash_reset_default_life_max();
2671     Leash_reset_default_renew_min();
2672     Leash_reset_default_renew_max();
2673     Leash_reset_default_uppercaserealm();
2674     Leash_reset_default_mslsa_import();
2675     Leash_reset_default_preserve_kinit_settings();
2676 }
2677
2678 static BOOL CALLBACK
2679 EnumChildProc(HWND hwnd, LPARAM lParam)
2680 {
2681     HWND * h = (HWND *)lParam;
2682     *h = hwnd;
2683     return FALSE;
2684 }
2685
2686
2687 static HWND
2688 FindFirstChildWindow(HWND parent)
2689 {
2690     HWND hFirstChild = 0;
2691     EnumChildWindows(parent, EnumChildProc, (LPARAM) &hFirstChild);
2692     return hFirstChild;
2693 }
2694
2695 static int
2696 acquire_tkt_send_msg(krb5_context ctx, const char * title,
2697                      const char * ccachename,
2698                      krb5_principal desiredKrb5Principal,
2699                      char * out_ccname, int out_cclen)
2700 {
2701     krb5_error_code     err;
2702     HWND                hNetIdMgr;
2703     HWND                hForeground;
2704     char                *desiredName = 0;
2705     char                *desiredRealm = 0;
2706
2707     /* do we want a specific client principal? */
2708     if (desiredKrb5Principal != NULL) {
2709         err = pkrb5_unparse_name (ctx, desiredKrb5Principal, &desiredName);
2710         if (!err) {
2711             char * p;
2712             for (p = desiredName; *p && *p != '@'; p++);
2713             if ( *p == '@' ) {
2714                 *p = '\0';
2715                 desiredRealm = ++p;
2716             }
2717         }
2718     }
2719
2720     hForeground = GetForegroundWindow();
2721     hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon");
2722     if (hNetIdMgr != NULL) {
2723         HANDLE hMap;
2724         DWORD  tid = GetCurrentThreadId();
2725         char mapname[256];
2726         NETID_DLGINFO *dlginfo;
2727
2728         sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid);
2729
2730         hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
2731                                  0, 4096, mapname);
2732         if (hMap == NULL) {
2733             return -1;
2734         } else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) {
2735             CloseHandle(hMap);
2736             return -1;
2737         }
2738
2739         dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE,
2740                                                  0, 0, 4096, NULL);
2741         if (dlginfo == NULL) {
2742             CloseHandle(hMap);
2743             return -1;
2744         }
2745
2746         memset(dlginfo, 0, sizeof(NETID_DLGINFO));
2747
2748         dlginfo->size = sizeof(NETID_DLGINFO);
2749         dlginfo->dlgtype = NETID_DLGTYPE_TGT;
2750         dlginfo->in.use_defaults = 1;
2751
2752         if (title) {
2753             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2754                                 title, -1,
2755                                 dlginfo->in.title, NETID_TITLE_SZ);
2756         } else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) {
2757             char mytitle[NETID_TITLE_SZ];
2758             sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm);
2759             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2760                                 mytitle, -1,
2761                                 dlginfo->in.title, NETID_TITLE_SZ);
2762         } else {
2763             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2764                                 "Obtain Kerberos TGT", -1,
2765                                 dlginfo->in.title, NETID_TITLE_SZ);
2766         }
2767         if (desiredName)
2768             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2769                                 desiredName, -1,
2770                                 dlginfo->in.username, NETID_USERNAME_SZ);
2771         if (desiredRealm)
2772             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2773                                 desiredRealm, -1,
2774                                 dlginfo->in.realm, NETID_REALM_SZ);
2775         if (ccachename)
2776             MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2777                                 ccachename, -1,
2778                                 dlginfo->in.ccache, NETID_CCACHE_NAME_SZ);
2779         SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid);
2780
2781         if (out_ccname && out_cclen > 0) {
2782             WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, dlginfo->out.ccache, -1,
2783                                 out_ccname, out_cclen, NULL, NULL);
2784         }
2785
2786         UnmapViewOfFile(dlginfo);
2787         CloseHandle(hMap);
2788     } else {
2789         HGLOBAL                 hData;
2790         HWND hLeash = FindWindow("LEASH.0WNDCLASS", NULL);
2791         hLeash = FindFirstChildWindow(hLeash);
2792
2793         /* construct a marshalling of data
2794          *   <title><principal><realm><ccache>
2795          * then send to Leash
2796          */
2797
2798         hData = GlobalAlloc( GHND, 4096 );
2799         SetForegroundWindow(hLeash);
2800         if ( hData && hLeash ) {
2801             char * strs = GlobalLock(hData);
2802             if ( strs ) {
2803                 if (title)
2804                     strcpy(strs, title);
2805                 else if (desiredName)
2806                     sprintf(strs, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm);
2807                 else
2808                     strcpy(strs, "Obtain Kerberos TGT");
2809                 strs += strlen(strs) + 1;
2810                 if ( desiredName ) {
2811                     strcpy(strs, desiredName);
2812                     strs += strlen(strs) + 1;
2813                     if (desiredRealm) {
2814                         strcpy(strs, desiredRealm);
2815                         strs += strlen(strs) + 1;
2816                     }
2817                 } else {
2818                     *strs = 0;
2819                     strs++;
2820                     *strs = 0;
2821                     strs++;
2822                 }
2823
2824                 /* Append the ccache name */
2825                 if (ccachename)
2826                     strcpy(strs, ccachename);
2827                 else
2828                     *strs = 0;
2829                 strs++;
2830
2831                 GlobalUnlock( hData );
2832                 SendMessage(hLeash, 32810, 0, (LPARAM) hData);
2833             }
2834         }
2835         GlobalFree( hData );
2836     }
2837
2838     SetForegroundWindow(hForeground);
2839     if (desiredName != NULL)
2840         pkrb5_free_unparsed_name(ctx, desiredName);
2841
2842     return 0;
2843 }
2844
2845 static void
2846 acquire_tkt_no_princ(krb5_context context, char * ccname, int cclen)
2847 {
2848     TicketList          *list = NULL;
2849     TICKETINFO          ticketinfo;
2850     krb5_context        ctx;
2851     DWORD               dwMsLsaImport = Leash_get_default_mslsa_import();
2852     DWORD               gle;
2853     char ccachename[272]="";
2854     char loginenv[16];
2855     BOOL prompt;
2856
2857     GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
2858     prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
2859
2860     ctx = context;
2861
2862     SetLastError(0);
2863     GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2864     gle = GetLastError();
2865     if ( ((gle == ERROR_ENVVAR_NOT_FOUND) || !ccachename[0]) && context ) {
2866         const char * ccdef = pkrb5_cc_default_name(ctx);
2867         SetEnvironmentVariable("KRB5CCNAME", ccdef ? ccdef : NULL);
2868         GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2869     }
2870
2871     not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
2872     not_an_API_LeashFreeTicketList(&list);
2873
2874     if ( ticketinfo.btickets != GOOD_TICKETS &&
2875          dwMsLsaImport && Leash_importable() ) {
2876         // We have the option of importing tickets from the MSLSA
2877         // but should we?  Do the tickets in the MSLSA cache belong
2878         // to the default realm used by Leash?  Does the default
2879         // ccache name specify a principal name?  Only import if we
2880         // aren't going to break the default identity as specified
2881         // by the user in Network Identity Manager.
2882         int import = 0;
2883         BOOL isCCPrinc;
2884
2885         /* Determine if the default ccachename is principal name.  If so, don't
2886         * import the MSLSA: credentials into it unless the names match.
2887         */
2888         isCCPrinc = (strncmp("API:",ccachename, 4) == 0 && strchr(ccachename, '@'));
2889
2890         if ( dwMsLsaImport == 1 && !isCCPrinc ) { /* always import */
2891             import = 1;
2892         } else if ( dwMsLsaImport ) {             /* import when realms match */
2893             krb5_error_code code;
2894             krb5_ccache mslsa_ccache=NULL;
2895             krb5_principal princ = NULL;
2896             char *mslsa_principal = NULL;
2897             char ms_realm[128] = "", *def_realm = NULL, *r;
2898             size_t i;
2899
2900             if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
2901                 goto cleanup;
2902
2903             if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
2904                 goto cleanup;
2905
2906             for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
2907                 *r = krb5_princ_realm(ctx, princ)->data[i];
2908             }
2909             *r = '\0';
2910
2911             if (code = pkrb5_get_default_realm(ctx, &def_realm))
2912                 goto cleanup;
2913
2914             if (code = pkrb5_unparse_name(ctx, princ, &mslsa_principal))
2915                 goto cleanup;
2916
2917             import = (!isCCPrinc && !strcmp(def_realm, ms_realm)) ||
2918                 (isCCPrinc && !strcmp(&ccachename[4], mslsa_principal));
2919
2920           cleanup:
2921             if (mslsa_principal)
2922                 pkrb5_free_unparsed_name(ctx, mslsa_principal);
2923
2924             if (def_realm)
2925                 pkrb5_free_default_realm(ctx, def_realm);
2926
2927             if (princ)
2928                 pkrb5_free_principal(ctx, princ);
2929
2930             if (mslsa_ccache)
2931                 pkrb5_cc_close(ctx, mslsa_ccache);
2932         }
2933
2934         if ( import ) {
2935             Leash_import();
2936
2937             not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
2938             not_an_API_LeashFreeTicketList(&list);
2939         }
2940     }
2941
2942     if ( prompt && ticketinfo.btickets != GOOD_TICKETS ) {
2943         acquire_tkt_send_msg(ctx, NULL, ccachename, NULL, ccname, cclen);
2944         /*
2945          * If the ticket manager returned an alternative credential cache
2946          * remember it as the default for this process.
2947          */
2948         if ( ccname && ccname[0] && strcmp(ccachename,ccname) ) {
2949             SetEnvironmentVariable("KRB5CCNAME",ccname);
2950         }
2951
2952     } else if (ccachename[0] && ccname) {
2953         strncpy(ccname, ccachename, cclen);
2954         ccname[cclen-1] = '\0';
2955     }
2956
2957     if ( !context )
2958         pkrb5_free_context(ctx);
2959 }
2960
2961
2962 static void
2963 acquire_tkt_for_princ(krb5_context context, krb5_principal desiredPrincipal,
2964                       char * ccname, int cclen)
2965 {
2966     TicketList          *list = NULL;
2967     TICKETINFO          ticketinfo;
2968     krb5_context        ctx;
2969     DWORD               dwMsLsaImport = Leash_get_default_mslsa_import();
2970     DWORD               gle;
2971     char                ccachename[272]="";
2972     char                loginenv[16];
2973     BOOL                prompt;
2974     char                *name = NULL;
2975
2976     GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
2977     prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
2978
2979     ctx = context;
2980
2981     SetLastError(0);
2982     GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2983     gle = GetLastError();
2984     if ( ((gle == ERROR_ENVVAR_NOT_FOUND) || !ccachename[0]) && context ) {
2985         const char * ccdef = pkrb5_cc_default_name(ctx);
2986         SetEnvironmentVariable("KRB5CCNAME", ccdef ? ccdef : NULL);
2987         GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2988     }
2989
2990     not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
2991     not_an_API_LeashFreeTicketList(&list);
2992
2993     pkrb5_unparse_name(ctx, desiredPrincipal, &name);
2994
2995     if ( ticketinfo.btickets != GOOD_TICKETS &&
2996          dwMsLsaImport && Leash_importable() ) {
2997         // We have the option of importing tickets from the MSLSA
2998         // but should we?  Does the MSLSA principal match the requested
2999         // principal?  If not, there is no benefit to importing.
3000         int import = 0;
3001         krb5_error_code code;
3002         krb5_ccache mslsa_ccache=NULL;
3003         krb5_principal princ = NULL;
3004
3005         if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3006             goto cleanup;
3007
3008         if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3009             goto cleanup;
3010
3011         import = pkrb5_principal_compare(ctx, desiredPrincipal, princ);
3012
3013       cleanup:
3014         if (princ)
3015             pkrb5_free_principal(ctx, princ);
3016
3017         if (mslsa_ccache)
3018             pkrb5_cc_close(ctx, mslsa_ccache);
3019
3020
3021         if ( import ) {
3022             /* Construct a new default ccache name into which the MSLSA:
3023              * credentials can be imported, set the default ccache to that
3024              * ccache, and then only import if that ccache does not already
3025              * contain valid tickets */
3026             sprintf(ccachename, "API:%s", name);
3027
3028             SetEnvironmentVariable("KRB5CCNAME", ccachename);
3029
3030             not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
3031             not_an_API_LeashFreeTicketList(&list);
3032
3033             if (ticketinfo.btickets != GOOD_TICKETS) {
3034                 Leash_import();
3035
3036                 not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
3037                 not_an_API_LeashFreeTicketList(&list);
3038             }
3039         }
3040     }
3041
3042     if (prompt) {
3043         if (ticketinfo.btickets != GOOD_TICKETS || strcmp(name,ticketinfo.principal)) {
3044             acquire_tkt_send_msg(ctx, NULL, ccachename, desiredPrincipal, ccname, cclen);
3045             /*
3046              * If the ticket manager returned an alternative credential cache
3047              * remember it as the default for this process.
3048              */
3049             if ( ccname && ccname[0] && strcmp(ccachename,ccname) ) {
3050                 SetEnvironmentVariable("KRB5CCNAME",ccname);
3051             }
3052         } else if (ccachename[0] && ccname) {
3053             strncpy(ccname, ccachename, cclen);
3054             ccname[cclen-1] = '\0';
3055         }
3056     }
3057
3058     if (name)
3059         pkrb5_free_unparsed_name(ctx, name);
3060
3061     if ( !context )
3062         pkrb5_free_context(ctx);
3063 }
3064
3065
3066 static int
3067 leash_int_get_princ_expiration_time(krb5_context ctx, krb5_ccache cc,
3068                                     krb5_principal desiredPrincipal,
3069                                     krb5_timestamp * pexpiration)
3070 {
3071     krb5_principal principal = 0;
3072     char * princ_name = NULL;
3073     char * desired_name = NULL;
3074     krb5_creds creds;
3075     krb5_error_code code, code2;
3076     krb5_error_code cc_code;
3077     krb5_cc_cursor cur;
3078     krb5_timestamp now, expiration = 0;
3079
3080     int rv = -1;
3081
3082     if (!ctx || !cc || !desiredPrincipal || !pexpiration)
3083         return -1;
3084
3085     code = pkrb5_cc_get_principal(ctx, cc, &principal);
3086     if ( code )
3087         return -1;
3088
3089
3090     code = pkrb5_unparse_name(ctx, desiredPrincipal, &desired_name);
3091     code2 = pkrb5_unparse_name(ctx, principal, &princ_name);
3092
3093     /* compare principal to ident. */
3094     if ( code || !princ_name || code2 || !desired_name ||
3095          strcmp(princ_name, desired_name) ) {
3096         if (princ_name)
3097             pkrb5_free_unparsed_name(ctx, princ_name);
3098         if (desired_name)
3099             pkrb5_free_unparsed_name(ctx, desired_name);
3100         pkrb5_free_principal(ctx, principal);
3101         return -1;
3102     }
3103
3104     pkrb5_free_unparsed_name(ctx, princ_name);
3105     pkrb5_free_unparsed_name(ctx, desired_name);
3106     pkrb5_free_principal(ctx, principal);
3107
3108     code = pkrb5_timeofday(ctx, &now);
3109
3110     if (code)
3111         return -1;
3112
3113     cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
3114
3115     while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
3116         krb5_data * c0 = krb5_princ_name(ctx, creds.server);
3117         krb5_data * c1  = krb5_princ_component(ctx, creds.server, 1);
3118         krb5_data * r = krb5_princ_realm(ctx, creds.server);
3119
3120         if ( c0 && c1 && r && c1->length == r->length &&
3121              !strncmp(c1->data,r->data,r->length) &&
3122              !strncmp("krbtgt",c0->data,c0->length) ) {
3123
3124             /* we have a TGT, check for the expiration time.
3125              * if it is valid and renewable, use the renew time
3126              */
3127
3128             if (!(creds.ticket_flags & TKT_FLG_INVALID) &&
3129                 creds.times.starttime < now && creds.times.endtime > now) {
3130                 expiration = creds.times.endtime;
3131
3132                 if ((creds.ticket_flags & TKT_FLG_RENEWABLE) &&
3133                     (creds.times.renew_till > creds.times.endtime)) {
3134                     expiration = creds.times.renew_till;
3135                 }
3136             }
3137         }
3138     }
3139
3140     if (cc_code == KRB5_CC_END) {
3141         cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
3142         rv = 0;
3143         *pexpiration = expiration;
3144     }
3145
3146     return rv;
3147 }
3148
3149 /* returns 0 on success */
3150 static int
3151 leash_int_find_ccache_for_princ(krb5_context ctx, krb5_principal princ,
3152                                 char * buffer, int * pcbbuf)
3153 {
3154     krb5_ccache         cache = 0;
3155     krb5_error_code     code;
3156     apiCB *             cc_ctx = 0;
3157     struct _infoNC **   pNCi = NULL;
3158     int                 i;
3159     krb5_timestamp      expiration = 0;
3160     krb5_timestamp      best_match_expiration = 0;
3161     char                best_match_ccname[256] = "";
3162     DWORD               dwMsLsaImport = Leash_get_default_mslsa_import();
3163
3164     if (!buffer || !pcbbuf)
3165         return -1;
3166
3167     code = cc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
3168     if (code)
3169         goto _exit;
3170
3171     code = cc_get_NC_info(cc_ctx, &pNCi);
3172     if (code)
3173         goto _exit;
3174
3175     for(i=0; pNCi[i]; i++) {
3176         if (pNCi[i]->vers != CC_CRED_V5)
3177             continue;
3178
3179         code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cache);
3180         if (code)
3181             continue;
3182
3183         /* need a function to check the cache for the identity
3184          * and determine if it has valid tickets.  If it has
3185          * the right identity and valid tickets, store the
3186          * expiration time and the cache name.  If it has the
3187          * right identity but no valid tickets, store the ccache
3188          * name and an expiration time of zero.  if it does not
3189          * have the right identity don't save the name.
3190          *
3191          * Keep searching to find the best cache available.
3192          */
3193
3194         if (!leash_int_get_princ_expiration_time(ctx, cache, princ,
3195                                                  &expiration)) {
3196             if ( expiration > best_match_expiration ) {
3197                 best_match_expiration = expiration;
3198                 strncpy(best_match_ccname, "API:",
3199                               sizeof(best_match_ccname));
3200                 strncat(best_match_ccname, pNCi[i]->name,
3201                          sizeof(best_match_ccname));
3202                 best_match_ccname[sizeof(best_match_ccname)-1] = '\0';
3203                 expiration = 0;
3204             }
3205         }
3206
3207         if(ctx != NULL && cache != NULL)
3208             pkrb5_cc_close(ctx, cache);
3209         cache = 0;
3210     }
3211
3212     if (dwMsLsaImport) {
3213         code = pkrb5_cc_resolve(ctx, "MSLSA:", &cache);
3214         if (code == 0 && cache) {
3215             if (!leash_int_get_princ_expiration_time(ctx, cache, princ,
3216                                                       &expiration)) {
3217                 if ( expiration > best_match_expiration ) {
3218                     best_match_expiration = expiration;
3219                     strcpy(best_match_ccname, "MSLSA:");
3220                     expiration = 0;
3221                 }
3222             }
3223         }
3224     }
3225
3226     if (ctx != NULL && cache != NULL)
3227         pkrb5_cc_close(ctx, cache);
3228
3229     cache = 0;
3230
3231  _exit:
3232     if (pNCi)
3233         cc_free_NC_info(cc_ctx, &pNCi);
3234
3235     if (cc_ctx)
3236         cc_shutdown(&cc_ctx);
3237
3238     if (best_match_ccname[0]) {
3239         strncpy(buffer, best_match_ccname, *pcbbuf);
3240         buffer[*pcbbuf-1]='\0';
3241
3242         *pcbbuf = strlen(buffer) + 1;
3243         return 0;
3244     }
3245
3246     return -1;
3247 }
3248
3249 void FAR
3250 not_an_API_Leash_AcquireInitialTicketsIfNeeded(krb5_context context,
3251                                                krb5_principal desiredKrb5Principal,
3252                                                char * ccname, int cclen)
3253 {
3254     char                *desiredName = 0;
3255     char                *desiredRealm = 0;
3256     TicketList          *list = NULL;
3257     char ccachename[272]="";
3258
3259     if (!desiredKrb5Principal) {
3260         acquire_tkt_no_princ(context, ccname, cclen);
3261     } else {
3262         if (leash_int_find_ccache_for_princ(context, desiredKrb5Principal, ccname, &cclen))
3263             acquire_tkt_for_princ(context, desiredKrb5Principal, ccname, cclen);
3264     }
3265     return;
3266 }