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