xref: /freebsd/crypto/krb5/src/windows/leashdll/lshfunc.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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*
clean_string(char * s)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
leash_error_message(const char * error,int rcL,int rc5,int rcA,char * result_string,int displayMB)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 *
make_postfix(const char * base,const char * postfix,char ** rcopy)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
make_temp_cache_v5(const char * postfix,krb5_context * pctx)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
Leash_checkpwd(char * principal,char * password)217 Leash_checkpwd(
218     char *principal,
219     char *password
220     )
221 {
222     return Leash_int_checkpwd(principal, password, 0);
223 }
224 
225 long
Leash_int_checkpwd(char * principal,char * password,int displayErrors)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
Leash_changepwd_v5(char * principal,char * password,char * newpassword,char ** error_str)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
Leash_changepwd(char * principal,char * password,char * newpassword,char ** result_string)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
Leash_int_changepwd(char * principal,char * password,char * newpassword,char ** result_string,int displayErrors)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
Leash_kinit(char * principal,char * password,int lifetime)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
Leash_kinit_ex(char * principal,char * password,int lifetime,int forwardable,int proxiable,int renew_life,int addressless,unsigned long publicip)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
Leash_int_kinit_ex(krb5_context ctx,HWND hParent,char * principal,char * password,int lifetime,int forwardable,int proxiable,int renew_life,int addressless,unsigned long publicip,int displayErrors)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
Leash_renew(void)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
GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)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
IsKerberosLogon(VOID)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
IsWindowsVista(void)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
IsProcessUacLimited(void)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 long FAR
Leash_importable(void)690 Leash_importable(void)
691 {
692     /* Import functionality has been removed. */
693     return FALSE;
694 }
695 
696 long FAR
Leash_import(void)697 Leash_import(void)
698 {
699     /* Import functionality has been removed. */
700     return 0;
701 }
702 
703 long
Leash_kdestroy(void)704 Leash_kdestroy(void)
705 {
706     Leash_krb5_kdestroy();
707 
708     return 0;
709 }
710 
Leash_klist(HWND hlist,TICKETINFO FAR * ticketinfo)711 long FAR Leash_klist(HWND hlist, TICKETINFO FAR *ticketinfo)
712 {
713     return(255);
714 }
715 
716 
717 // This function can be used to set the help file that will be
718 // referenced the DLL's PasswordProcDLL function and err_describe
719 // function.  Returns true if the help file has been set to the
720 // argument or the environment variable KERB_HELP. Returns FALSE if
721 // the default helpfile as defined in by HELPFILE in lsh_pwd.h is
722 // used.
Leash_set_help_file(char * szHelpFile)723 BOOL Leash_set_help_file( char *szHelpFile )
724 {
725     char tmpHelpFile[256];
726     BOOL ret = 0;
727 
728     if( szHelpFile == NULL ){
729 	GetEnvironmentVariable("KERB_HELP", tmpHelpFile, sizeof(tmpHelpFile));
730     } else {
731 	strcpy( KRB_HelpFile, szHelpFile );
732 	ret++;
733     }
734 
735     if( !ret && tmpHelpFile[0] ){
736 	strcpy( KRB_HelpFile, tmpHelpFile );
737 	ret++;
738     }
739 
740     if( !ret){
741 	strcpy( KRB_HelpFile, HELPFILE );
742     }
743 
744     return(ret);
745 }
746 
747 
748 
Leash_get_help_file(void)749 LPSTR Leash_get_help_file(void)
750 {
751     return( KRB_HelpFile);
752 }
753 
754 int
Leash_debug(int class,int priority,char * fmt,...)755 Leash_debug(
756     int class,
757     int priority,
758     char* fmt, ...
759     )
760 {
761 
762     return 0;
763 }
764 
765 
766 static int
get_profile_file(LPSTR confname,UINT szConfname)767 get_profile_file(LPSTR confname, UINT szConfname)
768 {
769     char **configFile = NULL;
770     if (hKrb5) {
771         if (pkrb5_get_default_config_files(&configFile) || !configFile[0])
772         {
773             GetWindowsDirectory(confname,szConfname);
774             confname[szConfname-1] = '\0';
775             strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));
776             confname[szConfname-1] = '\0';
777             return FALSE;
778         }
779 
780         *confname = 0;
781 
782         if (configFile)
783         {
784             strncpy(confname, *configFile, szConfname);
785             confname[szConfname-1] = '\0';
786             pkrb5_free_config_files(configFile);
787         }
788     }
789 
790     if (!*confname)
791     {
792         GetWindowsDirectory(confname,szConfname);
793         confname[szConfname-1] = '\0';
794         strncat(confname,"\\KRB5.INI",szConfname-strlen(confname));
795         confname[szConfname-1] = '\0';
796     }
797 
798     return FALSE;
799 }
800 
801 static const char *const conf_yes[] = {
802     "y", "yes", "true", "t", "1", "on",
803     0,
804 };
805 
806 static const char *const conf_no[] = {
807     "n", "no", "false", "nil", "0", "off",
808     0,
809 };
810 
811 int
config_boolean_to_int(const char * s)812 config_boolean_to_int(const char *s)
813 {
814     const char *const *p;
815 
816     for(p=conf_yes; *p; p++) {
817         if (!strcasecmp(*p,s))
818             return 1;
819     }
820 
821     for(p=conf_no; *p; p++) {
822         if (!strcasecmp(*p,s))
823             return 0;
824     }
825 
826     /* Default to "no" */
827     return 0;
828 }
829 
830 /*
831  * Leash_get_default_lifetime:
832  *
833  * This function is used to get the default ticket lifetime for this
834  * process in minutes.  A return value of 0 indicates no setting or
835  * "default" setting obtained.
836  *
837  * Here is where we look in order:
838  *
839  * - LIFETIME environment variable
840  * - HKCU\Software\MIT\Leash,lifetime
841  * - HKLM\Software\MIT\Leash,lifetime
842  * - string resource in the leash DLL
843  */
844 
845 static BOOL
get_DWORD_from_registry(HKEY hBaseKey,char * key,char * value,DWORD * result)846 get_DWORD_from_registry(
847     HKEY hBaseKey,
848     char * key,
849     char * value,
850     DWORD * result
851     )
852 {
853     HKEY hKey;
854     DWORD dwCount;
855     LONG rc;
856 
857     rc = RegOpenKeyEx(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey);
858     if (rc)
859         return FALSE;
860 
861     dwCount = sizeof(DWORD);
862     rc = RegQueryValueEx(hKey, value, 0, 0, (LPBYTE) result, &dwCount);
863     RegCloseKey(hKey);
864 
865     return rc?FALSE:TRUE;
866 }
867 
868 static
869 BOOL
get_default_lifetime_from_registry(HKEY hBaseKey,DWORD * result)870 get_default_lifetime_from_registry(
871     HKEY hBaseKey,
872     DWORD * result
873     )
874 {
875     return get_DWORD_from_registry(hBaseKey,
876                                    LEASH_REGISTRY_KEY_NAME,
877                                    LEASH_REGISTRY_VALUE_LIFETIME,
878                                    result);
879 }
880 
881 DWORD
Leash_reset_default_lifetime()882 Leash_reset_default_lifetime(
883     )
884 {
885     HKEY hKey;
886     LONG rc;
887 
888     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
889     if (rc)
890         return rc;
891 
892     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFETIME);
893     RegCloseKey(hKey);
894 
895     return rc;
896 }
897 
898 DWORD
Leash_set_default_lifetime(DWORD minutes)899 Leash_set_default_lifetime(
900     DWORD minutes
901     )
902 {
903     HKEY hKey;
904     LONG rc;
905 
906     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
907                         0, 0, KEY_WRITE, 0, &hKey, 0);
908     if (rc)
909         return rc;
910 
911     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFETIME, 0, REG_DWORD,
912                        (LPBYTE) &minutes, sizeof(DWORD));
913     RegCloseKey(hKey);
914 
915     return rc;
916 }
917 
918 DWORD
Leash_get_default_lifetime()919 Leash_get_default_lifetime(
920     )
921 {
922     HMODULE hmLeash;
923     char env[32];
924     DWORD result;
925 
926 
927     if (GetEnvironmentVariable("LIFETIME",env,sizeof(env)))
928     {
929         return atoi(env);
930     }
931 
932 
933     if (get_default_lifetime_from_registry(HKEY_CURRENT_USER, &result) ||
934         get_default_lifetime_from_registry(HKEY_LOCAL_MACHINE, &result))
935     {
936 	return result;
937     }
938 
939     if ( hKrb5 ) {
940         CHAR confname[MAX_PATH];
941 
942         if (!get_profile_file(confname, sizeof(confname)))
943         {
944             profile_t profile;
945             const char *filenames[2];
946             long retval;
947 
948             filenames[0] = confname;
949             filenames[1] = NULL;
950             if (!pprofile_init(filenames, &profile)) {
951                 char * value = NULL;
952 
953                 retval = pprofile_get_string(profile, "libdefaults", "ticket_lifetime", NULL, NULL, &value);
954                 if (retval == 0 && value) {
955                     krb5_deltat d;
956 
957 		    retval = pkrb5_string_to_deltat(value, &d);
958 
959                     if (retval == KRB5_DELTAT_BADFORMAT) {
960                         /* Historically some sites use relations of
961                            the form 'ticket_lifetime = 24000' where
962                            the unit is left out but is assumed to be
963                            seconds. Then there are other sites which
964                            use the form 'ticket_lifetime = 600' where
965                            the unit is assumed to be minutes.  While
966                            these are technically wrong (a unit needs
967                            to be specified), we try to accommodate for
968                            this using the safe assumption that the
969                            unit is seconds and tack an 's' to the end
970                            and see if that works. */
971 
972 			/* Of course, Leash is one of the platforms
973 			   that historically assumed no units and minutes
974 			   so this change is going to break some people
975 			   but its better to be consistent. */
976                         size_t cch;
977                         char buf[256];
978 
979 			do {
980 			    cch = strlen(value) + 2; /* NUL and new 's' */
981 			    if (cch > sizeof(buf))
982 				break;
983 
984 			    strcpy(buf, value);
985 			    strcat(buf, "s");
986 
987 			    retval = pkrb5_string_to_deltat(buf, &d);
988 
989 			    if (retval == 0) {
990 				result = d / 60;
991 			    }
992 			} while(0);
993                     } else if (retval == 0) {
994                         result = d / 60;
995                     }
996 
997                     pprofile_release_string(value);
998                 }
999                 pprofile_release(profile);
1000 		/* value has been released but we can still use a check for
1001 		 * non-NULL to see if we were able to read a value.
1002 		 */
1003 		if (retval == 0 && value)
1004 		    return result;
1005             }
1006         }
1007     }
1008 
1009     hmLeash = GetModuleHandle(LEASH_DLL);
1010     if (hmLeash)
1011     {
1012         char lifetime[80];
1013         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_LIFE,
1014                        lifetime, sizeof(lifetime)))
1015         {
1016             lifetime[sizeof(lifetime) - 1] = 0;
1017             return atoi(lifetime);
1018         }
1019     }
1020     return 0;
1021 }
1022 
1023 static
1024 BOOL
get_default_renew_till_from_registry(HKEY hBaseKey,DWORD * result)1025 get_default_renew_till_from_registry(
1026     HKEY hBaseKey,
1027     DWORD * result
1028     )
1029 {
1030     return get_DWORD_from_registry(hBaseKey,
1031                                    LEASH_REGISTRY_KEY_NAME,
1032                                    LEASH_REGISTRY_VALUE_RENEW_TILL,
1033                                    result);
1034 }
1035 
1036 DWORD
Leash_reset_default_renew_till()1037 Leash_reset_default_renew_till(
1038     )
1039 {
1040     HKEY hKey;
1041     LONG rc;
1042 
1043     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1044     if (rc)
1045         return rc;
1046 
1047     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL);
1048     RegCloseKey(hKey);
1049 
1050     return rc;
1051 }
1052 
1053 DWORD
Leash_set_default_renew_till(DWORD minutes)1054 Leash_set_default_renew_till(
1055     DWORD minutes
1056     )
1057 {
1058     HKEY hKey;
1059     LONG rc;
1060 
1061     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1062                         0, 0, KEY_WRITE, 0, &hKey, 0);
1063     if (rc)
1064         return rc;
1065 
1066     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_TILL, 0, REG_DWORD,
1067                        (LPBYTE) &minutes, sizeof(DWORD));
1068     RegCloseKey(hKey);
1069 
1070     return rc;
1071 }
1072 
1073 DWORD
Leash_get_default_renew_till()1074 Leash_get_default_renew_till(
1075     )
1076 {
1077     HMODULE hmLeash;
1078     char env[32];
1079     DWORD result;
1080 
1081     if(GetEnvironmentVariable("RENEW_TILL",env,sizeof(env)))
1082     {
1083         return atoi(env);
1084     }
1085 
1086     if (get_default_renew_till_from_registry(HKEY_CURRENT_USER, &result) ||
1087         get_default_renew_till_from_registry(HKEY_LOCAL_MACHINE, &result))
1088     {
1089         return result;
1090     }
1091 
1092     if ( hKrb5 ) {
1093         CHAR confname[MAX_PATH];
1094         if (!get_profile_file(confname, sizeof(confname)))
1095         {
1096             profile_t profile;
1097             const char *filenames[2];
1098             int value=0;
1099             long retval;
1100             filenames[0] = confname;
1101             filenames[1] = NULL;
1102 
1103 	    if (!pprofile_init(filenames, &profile)) {
1104                 char * value = NULL;
1105 
1106 		retval = pprofile_get_string(profile, "libdefaults", "renew_lifetime", NULL, NULL, &value);
1107                 if (retval == 0 && value) {
1108                     krb5_deltat d;
1109 
1110 		    retval = pkrb5_string_to_deltat(value, &d);
1111 		    if (retval == KRB5_DELTAT_BADFORMAT) {
1112                         /* Historically some sites use relations of
1113                            the form 'ticket_lifetime = 24000' where
1114                            the unit is left out but is assumed to be
1115                            seconds. Then there are other sites which
1116                            use the form 'ticket_lifetime = 600' where
1117                            the unit is assumed to be minutes.  While
1118                            these are technically wrong (a unit needs
1119                            to be specified), we try to accommodate for
1120                            this using the safe assumption that the
1121                            unit is seconds and tack an 's' to the end
1122                            and see if that works. */
1123 
1124 			/* Of course, Leash is one of the platforms
1125 			   that historically assumed no units and minutes
1126 			   so this change is going to break some people
1127 			   but its better to be consistent. */
1128                         size_t cch;
1129                         char buf[256];
1130 			do {
1131 			    cch = strlen(value) + 2; /* NUL and new 's' */
1132 			    if (cch > sizeof(buf))
1133 				break;
1134 
1135 			    strcpy(buf, value);
1136 			    strcat(buf, "s");
1137 
1138 			    retval = pkrb5_string_to_deltat(buf, &d);
1139 			    if (retval == 0) {
1140 				result = d / 60;
1141 			    }
1142 			} while(0);
1143                     } else if (retval == 0) {
1144 			result = d / 60;
1145                     }
1146                     pprofile_release_string(value);
1147                 }
1148 		pprofile_release(profile);
1149 		/* value has been released but we can still use a check for
1150 		 * non-NULL to see if we were able to read a value.
1151 		 */
1152 		if (retval == 0 && value)
1153 		    return result;
1154 
1155 		pprofile_release(profile);
1156             }
1157         }
1158     }
1159 
1160     hmLeash = GetModuleHandle(LEASH_DLL);
1161     if (hmLeash)
1162     {
1163         char renew_till[80];
1164         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW_TILL,
1165                        renew_till, sizeof(renew_till)))
1166         {
1167             renew_till[sizeof(renew_till) - 1] = 0;
1168             return atoi(renew_till);
1169         }
1170     }
1171     return 0;
1172 }
1173 
1174 static
1175 BOOL
get_default_forwardable_from_registry(HKEY hBaseKey,DWORD * result)1176 get_default_forwardable_from_registry(
1177     HKEY hBaseKey,
1178     DWORD * result
1179     )
1180 {
1181     return get_DWORD_from_registry(hBaseKey,
1182                                    LEASH_REGISTRY_KEY_NAME,
1183                                    LEASH_REGISTRY_VALUE_FORWARDABLE,
1184                                    result);
1185 }
1186 
1187 DWORD
Leash_reset_default_forwardable()1188 Leash_reset_default_forwardable(
1189     )
1190 {
1191     HKEY hKey;
1192     LONG rc;
1193 
1194     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1195     if (rc)
1196         return rc;
1197 
1198     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE);
1199     RegCloseKey(hKey);
1200 
1201     return rc;
1202 }
1203 
1204 DWORD
Leash_set_default_forwardable(DWORD minutes)1205 Leash_set_default_forwardable(
1206     DWORD minutes
1207     )
1208 {
1209     HKEY hKey;
1210     LONG rc;
1211 
1212     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1213                         0, 0, KEY_WRITE, 0, &hKey, 0);
1214     if (rc)
1215         return rc;
1216 
1217     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_FORWARDABLE, 0, REG_DWORD,
1218                        (LPBYTE) &minutes, sizeof(DWORD));
1219     RegCloseKey(hKey);
1220 
1221     return rc;
1222 }
1223 
1224 DWORD
Leash_get_default_forwardable()1225 Leash_get_default_forwardable(
1226     )
1227 {
1228     HMODULE hmLeash;
1229 
1230     char env[32];
1231     DWORD result;
1232 
1233     if(GetEnvironmentVariable("FORWARDABLE",env,sizeof(env)))
1234     {
1235         return atoi(env);
1236     }
1237 
1238     if (get_default_forwardable_from_registry(HKEY_CURRENT_USER, &result) ||
1239         get_default_forwardable_from_registry(HKEY_LOCAL_MACHINE, &result))
1240     {
1241         return result;
1242     }
1243 
1244     if ( hKrb5 ) {
1245         CHAR confname[MAX_PATH];
1246         if (!get_profile_file(confname, sizeof(confname)))
1247         {
1248             profile_t profile;
1249             const char *filenames[2];
1250             char *value=0;
1251             long retval;
1252             filenames[0] = confname;
1253             filenames[1] = NULL;
1254             if (!pprofile_init(filenames, &profile)) {
1255                 retval = pprofile_get_string(profile, "libdefaults","forwardable", 0, 0, &value);
1256                 if ( value ) {
1257                     result = config_boolean_to_int(value);
1258                     pprofile_release_string(value);
1259                     pprofile_release(profile);
1260                     return result;
1261                 }
1262                 pprofile_release(profile);
1263             }
1264         }
1265     }
1266 
1267     hmLeash = GetModuleHandle(LEASH_DLL);
1268     if (hmLeash)
1269     {
1270         char forwardable[80];
1271         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_FORWARD,
1272                        forwardable, sizeof(forwardable)))
1273         {
1274             forwardable[sizeof(forwardable) - 1] = 0;
1275             return atoi(forwardable);
1276         }
1277     }
1278     return 0;
1279 }
1280 
1281 static
1282 BOOL
get_default_renewable_from_registry(HKEY hBaseKey,DWORD * result)1283 get_default_renewable_from_registry(
1284     HKEY hBaseKey,
1285     DWORD * result
1286     )
1287 {
1288     return get_DWORD_from_registry(hBaseKey,
1289                                    LEASH_REGISTRY_KEY_NAME,
1290                                    LEASH_REGISTRY_VALUE_RENEWABLE,
1291                                    result);
1292 }
1293 
1294 DWORD
Leash_reset_default_renewable()1295 Leash_reset_default_renewable(
1296     )
1297 {
1298     HKEY hKey;
1299     LONG rc;
1300 
1301     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1302     if (rc)
1303         return rc;
1304 
1305     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEWABLE);
1306     RegCloseKey(hKey);
1307 
1308     return rc;
1309 }
1310 
1311 DWORD
Leash_set_default_renewable(DWORD minutes)1312 Leash_set_default_renewable(
1313     DWORD minutes
1314     )
1315 {
1316     HKEY hKey;
1317     LONG rc;
1318 
1319     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1320                         0, 0, KEY_WRITE, 0, &hKey, 0);
1321     if (rc)
1322         return rc;
1323 
1324     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEWABLE, 0, REG_DWORD,
1325                        (LPBYTE) &minutes, sizeof(DWORD));
1326     RegCloseKey(hKey);
1327 
1328     return rc;
1329 }
1330 
1331 DWORD
Leash_get_default_renewable()1332 Leash_get_default_renewable(
1333     )
1334 {
1335     HMODULE hmLeash;
1336     char env[32];
1337     DWORD result;
1338 
1339     if(GetEnvironmentVariable("RENEWABLE",env,sizeof(env)))
1340     {
1341         return atoi(env);
1342     }
1343 
1344     if (get_default_renewable_from_registry(HKEY_CURRENT_USER, &result) ||
1345         get_default_renewable_from_registry(HKEY_LOCAL_MACHINE, &result))
1346     {
1347         return result;
1348     }
1349 
1350     if ( hKrb5 ) {
1351         CHAR confname[MAX_PATH];
1352         if (!get_profile_file(confname, sizeof(confname)))
1353         {
1354             profile_t profile;
1355             const char *filenames[2];
1356             char *value=0;
1357             long retval;
1358             filenames[0] = confname;
1359             filenames[1] = NULL;
1360             if (!pprofile_init(filenames, &profile)) {
1361                 retval = pprofile_get_string(profile, "libdefaults","renewable", 0, 0, &value);
1362                 if ( value ) {
1363                     result = config_boolean_to_int(value);
1364                     pprofile_release_string(value);
1365                     pprofile_release(profile);
1366                     return result;
1367                 }
1368                 pprofile_release(profile);
1369             }
1370         }
1371     }
1372 
1373     hmLeash = GetModuleHandle(LEASH_DLL);
1374     if (hmLeash)
1375     {
1376         char renewable[80];
1377         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_RENEW,
1378                        renewable, sizeof(renewable)))
1379         {
1380             renewable[sizeof(renewable) - 1] = 0;
1381             return atoi(renewable);
1382         }
1383     }
1384     return 0;
1385 }
1386 
1387 static
1388 BOOL
get_default_noaddresses_from_registry(HKEY hBaseKey,DWORD * result)1389 get_default_noaddresses_from_registry(
1390     HKEY hBaseKey,
1391     DWORD * result
1392     )
1393 {
1394     return get_DWORD_from_registry(hBaseKey,
1395                                    LEASH_REGISTRY_KEY_NAME,
1396                                    LEASH_REGISTRY_VALUE_NOADDRESSES,
1397                                    result);
1398 }
1399 
1400 DWORD
Leash_reset_default_noaddresses()1401 Leash_reset_default_noaddresses(
1402     )
1403 {
1404     HKEY hKey;
1405     LONG rc;
1406 
1407     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1408     if (rc)
1409         return rc;
1410 
1411     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES);
1412     RegCloseKey(hKey);
1413 
1414     return rc;
1415 }
1416 
1417 DWORD
Leash_set_default_noaddresses(DWORD minutes)1418 Leash_set_default_noaddresses(
1419     DWORD minutes
1420     )
1421 {
1422     HKEY hKey;
1423     LONG rc;
1424 
1425     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1426                         0, 0, KEY_WRITE, 0, &hKey, 0);
1427     if (rc)
1428         return rc;
1429 
1430     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_NOADDRESSES, 0, REG_DWORD,
1431                        (LPBYTE) &minutes, sizeof(DWORD));
1432     RegCloseKey(hKey);
1433 
1434     return rc;
1435 }
1436 
1437 DWORD
Leash_get_default_noaddresses()1438 Leash_get_default_noaddresses(
1439     )
1440 {
1441     HMODULE hmLeash;
1442     char env[32];
1443     DWORD result;
1444 
1445     if ( hKrb5 ) {
1446         // if the profile file cannot be opened then the value will be true
1447         // if the noaddresses name cannot be found then the value will be true
1448         // if true in the library, we can't alter it by other means
1449         CHAR confname[MAX_PATH];
1450         result = 1;
1451         if (!get_profile_file(confname, sizeof(confname)))
1452         {
1453             profile_t profile;
1454             const char *filenames[2];
1455             char *value=0;
1456             long retval;
1457             filenames[0] = confname;
1458             filenames[1] = NULL;
1459             if (!pprofile_init(filenames, &profile)) {
1460                 retval = pprofile_get_string(profile, "libdefaults","noaddresses", 0, "true", &value);
1461                 if ( value ) {
1462                     result = config_boolean_to_int(value);
1463                     pprofile_release_string(value);
1464                 }
1465                 pprofile_release(profile);
1466             }
1467         }
1468 
1469         if ( result )
1470             return 1;
1471     }
1472 
1473     // The library default is false, check other locations
1474 
1475     if(GetEnvironmentVariable("NOADDRESSES",env,sizeof(env)))
1476     {
1477         return atoi(env);
1478     }
1479 
1480     if (get_default_noaddresses_from_registry(HKEY_CURRENT_USER, &result) ||
1481         get_default_noaddresses_from_registry(HKEY_LOCAL_MACHINE, &result))
1482     {
1483         return result;
1484     }
1485 
1486     hmLeash = GetModuleHandle(LEASH_DLL);
1487     if (hmLeash)
1488     {
1489         char noaddresses[80];
1490         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_NOADDRESS,
1491                        noaddresses, sizeof(noaddresses)))
1492         {
1493             noaddresses[sizeof(noaddresses) - 1] = 0;
1494         }
1495     }
1496     return 1;
1497 }
1498 
1499 static
1500 BOOL
get_default_proxiable_from_registry(HKEY hBaseKey,DWORD * result)1501 get_default_proxiable_from_registry(
1502     HKEY hBaseKey,
1503     DWORD * result
1504     )
1505 {
1506     return get_DWORD_from_registry(hBaseKey,
1507                                    LEASH_REGISTRY_KEY_NAME,
1508                                    LEASH_REGISTRY_VALUE_PROXIABLE,
1509                                    result);
1510 }
1511 
1512 DWORD
Leash_reset_default_proxiable()1513 Leash_reset_default_proxiable(
1514     )
1515 {
1516     HKEY hKey;
1517     LONG rc;
1518 
1519     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1520     if (rc)
1521         return rc;
1522 
1523     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PROXIABLE);
1524     RegCloseKey(hKey);
1525 
1526     return rc;
1527 }
1528 
1529 DWORD
Leash_set_default_proxiable(DWORD minutes)1530 Leash_set_default_proxiable(
1531     DWORD minutes
1532     )
1533 {
1534     HKEY hKey;
1535     LONG rc;
1536 
1537     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1538                         0, 0, KEY_WRITE, 0, &hKey, 0);
1539     if (rc)
1540         return rc;
1541 
1542     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PROXIABLE, 0, REG_DWORD,
1543                        (LPBYTE) &minutes, sizeof(DWORD));
1544     RegCloseKey(hKey);
1545 
1546     return rc;
1547 }
1548 
1549 DWORD
Leash_get_default_proxiable()1550 Leash_get_default_proxiable(
1551     )
1552 {
1553     HMODULE hmLeash;
1554     char env[32];
1555     DWORD result;
1556 
1557     if(GetEnvironmentVariable("PROXIABLE",env,sizeof(env)))
1558     {
1559         return atoi(env);
1560     }
1561 
1562     if (get_default_proxiable_from_registry(HKEY_CURRENT_USER, &result) ||
1563         get_default_proxiable_from_registry(HKEY_LOCAL_MACHINE, &result))
1564     {
1565         return result;
1566     }
1567 
1568     if ( hKrb5 ) {
1569         CHAR confname[MAX_PATH];
1570         if (!get_profile_file(confname, sizeof(confname)))
1571         {
1572             profile_t profile;
1573             const char *filenames[2];
1574             char *value=0;
1575             long retval;
1576             filenames[0] = confname;
1577             filenames[1] = NULL;
1578             if (!pprofile_init(filenames, &profile)) {
1579                 retval = pprofile_get_string(profile, "libdefaults","proxiable", 0, 0, &value);
1580                 if ( value ) {
1581                     result = config_boolean_to_int(value);
1582                     pprofile_release_string(value);
1583                     pprofile_release(profile);
1584                     return result;
1585                 }
1586                 pprofile_release(profile);
1587             }
1588         }
1589     }
1590 
1591     hmLeash = GetModuleHandle(LEASH_DLL);
1592     if (hmLeash)
1593     {
1594         char proxiable[80];
1595         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PROXIABLE,
1596                        proxiable, sizeof(proxiable)))
1597         {
1598             proxiable[sizeof(proxiable) - 1] = 0;
1599             return atoi(proxiable);
1600         }
1601     }
1602     return 0;
1603 }
1604 
1605 static
1606 BOOL
get_default_publicip_from_registry(HKEY hBaseKey,DWORD * result)1607 get_default_publicip_from_registry(
1608     HKEY hBaseKey,
1609     DWORD * result
1610     )
1611 {
1612     return get_DWORD_from_registry(hBaseKey,
1613                                    LEASH_REGISTRY_KEY_NAME,
1614                                    LEASH_REGISTRY_VALUE_PUBLICIP,
1615                                    result);
1616 }
1617 
1618 DWORD
Leash_reset_default_publicip()1619 Leash_reset_default_publicip(
1620     )
1621 {
1622     HKEY hKey;
1623     LONG rc;
1624 
1625     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1626     if (rc)
1627         return rc;
1628 
1629     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PUBLICIP);
1630     RegCloseKey(hKey);
1631 
1632     return rc;
1633 }
1634 
1635 DWORD
Leash_set_default_publicip(DWORD minutes)1636 Leash_set_default_publicip(
1637     DWORD minutes
1638     )
1639 {
1640     HKEY hKey;
1641     LONG rc;
1642 
1643     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1644                         0, 0, KEY_WRITE, 0, &hKey, 0);
1645     if (rc)
1646         return rc;
1647 
1648     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PUBLICIP, 0, REG_DWORD,
1649                        (LPBYTE) &minutes, sizeof(DWORD));
1650     RegCloseKey(hKey);
1651 
1652     return rc;
1653 }
1654 
1655 DWORD
Leash_get_default_publicip()1656 Leash_get_default_publicip(
1657     )
1658 {
1659     HMODULE hmLeash;
1660     char env[32];
1661     DWORD result;
1662 
1663     if(GetEnvironmentVariable("PUBLICIP",env,sizeof(env)))
1664     {
1665         return atoi(env);
1666     }
1667 
1668     if (get_default_publicip_from_registry(HKEY_CURRENT_USER, &result) ||
1669         get_default_publicip_from_registry(HKEY_LOCAL_MACHINE, &result))
1670     {
1671         return result;
1672     }
1673 
1674     hmLeash = GetModuleHandle(LEASH_DLL);
1675     if (hmLeash)
1676     {
1677         char publicip[80];
1678         if (LoadString(hmLeash, LSH_DEFAULT_TICKET_PUBLICIP,
1679                        publicip, sizeof(publicip)))
1680         {
1681             publicip[sizeof(publicip) - 1] = 0;
1682             return atoi(publicip);
1683         }
1684     }
1685     return 0;
1686 }
1687 
1688 static
1689 BOOL
get_hide_kinit_options_from_registry(HKEY hBaseKey,DWORD * result)1690 get_hide_kinit_options_from_registry(
1691     HKEY hBaseKey,
1692     DWORD * result
1693     )
1694 {
1695     return get_DWORD_from_registry(hBaseKey,
1696                                    LEASH_REGISTRY_KEY_NAME,
1697                                    LEASH_REGISTRY_VALUE_KINIT_OPT,
1698                                    result);
1699 }
1700 
1701 DWORD
Leash_reset_hide_kinit_options()1702 Leash_reset_hide_kinit_options(
1703     )
1704 {
1705     HKEY hKey;
1706     LONG rc;
1707 
1708     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1709     if (rc)
1710         return rc;
1711 
1712     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT);
1713     RegCloseKey(hKey);
1714 
1715     return rc;
1716 }
1717 
1718 DWORD
Leash_set_hide_kinit_options(DWORD minutes)1719 Leash_set_hide_kinit_options(
1720     DWORD minutes
1721     )
1722 {
1723     HKEY hKey;
1724     LONG rc;
1725 
1726     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1727                         0, 0, KEY_WRITE, 0, &hKey, 0);
1728     if (rc)
1729         return rc;
1730 
1731     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_KINIT_OPT, 0, REG_DWORD,
1732                        (LPBYTE) &minutes, sizeof(DWORD));
1733     RegCloseKey(hKey);
1734 
1735     return rc;
1736 }
1737 
1738 DWORD
Leash_get_hide_kinit_options()1739 Leash_get_hide_kinit_options(
1740     )
1741 {
1742     HMODULE hmLeash;
1743     DWORD result;
1744 
1745     if (get_hide_kinit_options_from_registry(HKEY_CURRENT_USER, &result) ||
1746         get_hide_kinit_options_from_registry(HKEY_LOCAL_MACHINE, &result))
1747     {
1748         return result;
1749     }
1750 
1751     hmLeash = GetModuleHandle(LEASH_DLL);
1752     if (hmLeash)
1753     {
1754         char hide_kinit_options[80];
1755         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_KINIT_OPT,
1756                        hide_kinit_options, sizeof(hide_kinit_options)))
1757         {
1758             hide_kinit_options[sizeof(hide_kinit_options) - 1] = 0;
1759             return atoi(hide_kinit_options);
1760         }
1761     }
1762     return 0;	/* hide unless otherwise indicated */
1763 }
1764 
1765 
1766 
1767 static
1768 BOOL
get_default_life_min_from_registry(HKEY hBaseKey,DWORD * result)1769 get_default_life_min_from_registry(
1770     HKEY hBaseKey,
1771     DWORD * result
1772     )
1773 {
1774     return get_DWORD_from_registry(hBaseKey,
1775                                    LEASH_REGISTRY_KEY_NAME,
1776                                    LEASH_REGISTRY_VALUE_LIFE_MIN,
1777                                    result);
1778 }
1779 
1780 DWORD
Leash_reset_default_life_min()1781 Leash_reset_default_life_min(
1782     )
1783 {
1784     HKEY hKey;
1785     LONG rc;
1786 
1787     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1788     if (rc)
1789         return rc;
1790 
1791     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN);
1792     RegCloseKey(hKey);
1793 
1794     return rc;
1795 }
1796 
1797 DWORD
Leash_set_default_life_min(DWORD minutes)1798 Leash_set_default_life_min(
1799     DWORD minutes
1800     )
1801 {
1802     HKEY hKey;
1803     LONG rc;
1804 
1805     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1806                         0, 0, KEY_WRITE, 0, &hKey, 0);
1807     if (rc)
1808         return rc;
1809 
1810     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MIN, 0, REG_DWORD,
1811                        (LPBYTE) &minutes, sizeof(DWORD));
1812     RegCloseKey(hKey);
1813 
1814     return rc;
1815 }
1816 
1817 DWORD
Leash_get_default_life_min()1818 Leash_get_default_life_min(
1819     )
1820 {
1821     HMODULE hmLeash;
1822     DWORD result;
1823 
1824     if (get_default_life_min_from_registry(HKEY_CURRENT_USER, &result) ||
1825         get_default_life_min_from_registry(HKEY_LOCAL_MACHINE, &result))
1826     {
1827         return result;
1828     }
1829 
1830     hmLeash = GetModuleHandle(LEASH_DLL);
1831     if (hmLeash)
1832     {
1833         char life_min[80];
1834         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MIN,
1835                        life_min, sizeof(life_min)))
1836         {
1837             life_min[sizeof(life_min) - 1] = 0;
1838             return atoi(life_min);
1839         }
1840     }
1841     return 5; 	/* 5 minutes */
1842 }
1843 
1844 static
1845 BOOL
get_default_life_max_from_registry(HKEY hBaseKey,DWORD * result)1846 get_default_life_max_from_registry(
1847     HKEY hBaseKey,
1848     DWORD * result
1849     )
1850 {
1851     return get_DWORD_from_registry(hBaseKey,
1852                                    LEASH_REGISTRY_KEY_NAME,
1853                                    LEASH_REGISTRY_VALUE_LIFE_MAX,
1854                                    result);
1855 }
1856 
1857 DWORD
Leash_reset_default_life_max()1858 Leash_reset_default_life_max(
1859     )
1860 {
1861     HKEY hKey;
1862     LONG rc;
1863 
1864     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1865     if (rc)
1866         return rc;
1867 
1868     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX);
1869     RegCloseKey(hKey);
1870 
1871     return rc;
1872 }
1873 
1874 DWORD
Leash_set_default_life_max(DWORD minutes)1875 Leash_set_default_life_max(
1876     DWORD minutes
1877     )
1878 {
1879     HKEY hKey;
1880     LONG rc;
1881 
1882     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1883                         0, 0, KEY_WRITE, 0, &hKey, 0);
1884     if (rc)
1885         return rc;
1886 
1887     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_LIFE_MAX, 0, REG_DWORD,
1888                        (LPBYTE) &minutes, sizeof(DWORD));
1889     RegCloseKey(hKey);
1890 
1891     return rc;
1892 }
1893 
1894 DWORD
Leash_get_default_life_max()1895 Leash_get_default_life_max(
1896     )
1897 {
1898     HMODULE hmLeash;
1899     DWORD result;
1900 
1901     if (get_default_life_max_from_registry(HKEY_CURRENT_USER, &result) ||
1902         get_default_life_max_from_registry(HKEY_LOCAL_MACHINE, &result))
1903     {
1904         return result;
1905     }
1906 
1907     hmLeash = GetModuleHandle(LEASH_DLL);
1908     if (hmLeash)
1909     {
1910         char life_max[80];
1911         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_LIFE_MAX,
1912                        life_max, sizeof(life_max)))
1913         {
1914             life_max[sizeof(life_max) - 1] = 0;
1915             return atoi(life_max);
1916         }
1917     }
1918     return 1440;
1919 }
1920 
1921 static
1922 BOOL
get_default_renew_min_from_registry(HKEY hBaseKey,DWORD * result)1923 get_default_renew_min_from_registry(
1924     HKEY hBaseKey,
1925     DWORD * result
1926     )
1927 {
1928     return get_DWORD_from_registry(hBaseKey,
1929                                    LEASH_REGISTRY_KEY_NAME,
1930                                    LEASH_REGISTRY_VALUE_RENEW_MIN,
1931                                    result);
1932 }
1933 
1934 DWORD
Leash_reset_default_renew_min()1935 Leash_reset_default_renew_min(
1936     )
1937 {
1938     HKEY hKey;
1939     LONG rc;
1940 
1941     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
1942     if (rc)
1943         return rc;
1944 
1945     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN);
1946     RegCloseKey(hKey);
1947 
1948     return rc;
1949 }
1950 
1951 DWORD
Leash_set_default_renew_min(DWORD minutes)1952 Leash_set_default_renew_min(
1953     DWORD minutes
1954     )
1955 {
1956     HKEY hKey;
1957     LONG rc;
1958 
1959     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
1960                         0, 0, KEY_WRITE, 0, &hKey, 0);
1961     if (rc)
1962         return rc;
1963 
1964     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MIN, 0, REG_DWORD,
1965                        (LPBYTE) &minutes, sizeof(DWORD));
1966     RegCloseKey(hKey);
1967 
1968     return rc;
1969 }
1970 
1971 DWORD
Leash_get_default_renew_min()1972 Leash_get_default_renew_min(
1973     )
1974 {
1975     HMODULE hmLeash;
1976     DWORD result;
1977 
1978     if (get_default_renew_min_from_registry(HKEY_CURRENT_USER, &result) ||
1979         get_default_renew_min_from_registry(HKEY_LOCAL_MACHINE, &result))
1980     {
1981         return result;
1982     }
1983 
1984     hmLeash = GetModuleHandle(LEASH_DLL);
1985     if (hmLeash)
1986     {
1987         char renew_min[80];
1988         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MIN,
1989                        renew_min, sizeof(renew_min)))
1990         {
1991             renew_min[sizeof(renew_min) - 1] = 0;
1992             return atoi(renew_min);
1993         }
1994     }
1995     return 600;  	/* 10 hours */
1996 }
1997 
1998 static
1999 BOOL
get_default_renew_max_from_registry(HKEY hBaseKey,DWORD * result)2000 get_default_renew_max_from_registry(
2001     HKEY hBaseKey,
2002     DWORD * result
2003     )
2004 {
2005     return get_DWORD_from_registry(hBaseKey,
2006                                    LEASH_REGISTRY_KEY_NAME,
2007                                    LEASH_REGISTRY_VALUE_RENEW_MAX,
2008                                    result);
2009 }
2010 
2011 DWORD
Leash_reset_default_renew_max()2012 Leash_reset_default_renew_max(
2013     )
2014 {
2015     HKEY hKey;
2016     LONG rc;
2017 
2018     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2019     if (rc)
2020         return rc;
2021 
2022     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX);
2023     RegCloseKey(hKey);
2024 
2025     return rc;
2026 }
2027 
2028 DWORD
Leash_set_default_renew_max(DWORD minutes)2029 Leash_set_default_renew_max(
2030     DWORD minutes
2031     )
2032 {
2033     HKEY hKey;
2034     LONG rc;
2035 
2036     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2037                         0, 0, KEY_WRITE, 0, &hKey, 0);
2038     if (rc)
2039         return rc;
2040 
2041     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_RENEW_MAX, 0, REG_DWORD,
2042                        (LPBYTE) &minutes, sizeof(DWORD));
2043     RegCloseKey(hKey);
2044 
2045     return rc;
2046 }
2047 
2048 DWORD
Leash_get_default_renew_max()2049 Leash_get_default_renew_max(
2050     )
2051 {
2052     HMODULE hmLeash;
2053     DWORD result;
2054 
2055     if (get_default_renew_max_from_registry(HKEY_CURRENT_USER, &result) ||
2056         get_default_renew_max_from_registry(HKEY_LOCAL_MACHINE, &result))
2057     {
2058         return result;
2059     }
2060 
2061     hmLeash = GetModuleHandle(LEASH_DLL);
2062     if (hmLeash)
2063     {
2064         char renew_max[80];
2065         if (LoadString(hmLeash, LSH_DEFAULT_DIALOG_RENEW_MAX,
2066                        renew_max, sizeof(renew_max)))
2067         {
2068             renew_max[sizeof(renew_max) - 1] = 0;
2069             return atoi(renew_max);
2070         }
2071     }
2072     return 60 * 24 * 30;
2073 }
2074 
2075 static
2076 BOOL
get_default_uppercaserealm_from_registry(HKEY hBaseKey,DWORD * result)2077 get_default_uppercaserealm_from_registry(
2078     HKEY hBaseKey,
2079     DWORD * result
2080     )
2081 {
2082     return get_DWORD_from_registry(hBaseKey,
2083                                    LEASH_SETTINGS_REGISTRY_KEY_NAME,
2084                                    LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM,
2085                                    result);
2086 }
2087 
2088 DWORD
Leash_reset_default_uppercaserealm()2089 Leash_reset_default_uppercaserealm(
2090     )
2091 {
2092     HKEY hKey;
2093     LONG rc;
2094 
2095     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2096     if (rc)
2097         return rc;
2098 
2099     rc = RegDeleteValue(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM);
2100     RegCloseKey(hKey);
2101 
2102     return rc;
2103 }
2104 
2105 DWORD
Leash_set_default_uppercaserealm(DWORD onoff)2106 Leash_set_default_uppercaserealm(
2107     DWORD onoff
2108     )
2109 {
2110     HKEY hKey;
2111     LONG rc;
2112 
2113     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_SETTINGS_REGISTRY_KEY_NAME, 0,
2114                         0, 0, KEY_WRITE, 0, &hKey, 0);
2115     if (rc)
2116         return rc;
2117 
2118     rc = RegSetValueEx(hKey, LEASH_SETTINGS_REGISTRY_VALUE_UPPERCASEREALM, 0, REG_DWORD,
2119                        (LPBYTE) &onoff, sizeof(DWORD));
2120     RegCloseKey(hKey);
2121 
2122     return rc;
2123 }
2124 
2125 DWORD
Leash_get_default_uppercaserealm()2126 Leash_get_default_uppercaserealm(
2127     )
2128 {
2129     HMODULE hmLeash;
2130     DWORD result;
2131 
2132     if (get_default_uppercaserealm_from_registry(HKEY_CURRENT_USER, &result) ||
2133         get_default_uppercaserealm_from_registry(HKEY_LOCAL_MACHINE, &result))
2134     {
2135         return result;
2136     }
2137 
2138     hmLeash = GetModuleHandle(LEASH_DLL);
2139     if (hmLeash)
2140     {
2141         char uppercaserealm[80];
2142         if (LoadString(hmLeash, LSH_DEFAULT_UPPERCASEREALM,
2143                        uppercaserealm, sizeof(uppercaserealm)))
2144         {
2145             uppercaserealm[sizeof(uppercaserealm) - 1] = 0;
2146             return atoi(uppercaserealm);
2147         }
2148     }
2149     return 1;
2150 }
2151 
2152 DWORD
Leash_reset_default_mslsa_import()2153 Leash_reset_default_mslsa_import(
2154     )
2155 {
2156     return ERROR_INVALID_FUNCTION;
2157 }
2158 
2159 DWORD
Leash_set_default_mslsa_import(DWORD onoffmatch)2160 Leash_set_default_mslsa_import(
2161     DWORD onoffmatch
2162     )
2163 {
2164     return ERROR_INVALID_FUNCTION;
2165 }
2166 
2167 DWORD
Leash_get_default_mslsa_import()2168 Leash_get_default_mslsa_import(
2169     )
2170 {
2171     return 0;
2172 }
2173 
2174 
2175 static
2176 BOOL
get_default_preserve_kinit_settings_from_registry(HKEY hBaseKey,DWORD * result)2177 get_default_preserve_kinit_settings_from_registry(
2178     HKEY hBaseKey,
2179     DWORD * result
2180     )
2181 {
2182     return get_DWORD_from_registry(hBaseKey,
2183                                    LEASH_REGISTRY_KEY_NAME,
2184                                    LEASH_REGISTRY_VALUE_PRESERVE_KINIT,
2185                                    result);
2186 }
2187 
2188 DWORD
Leash_reset_default_preserve_kinit_settings()2189 Leash_reset_default_preserve_kinit_settings(
2190     )
2191 {
2192     HKEY hKey;
2193     LONG rc;
2194 
2195     rc = RegOpenKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0, KEY_WRITE, &hKey);
2196     if (rc)
2197         return rc;
2198 
2199     rc = RegDeleteValue(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT);
2200     RegCloseKey(hKey);
2201 
2202     return rc;
2203 }
2204 
2205 DWORD
Leash_set_default_preserve_kinit_settings(DWORD onoff)2206 Leash_set_default_preserve_kinit_settings(
2207     DWORD onoff
2208     )
2209 {
2210     HKEY hKey;
2211     LONG rc;
2212 
2213     rc = RegCreateKeyEx(HKEY_CURRENT_USER, LEASH_REGISTRY_KEY_NAME, 0,
2214                         0, 0, KEY_WRITE, 0, &hKey, 0);
2215     if (rc)
2216         return rc;
2217 
2218     rc = RegSetValueEx(hKey, LEASH_REGISTRY_VALUE_PRESERVE_KINIT, 0, REG_DWORD,
2219                        (LPBYTE) &onoff, sizeof(DWORD));
2220     RegCloseKey(hKey);
2221 
2222     return rc;
2223 }
2224 
2225 DWORD
Leash_get_default_preserve_kinit_settings()2226 Leash_get_default_preserve_kinit_settings(
2227     )
2228 {
2229     HMODULE hmLeash;
2230     DWORD result;
2231 
2232     if (get_default_preserve_kinit_settings_from_registry(HKEY_CURRENT_USER, &result) ||
2233         get_default_preserve_kinit_settings_from_registry(HKEY_LOCAL_MACHINE, &result))
2234     {
2235         return result;
2236     }
2237 
2238     hmLeash = GetModuleHandle(LEASH_DLL);
2239     if (hmLeash)
2240     {
2241         char preserve_kinit_settings[80];
2242         if (LoadString(hmLeash, LSH_DEFAULT_PRESERVE_KINIT,
2243                        preserve_kinit_settings, sizeof(preserve_kinit_settings)))
2244         {
2245             preserve_kinit_settings[sizeof(preserve_kinit_settings) - 1] = 0;
2246             return atoi(preserve_kinit_settings);
2247         }
2248     }
2249     return 1;
2250 }
2251 
2252 void
Leash_reset_defaults(void)2253 Leash_reset_defaults(void)
2254 {
2255     Leash_reset_default_lifetime();
2256     Leash_reset_default_renew_till();
2257     Leash_reset_default_renewable();
2258     Leash_reset_default_forwardable();
2259     Leash_reset_default_noaddresses();
2260     Leash_reset_default_proxiable();
2261     Leash_reset_default_publicip();
2262     Leash_reset_hide_kinit_options();
2263     Leash_reset_default_life_min();
2264     Leash_reset_default_life_max();
2265     Leash_reset_default_renew_min();
2266     Leash_reset_default_renew_max();
2267     Leash_reset_default_uppercaserealm();
2268     Leash_reset_default_preserve_kinit_settings();
2269 }
2270 
2271 static void
acquire_tkt_send_msg_leash(const char * title,const char * ccachename,const char * name,const char * realm)2272 acquire_tkt_send_msg_leash(const char *title,
2273                            const char *ccachename,
2274                            const char *name,
2275                            const char *realm)
2276 {
2277     DWORD leashProcessId = 0;
2278     DWORD bufsize = 4096;
2279     DWORD step;
2280     HANDLE hLeashProcess = NULL;
2281     HANDLE hMapFile = NULL;
2282     HANDLE hTarget = NULL;
2283     HWND hLeashWnd = FindWindow("LEASH.0WNDCLASS", NULL);
2284     char *strs;
2285     void *view;
2286     if (!hLeashWnd)
2287         // no leash window
2288         return;
2289 
2290     GetWindowThreadProcessId(hLeashWnd, &leashProcessId);
2291     hLeashProcess = OpenProcess(PROCESS_DUP_HANDLE,
2292                                 FALSE,
2293                                 leashProcessId);
2294     if (!hLeashProcess)
2295         // can't get process handle; use GetLastError() for more info
2296         return;
2297 
2298     hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file
2299                                  NULL,                 // default security
2300                                  PAGE_READWRITE,       // read/write access
2301                                  0,                    // max size (high 32)
2302                                  bufsize,              // max size (low 32)
2303                                  NULL);                // name
2304     if (!hMapFile) {
2305         // GetLastError() for more info
2306         CloseHandle(hLeashProcess);
2307         return;
2308     }
2309 
2310     SetForegroundWindow(hLeashWnd);
2311 
2312     view = MapViewOfFile(hMapFile,
2313                          FILE_MAP_ALL_ACCESS,
2314                          0,
2315                          0,
2316                          bufsize);
2317     if (view != NULL) {
2318         /* construct a marshalling of data
2319          *   <title><principal><realm><ccache>
2320          * then send to Leash
2321          */
2322         strs = (char *)view;
2323         // first reserve space for three more NULLs (4 strings total)
2324         bufsize -= 3;
2325         // Dialog title
2326         if (title != NULL)
2327             strcpy_s(strs, bufsize, title);
2328         else if (name != NULL && realm != NULL)
2329             sprintf_s(strs, bufsize,
2330                       "MIT Kerberos: Get Ticket for %s@%s", name, realm);
2331         else
2332             strcpy_s(strs, bufsize, "MIT Kerberos: Get Ticket");
2333         step = strlen(strs);
2334         strs += step + 1;
2335         bufsize -= step;
2336         // name and realm
2337         if (name != NULL) {
2338             strcpy_s(strs, bufsize, name);
2339             step = strlen(strs);
2340             strs += step + 1;
2341             bufsize -= step;
2342             if (realm != NULL) {
2343                 strcpy_s(strs, bufsize, realm);
2344                 step = strlen(strs);
2345                 strs += step + 1;
2346                 bufsize -= step;
2347             } else {
2348                 *strs = 0;
2349                 strs++;
2350             }
2351         } else {
2352             *strs = 0;
2353             strs++;
2354             *strs = 0;
2355             strs++;
2356         }
2357 
2358         /* Append the ccache name */
2359         if (ccachename != NULL)
2360             strcpy_s(strs, bufsize, ccachename);
2361         else
2362             *strs = 0;
2363 
2364         UnmapViewOfFile(view);
2365     }
2366     // Duplicate the file mapping handle to one leash can use
2367     if (DuplicateHandle(GetCurrentProcess(),
2368                         hMapFile,
2369                         hLeashProcess,
2370                         &hTarget,
2371                         PAGE_READWRITE,
2372                         FALSE,
2373                         DUPLICATE_SAME_ACCESS |
2374                         DUPLICATE_CLOSE_SOURCE)) {
2375         /* 32809 = ID_OBTAIN_TGT_WITH_LPARAM in src/windows/leash/resource.h */
2376         SendMessage(hLeashWnd, 32809, 0, (LPARAM) hTarget);
2377     } else {
2378         // GetLastError()
2379     }
2380 }
2381 
2382 static int
acquire_tkt_send_msg(krb5_context ctx,const char * title,const char * ccachename,krb5_principal desiredKrb5Principal,char * out_ccname,int out_cclen)2383 acquire_tkt_send_msg(krb5_context ctx, const char * title,
2384 		     const char * ccachename,
2385 		     krb5_principal desiredKrb5Principal,
2386 		     char * out_ccname, int out_cclen)
2387 {
2388     krb5_error_code 	err;
2389     HWND    	        hNetIdMgr;
2390     HWND    		hForeground;
2391     char		*desiredName = 0;
2392     char                *desiredRealm = 0;
2393 
2394     /* do we want a specific client principal? */
2395     if (desiredKrb5Principal != NULL) {
2396 	err = pkrb5_unparse_name (ctx, desiredKrb5Principal, &desiredName);
2397 	if (!err) {
2398 	    char * p;
2399 	    for (p = desiredName; *p && *p != '@'; p++);
2400 	    if ( *p == '@' ) {
2401 		*p = '\0';
2402 		desiredRealm = ++p;
2403 	    }
2404 	}
2405     }
2406 
2407     hForeground = GetForegroundWindow();
2408     hNetIdMgr = FindWindow("IDMgrRequestDaemonCls", "IDMgrRequestDaemon");
2409     if (hNetIdMgr != NULL) {
2410 	HANDLE hMap;
2411 	DWORD  tid = GetCurrentThreadId();
2412 	char mapname[256];
2413 	NETID_DLGINFO *dlginfo;
2414 
2415 	sprintf(mapname,"Local\\NetIDMgr_DlgInfo_%lu",tid);
2416 
2417 	hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
2418 				 0, 4096, mapname);
2419 	if (hMap == NULL) {
2420 	    return -1;
2421 	} else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS) {
2422 	    CloseHandle(hMap);
2423 	    return -1;
2424 	}
2425 
2426 	dlginfo = (NETID_DLGINFO *)MapViewOfFileEx(hMap, FILE_MAP_READ|FILE_MAP_WRITE,
2427 						 0, 0, 4096, NULL);
2428 	if (dlginfo == NULL) {
2429 	    CloseHandle(hMap);
2430 	    return -1;
2431 	}
2432 
2433 	memset(dlginfo, 0, sizeof(NETID_DLGINFO));
2434 
2435 	dlginfo->size = sizeof(NETID_DLGINFO);
2436 	dlginfo->dlgtype = NETID_DLGTYPE_TGT;
2437 	dlginfo->in.use_defaults = 1;
2438 
2439 	if (title) {
2440 	    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2441 				title, -1,
2442 				dlginfo->in.title, NETID_TITLE_SZ);
2443 	} else if (desiredName && (strlen(desiredName) + strlen(desiredRealm) + 32 < NETID_TITLE_SZ)) {
2444 	    char mytitle[NETID_TITLE_SZ];
2445 	    sprintf(mytitle, "Obtain Kerberos TGT for %s@%s",desiredName,desiredRealm);
2446 	    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2447 				mytitle, -1,
2448 				dlginfo->in.title, NETID_TITLE_SZ);
2449 	} else {
2450 	    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2451 				"Obtain Kerberos TGT", -1,
2452 				dlginfo->in.title, NETID_TITLE_SZ);
2453 	}
2454 	if (desiredName)
2455 	    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2456 				desiredName, -1,
2457 				dlginfo->in.username, NETID_USERNAME_SZ);
2458 	if (desiredRealm)
2459 	    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2460 				desiredRealm, -1,
2461 				dlginfo->in.realm, NETID_REALM_SZ);
2462 	if (ccachename)
2463 	    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS,
2464 				ccachename, -1,
2465 				dlginfo->in.ccache, NETID_CCACHE_NAME_SZ);
2466 	SendMessage(hNetIdMgr, 32810, 0, (LPARAM) tid);
2467 
2468 	if (out_ccname && out_cclen > 0) {
2469 	    WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, dlginfo->out.ccache, -1,
2470 				out_ccname, out_cclen, NULL, NULL);
2471 	}
2472 
2473 	UnmapViewOfFile(dlginfo);
2474 	CloseHandle(hMap);
2475     } else {
2476         acquire_tkt_send_msg_leash(title,
2477                                    ccachename, desiredName, desiredRealm);
2478     }
2479 
2480     SetForegroundWindow(hForeground);
2481     if (desiredName != NULL)
2482 	pkrb5_free_unparsed_name(ctx, desiredName);
2483 
2484     return 0;
2485 }
2486 
cc_have_tickets(krb5_context ctx,krb5_ccache cache)2487 static BOOL cc_have_tickets(krb5_context ctx, krb5_ccache cache)
2488 {
2489     krb5_cc_cursor cur = NULL;
2490     krb5_creds creds;
2491     krb5_flags flags;
2492     krb5_error_code code;
2493     BOOL have_tickets = FALSE;
2494 
2495     // Don't need the actual ticket.
2496     flags = KRB5_TC_NOTICKET;
2497     code = pkrb5_cc_set_flags(ctx, cache, flags);
2498     if (code)
2499         goto cleanup;
2500     code = pkrb5_cc_start_seq_get(ctx, cache, &cur);
2501     if (code)
2502         goto cleanup;
2503 
2504     _tzset();
2505     while (!(code = pkrb5_cc_next_cred(ctx, cache, &cur, &creds))) {
2506         if ((!pkrb5_is_config_principal(ctx, creds.server)) &&
2507             ((time_t)(DWORD)creds.times.endtime - time(0) > 0))
2508             have_tickets = TRUE;
2509 
2510         pkrb5_free_cred_contents(ctx, &creds);
2511     }
2512     if (code == KRB5_CC_END) {
2513         code = pkrb5_cc_end_seq_get(ctx, cache, &cur);
2514         if (code)
2515             goto cleanup;
2516         flags = 0;
2517         code = pkrb5_cc_set_flags(ctx, cache, flags);
2518         if (code)
2519             goto cleanup;
2520     }
2521 cleanup:
2522     return have_tickets;
2523 }
2524 
2525 static BOOL
cc_have_tickets_for_princ(krb5_context ctx,krb5_ccache cache,krb5_principal princ)2526 cc_have_tickets_for_princ(krb5_context ctx,
2527                           krb5_ccache cache,
2528                           krb5_principal princ)
2529 {
2530     krb5_error_code code;
2531     krb5_principal cc_princ = NULL;
2532     BOOL have_tickets = FALSE;
2533     code = pkrb5_cc_get_principal(ctx, cache, &cc_princ);
2534     if (code)
2535         goto cleanup;
2536 
2537     if (pkrb5_principal_compare(ctx, princ, cc_princ))
2538         have_tickets = cc_have_tickets(ctx, cache);
2539 
2540 cleanup:
2541     if (cc_princ != NULL)
2542         pkrb5_free_principal(ctx, cc_princ);
2543     return have_tickets;
2544 }
2545 
cc_default_have_tickets(krb5_context ctx)2546 static BOOL cc_default_have_tickets(krb5_context ctx)
2547 {
2548     krb5_ccache cache = NULL;
2549     BOOL have_tickets = FALSE;
2550     if (pkrb5_cc_default(ctx, &cache) == 0)
2551         have_tickets = cc_have_tickets(ctx, cache);
2552     if (cache != NULL)
2553         pkrb5_cc_close(ctx, cache);
2554     return have_tickets;
2555 }
2556 
2557 static BOOL
cccol_have_tickets_for_princ(krb5_context ctx,krb5_principal princ,char * ccname,int cclen)2558 cccol_have_tickets_for_princ(krb5_context ctx,
2559                              krb5_principal princ,
2560                              char *ccname,
2561                              int cclen)
2562 {
2563     krb5_error_code code;
2564     krb5_ccache cache;
2565     krb5_cccol_cursor cursor;
2566     BOOL have_tickets = FALSE;
2567     char *ccfullname;
2568 
2569     code = pkrb5_cccol_cursor_new(ctx, &cursor);
2570     if (code)
2571         goto cleanup;
2572 
2573     while (!have_tickets &&
2574            !(code = pkrb5_cccol_cursor_next(ctx, cursor, &cache)) &&
2575            cache != NULL) {
2576         if (cc_have_tickets_for_princ(ctx, cache, princ)) {
2577             if (pkrb5_cc_get_full_name(ctx, cache, &ccfullname)==0) {
2578                 strcpy_s(ccname, cclen, ccfullname);
2579                 pkrb5_free_string(ctx, ccfullname);
2580                 have_tickets = TRUE;
2581             }
2582         }
2583         pkrb5_cc_close(ctx, cache);
2584     }
2585     pkrb5_cccol_cursor_free(ctx, &cursor);
2586 cleanup:
2587 
2588     return have_tickets;
2589 }
2590 
2591 static void
acquire_tkt_no_princ(krb5_context context,char * ccname,int cclen)2592 acquire_tkt_no_princ(krb5_context context, char * ccname, int cclen)
2593 {
2594     krb5_context        ctx;
2595     DWORD		gle;
2596     char ccachename[272]="";
2597     char loginenv[16];
2598     BOOL prompt;
2599     BOOL haveTickets;
2600 
2601     GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
2602     prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
2603 
2604     ctx = context;
2605 
2606     SetLastError(0);
2607     GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2608     gle = GetLastError();
2609     if ( ((gle == ERROR_ENVVAR_NOT_FOUND) || !ccachename[0]) && context ) {
2610         const char * ccdef = pkrb5_cc_default_name(ctx);
2611 	SetEnvironmentVariable("KRB5CCNAME", ccdef ? ccdef : NULL);
2612 	GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2613     }
2614 
2615     haveTickets = cc_default_have_tickets(ctx);
2616 
2617     if ( prompt && !haveTickets ) {
2618 	acquire_tkt_send_msg(ctx, NULL, ccachename, NULL, ccname, cclen);
2619         /*
2620          * If the ticket manager returned an alternative credential cache
2621          * remember it as the default for this process.
2622          */
2623         if ( ccname && ccname[0] && strcmp(ccachename,ccname) ) {
2624             SetEnvironmentVariable("KRB5CCNAME",ccname);
2625         }
2626 
2627     } else if (ccachename[0] && ccname) {
2628 	strncpy(ccname, ccachename, cclen);
2629 	ccname[cclen-1] = '\0';
2630     }
2631     if ( !context )
2632         pkrb5_free_context(ctx);
2633 }
2634 
2635 
2636 static void
acquire_tkt_for_princ(krb5_context ctx,krb5_principal desiredPrincipal,char * ccname,int cclen)2637 acquire_tkt_for_princ(krb5_context ctx, krb5_principal desiredPrincipal,
2638 		      char * ccname, int cclen)
2639 {
2640     DWORD		gle;
2641     char 		ccachename[272]="";
2642     char 		loginenv[16];
2643     BOOL 		prompt;
2644 
2645     GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
2646     prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
2647 
2648     SetLastError(0);
2649     GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2650     gle = GetLastError();
2651     if ((gle == ERROR_ENVVAR_NOT_FOUND || !ccachename[0]) && ctx != NULL) {
2652         const char * ccdef = pkrb5_cc_default_name(ctx);
2653 	SetEnvironmentVariable("KRB5CCNAME", ccdef ? ccdef : NULL);
2654 	GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename));
2655     }
2656     if (!cccol_have_tickets_for_princ(ctx, desiredPrincipal, ccname, cclen)) {
2657         if (prompt) {
2658 	        acquire_tkt_send_msg(ctx, NULL,
2659                                  ccachename, desiredPrincipal, ccname, cclen);
2660             /*
2661              * If the ticket manager returned an alternative credential cache
2662              * remember it as the default for this process.
2663              */
2664             if (ccname != NULL && ccname[0] &&
2665                 strcmp(ccachename, ccname)) {
2666                 SetEnvironmentVariable("KRB5CCNAME",ccname);
2667             }
2668         }
2669 	}
2670 }
2671 
2672 
2673 void FAR
not_an_API_Leash_AcquireInitialTicketsIfNeeded(krb5_context context,krb5_principal desiredKrb5Principal,char * ccname,int cclen)2674 not_an_API_Leash_AcquireInitialTicketsIfNeeded(krb5_context context,
2675 					       krb5_principal desiredKrb5Principal,
2676 					       char * ccname, int cclen)
2677 {
2678     if (!desiredKrb5Principal) {
2679 	acquire_tkt_no_princ(context, ccname, cclen);
2680     } else {
2681         acquire_tkt_for_princ(context, desiredKrb5Principal, ccname, cclen);
2682     }
2683     return;
2684 }
2685