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