2 * Copyright (c) 2004 Massachusetts Institute of Technology
\r
4 * Permission is hereby granted, free of charge, to any person
\r
5 * obtaining a copy of this software and associated documentation
\r
6 * files (the "Software"), to deal in the Software without
\r
7 * restriction, including without limitation the rights to use, copy,
\r
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
\r
9 * of the Software, and to permit persons to whom the Software is
\r
10 * furnished to do so, subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be
\r
13 * included in all copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
27 #include <windows.h>
\r
29 #include <sys/types.h>
\r
30 #include <winsock.h>
\r
31 #include "leashdll.h"
\r
32 #include <KerberosIV/krb.h>
\r
36 #include <leashwin.h>
\r
37 #include "leasherr.h"
\r
38 #include "leash-int.h"
\r
39 #include "leashids.h"
\r
41 #include <mitwhich.h>
\r
43 #include <winkrbid.h>
\r
44 #include "reminder.h"
\r
46 static char FAR *err_context;
\r
48 char KRB_HelpFile[_MAX_PATH] = HELPFILE;
\r
50 #define LEN 64 /* Maximum Hostname Length */
\r
52 #define LIFE DEFAULT_TKT_LIFE /* lifetime of ticket in 5-minute units */
\r
59 cp = ctime(dp) + 4; // skip day of week
\r
61 cp[12] = '\0'; // Don't display seconds
\r
77 for (p = s; *p; p++) {
\r
80 /* Add more cases here */
\r
93 leash_error_message(
\r
99 char* result_string,
\r
103 char message[2048];
\r
105 int size = sizeof(message);
\r
108 // XXX: ignore AFS for now.
\r
110 if (!rc5 && !rc4 && !rcL)
\r
113 n = _snprintf(p, size, "%s\n\n", error);
\r
117 if (rc5 && !result_string)
\r
119 n = _snprintf(p, size,
\r
120 "Kerberos 5: %s (error %ld)\n",
\r
121 perror_message(rc5),
\r
122 rc5 & 255 // XXX: & 255??!!!
\r
127 if (rc4 && !result_string)
\r
130 n = _snprintf(p, size,
\r
131 "Kerberos 4: %s\n",
\r
132 err_describe(buffer, rc4)
\r
140 n = _snprintf(p, size,
\r
142 err_describe(buffer, rcL)
\r
149 n = _snprintf(p, size,
\r
156 MessageBox(NULL, message, "Leash", MB_OK | MB_ICONERROR | MB_TASKMODAL |
\r
159 if (rc5) return rc5;
\r
160 if (rc4) return rc4;
\r
161 if (rcL) return rcL;
\r
170 const char * postfix,
\r
179 base_size = strlen(base) + 1;
\r
180 ret_size = base_size + strlen(postfix) + 1;
\r
181 copy = malloc(base_size);
\r
182 ret = malloc(ret_size);
\r
187 strncpy(copy, base, base_size);
\r
188 copy[base_size - 1] = 0;
\r
190 strncpy(ret, base, base_size);
\r
191 strncpy(ret + (base_size - 1), postfix, ret_size - (base_size - 1));
\r
192 ret[ret_size - 1] = 0;
\r
195 if (!copy || !ret) {
\r
202 // INVARIANT: (ret ==> copy) && (copy ==> ret)
\r
209 make_temp_cache_v4(
\r
210 const char * postfix
\r
213 static char * old_cache = 0;
\r
215 if (!pkrb_set_tkt_string || !ptkt_string || !pdest_tkt)
\r
216 return 0; // XXX - is this appropriate?
\r
220 pkrb_set_tkt_string(old_cache);
\r
227 char * tmp_cache = make_postfix(ptkt_string(), postfix, &old_cache);
\r
232 pkrb_set_tkt_string(tmp_cache);
\r
240 make_temp_cache_v5(
\r
241 const char * postfix,
\r
242 krb5_context * pctx
\r
245 static krb5_context ctx = 0;
\r
246 static char * old_cache = 0;
\r
248 // INVARIANT: old_cache ==> ctx && ctx ==> old_cache
\r
253 if (!pkrb5_init_context || !pkrb5_free_context || !pkrb5_cc_resolve ||
\r
254 !pkrb5_cc_default_name || !pkrb5_cc_set_default_name)
\r
258 krb5_ccache cc = 0;
\r
259 if (!pkrb5_cc_resolve(ctx, pkrb5_cc_default_name(ctx), &cc))
\r
260 pkrb5_cc_destroy(ctx, cc);
\r
261 pkrb5_cc_set_default_name(ctx, old_cache);
\r
266 pkrb5_free_context(ctx);
\r
272 char * tmp_cache = 0;
\r
273 krb5_error_code rc = 0;
\r
275 rc = pkrb5_init_context(&ctx);
\r
276 if (rc) goto cleanup;
\r
278 tmp_cache = make_postfix(pkrb5_cc_default_name(ctx), postfix,
\r
286 rc = pkrb5_cc_set_default_name(ctx, tmp_cache);
\r
290 pkrb5_free_context(ctx);
\r
308 return Leash_int_checkpwd(principal, password, 0);
\r
312 Leash_int_checkpwd(
\r
319 krb5_context ctx = 0; // statically allocated in make_temp_cache_v5
\r
320 // XXX - we ignore errors in make_temp_cache_v? This is BAD!!!
\r
321 make_temp_cache_v4("_checkpwd");
\r
322 make_temp_cache_v5("_checkpwd", &ctx);
\r
323 rc = Leash_int_kinit_ex( ctx, 0,
\r
324 principal, password, 0, 0, 0, 0,
\r
325 Leash_get_default_noaddresses(),
\r
326 Leash_get_default_publicip(),
\r
329 make_temp_cache_v4(0);
\r
330 make_temp_cache_v5(0, &ctx);
\r
336 Leash_changepwd_v5(char * principal,
\r
338 char * newpassword,
\r
341 krb5_error_code rc = 0;
\r
343 krb5_data result_code_string, result_string;
\r
344 krb5_context context = 0;
\r
345 krb5_principal princ = 0;
\r
346 krb5_get_init_creds_opt opts;
\r
348 DWORD addressless = 0;
\r
350 result_string.data = 0;
\r
351 result_code_string.data = 0;
\r
353 if ( !pkrb5_init_context )
\r
356 if (rc = pkrb5_init_context(&context)) {
\r
358 com_err(argv[0], ret, "initializing kerberos library");
\r
363 if (rc = pkrb5_parse_name(context, principal, &princ)) {
\r
365 com_err(argv[0], ret, "parsing client name");
\r
370 pkrb5_get_init_creds_opt_init(&opts);
\r
371 pkrb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
\r
372 pkrb5_get_init_creds_opt_set_renew_life(&opts, 0);
\r
373 pkrb5_get_init_creds_opt_set_forwardable(&opts, 0);
\r
374 pkrb5_get_init_creds_opt_set_proxiable(&opts, 0);
\r
376 addressless = Leash_get_default_noaddresses();
\r
378 pkrb5_get_init_creds_opt_set_address_list(&opts,NULL);
\r
381 if (rc = pkrb5_get_init_creds_password(context, &creds, princ, password,
\r
382 0, 0, 0, "kadmin/changepw", &opts)) {
\r
383 if (rc == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
\r
385 com_err(argv[0], 0,
\r
386 "Password incorrect while getting initial ticket");
\r
391 com_err(argv[0], ret, "getting initial ticket");
\r
397 if (rc = pkrb5_change_password(context, &creds, newpassword,
\r
398 &result_code, &result_code_string,
\r
401 com_err(argv[0], ret, "changing password");
\r
407 int len = result_code_string.length +
\r
408 (result_string.length ? (sizeof(": ") - 1) : 0) +
\r
409 result_string.length;
\r
410 if (len && error_str) {
\r
411 *error_str = malloc(len + 1);
\r
413 _snprintf(*error_str, len + 1,
\r
415 result_code_string.length, result_code_string.data,
\r
416 result_string.length?": ":"",
\r
417 result_string.length, result_string.data);
\r
424 if (result_string.data)
\r
425 pkrb5_free_data_contents(context, &result_string);
\r
427 if (result_code_string.data)
\r
428 pkrb5_free_data_contents(context, &result_code_string);
\r
431 pkrb5_free_principal(context, princ);
\r
434 pkrb5_free_context(context);
\r
441 Leash_changepwd_v4(
\r
444 char * newpassword,
\r
450 if (!pkrb_set_tkt_string || !ptkt_string || !pkadm_change_your_password ||
\r
454 k_errno = make_temp_cache_v4("_chgpwd");
\r
455 if (k_errno) return k_errno;
\r
456 k_errno = pkadm_change_your_password(principal, password, newpassword,
\r
458 make_temp_cache_v4(0);
\r
465 * Try to change the password using one of krb5 or krb4 -- whichever one
\r
466 * works. We return ok on the first one that works.
\r
472 char * newpassword,
\r
473 char** result_string
\r
476 return Leash_int_changepwd(principal, password, newpassword, result_string, 0);
\r
480 Leash_int_changepwd(
\r
483 char * newpassword,
\r
484 char** result_string,
\r
488 char* v5_error_str = 0;
\r
489 char* v4_error_str = 0;
\r
490 char* error_str = 0;
\r
495 rc = rc5 = Leash_changepwd_v5(principal, password, newpassword,
\r
498 Leash_get_default_use_krb4() &&
\r
500 rc = rc4 = Leash_changepwd_v4(principal, password, newpassword,
\r
504 if (v5_error_str || v4_error_str) {
\r
506 char v5_prefix[] = "Kerberos 5: ";
\r
508 char v4_prefix[] = "Kerberos 4: ";
\r
510 clean_string(v5_error_str);
\r
511 clean_string(v4_error_str);
\r
514 len += sizeof(sep) + sizeof(v5_prefix) + strlen(v5_error_str) +
\r
517 len += sizeof(sep) + sizeof(v4_prefix) + strlen(v4_error_str) +
\r
519 error_str = malloc(len + 1);
\r
521 char* p = error_str;
\r
522 int size = len + 1;
\r
524 if (v5_error_str) {
\r
525 n = _snprintf(p, size, "%s%s%s%s",
\r
526 sep, v5_prefix, v5_error_str, sep);
\r
530 if (v4_error_str) {
\r
531 n = _snprintf(p, size, "%s%s%s%s",
\r
532 sep, v4_prefix, v4_error_str, sep);
\r
537 *result_string = error_str;
\r
540 return leash_error_message("Error while changing password.",
\r
541 rc4, rc4, rc5, 0, error_str,
\r
546 int (*Lcom_err)(LPSTR,long,LPSTR,...);
\r
547 LPSTR (*Lerror_message)(long);
\r
548 LPSTR (*Lerror_table_name)(long);
\r
558 return Leash_int_kinit_ex( 0, 0,
\r
562 Leash_get_default_forwardable(),
\r
563 Leash_get_default_proxiable(),
\r
564 Leash_get_default_renew_till(),
\r
565 Leash_get_default_noaddresses(),
\r
566 Leash_get_default_publicip(),
\r
580 unsigned long publicip
\r
583 return Leash_int_kinit_ex( 0, /* krb5 context */
\r
584 0, /* parent window */
\r
598 Leash_int_kinit_ex(
\r
608 unsigned long publicip,
\r
612 LPCSTR functionName;
\r
613 char aname[ANAME_SZ];
\r
614 char inst[INST_SZ];
\r
615 char realm[REALM_SZ];
\r
616 char first_part[256];
\r
617 char second_part[256];
\r
631 if (renew_life > 0 && renew_life < 5)
\r
636 /* This should be changed if the maximum ticket lifetime */
\r
639 if (lifetime > 255)
\r
642 err_context = "parsing principal";
\r
644 memset(temp, '\0', sizeof(temp));
\r
645 memset(inst, '\0', sizeof(inst));
\r
646 memset(realm, '\0', sizeof(realm));
\r
647 memset(first_part, '\0', sizeof(first_part));
\r
648 memset(second_part, '\0', sizeof(second_part));
\r
650 sscanf(principal, "%[/0-9a-zA-Z._-]@%[/0-9a-zA-Z._-]", first_part, second_part);
\r
651 strcpy(temp, first_part);
\r
652 strcpy(realm, second_part);
\r
653 memset(first_part, '\0', sizeof(first_part));
\r
654 memset(second_part, '\0', sizeof(second_part));
\r
655 if (sscanf(temp, "%[@0-9a-zA-Z._-]/%[@0-9a-zA-Z._-]", first_part, second_part) == 2)
\r
657 strcpy(aname, first_part);
\r
658 strcpy(inst, second_part);
\r
664 for (i = 0; temp[i]; i++)
\r
666 if (temp[i] == '.')
\r
671 strcpy(aname, temp);
\r
675 if (pkname_parse != NULL)
\r
677 memset(first_part, '\0', sizeof(first_part));
\r
678 memset(second_part, '\0', sizeof(second_part));
\r
679 sscanf(temp, "%[@/0-9a-zA-Z_-].%[@/0-9a-zA-Z_-]", first_part, second_part);
\r
680 strcpy(aname, first_part);
\r
681 strcpy(inst, second_part);
\r
685 strcpy(aname, temp);
\r
690 memset(temp, '\0', sizeof(temp));
\r
691 strcpy(temp, aname);
\r
692 if (strlen(inst) != 0)
\r
695 strcat(temp, inst);
\r
697 if (strlen(realm) != 0)
\r
700 strcat(temp, realm);
\r
703 rc5 = Leash_krb5_kinit(ctx, hParent,
\r
704 temp, password, lifetime,
\r
711 if ( Leash_get_default_use_krb4() ) {
\r
713 if (!Leash_convert524(ctx))
\r
716 if (pkname_parse == NULL)
\r
721 err_context = "getting realm";
\r
722 if (!*realm && (rc4 = (int)(*pkrb_get_lrealm)(realm, 1)))
\r
724 functionName = "krb_get_lrealm()";
\r
725 rcL = LSH_FAILEDREALM;
\r
729 err_context = "checking principal";
\r
730 if ((!*aname) || (!(rc4 = (int)(*pk_isname)(aname))))
\r
732 functionName = "krb_get_lrealm()";
\r
733 rcL = LSH_INVPRINCIPAL;
\r
737 /* optional instance */
\r
738 if (!(rc4 = (int)(*pk_isinst)(inst)))
\r
740 functionName = "k_isinst()";
\r
741 rcL = LSH_INVINSTANCE;
\r
745 if (!(rc4 = (int)(*pk_isrealm)(realm)))
\r
747 functionName = "k_isrealm()";
\r
748 rcL = LSH_INVREALM;
\r
752 err_context = "fetching ticket";
\r
753 rc4 = (*pkrb_get_pw_in_tkt)(aname, inst, realm, "krbtgt", realm,
\r
754 lifetime, password);
\r
755 if (rc4) /* XXX: do we want: && (rc != NO_TKT_FIL) as well? */
\r
757 functionName = "krb_get_pw_in_tkt()";
\r
765 if ( !rc5 || (Leash_get_default_use_krb4() && !rc4) ) {
\r
769 for ( r=realm, t=temp; c=*r; r++,t++ )
\r
770 *t = isupper(c) ? tolower(c) : c;
\r
773 rcA = Leash_afs_klog("afs", temp, realm, lifetime);
\r
775 rcA = Leash_afs_klog("afs", "", realm, lifetime);
\r
777 #endif /* NO_AFS */
\r
780 return leash_error_message("Ticket initialization failed.",
\r
781 rcL, (rc5 && rc4)?KRBERR(rc4):0, rc5, rcA, 0,
\r
788 if ( hKrb5 && !LeashKRB5_renew() ) {
\r
790 lifetime = Leash_get_default_lifetime() / 5;
\r
791 if (hKrb4 && Leash_get_default_use_krb4())
\r
792 Leash_convert524(0);
\r
795 TicketList * list = NULL, * token;
\r
796 afs_get_tokens(NULL,&list,NULL);
\r
797 for ( token = list ; token ; token = token->next )
\r
798 Leash_afs_klog("afs", token->realm, "", lifetime);
\r
799 not_an_API_LeashFreeTicketList(&list);
\r
801 #endif /* NO_AFS */
\r
808 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
\r
810 NTSTATUS Status = 0;
\r
811 HANDLE TokenHandle;
\r
812 TOKEN_STATISTICS Stats;
\r
816 if (!ppSessionData || !pLsaGetLogonSessionData)
\r
818 *ppSessionData = NULL;
\r
820 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
\r
824 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
\r
825 CloseHandle( TokenHandle );
\r
829 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
\r
830 if ( FAILED(Status) || !ppSessionData )
\r
836 // IsKerberosLogon() does not validate whether or not there are valid tickets in the
\r
837 // cache. It validates whether or not it is reasonable to assume that if we
\r
838 // attempted to retrieve valid tickets we could do so. Microsoft does not
\r
839 // automatically renew expired tickets. Therefore, the cache could contain
\r
840 // expired or invalid tickets. Microsoft also caches the user's password
\r
841 // and will use it to retrieve new TGTs if the cache is empty and tickets
\r
845 IsKerberosLogon(VOID)
\r
847 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
\r
848 BOOL Success = FALSE;
\r
850 if ( GetSecurityLogonSessionData(&pSessionData) ) {
\r
851 if ( pSessionData->AuthenticationPackage.Buffer ) {
\r
857 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
\r
858 usLength = (pSessionData->AuthenticationPackage).Length;
\r
859 if (usLength < 256)
\r
861 lstrcpyn (buffer, usBuffer, usLength);
\r
862 lstrcat (buffer,L"");
\r
863 if ( !lstrcmp(L"Kerberos",buffer) )
\r
867 pLsaFreeReturnBuffer(pSessionData);
\r
873 // This looks really ugly because it is. The result of IsKerberosLogon()
\r
874 // does not prove whether or not there are Kerberos tickets available to
\r
875 // be imported. Only the call to khm_krb5_ms2mit() which actually attempts
\r
876 // to import tickets can do that. However, calling khm_krb5_ms2mit() can
\r
877 // result in a TGS_REQ being sent to the KDC and since Leash_importable()
\r
878 // is called quite often we want to avoid this if at all possible.
\r
879 // Unfortunately, we have be shown at least one case in which the primary
\r
880 // authentication package was not Kerberos and yet there were Kerberos
\r
881 // tickets available. Therefore, if IsKerberosLogon() is not TRUE we
\r
882 // must call khm_krb5_ms2mit() but we still do not want to call it in a
\r
883 // tight loop so we cache the response and assume it won't change.
\r
885 Leash_importable(void)
\r
887 if ( IsKerberosLogon() )
\r
890 static int response = -1;
\r
891 if (response == -1) {
\r
892 response = khm_krb5_ms2mit(0);
\r
901 if ( khm_krb5_ms2mit(1) ) {
\r
903 lifetime = Leash_get_default_lifetime() / 5;
\r
904 if (hKrb4 && Leash_get_default_use_krb4())
\r
905 Leash_convert524(0);
\r
916 krb5_context ctx = 0;
\r
917 krb5_error_code code = 0;
\r
918 krb5_ccache cc = 0;
\r
919 krb5_principal me = 0;
\r
921 if ( !pkrb5_init_context )
\r
924 code = pkrb5_init_context(&ctx);
\r
925 if (code) goto cleanup;
\r
927 code = pkrb5_cc_default(ctx, &cc);
\r
928 if (code) goto cleanup;
\r
930 if (code = pkrb5_cc_get_principal(ctx, cc, &me))
\r
933 for ( r=realm, t=cell, i=0; i<krb5_princ_realm(ctx, me)->length; r++,t++,i++ ) {
\r
934 c = krb5_princ_realm(ctx, me)->data[i];
\r
936 *t = isupper(c) ? tolower(c) : c;
\r
940 rcA = Leash_afs_klog("afs", cell, realm, lifetime);
\r
942 rcA = Leash_afs_klog("afs", "", realm, lifetime);
\r
946 pkrb5_free_principal(ctx, me);
\r
948 pkrb5_cc_close(ctx, cc);
\r
950 pkrb5_free_context(ctx);
\r
952 #endif /* NO_AFS */
\r
959 Leash_kdestroy(void)
\r
964 khm_krb5_destroy_identity(NULL);
\r
966 if (pdest_tkt != NULL)
\r
968 k_errno = (*pdest_tkt)();
\r
969 if (k_errno && (k_errno != RET_TKFIL))
\r
970 return KRBERR(k_errno);
\r
979 char loc_addr[ADDR_SZ];
\r
985 struct in_addr LocAddr;
\r
988 if (pkrb_get_cred == NULL)
\r
991 k_errno = (*pkrb_get_cred)(service,instance,realm,&cred);
\r
993 return KRBERR(k_errno);
\r
997 ipAddr = (*pLocalHostAddr)();
\r
998 LocAddr.s_addr = ipAddr;
\r
999 strcpy(loc_addr,inet_ntoa(LocAddr));
\r
1000 if ( strcmp(cred.address,loc_addr) != 0) {
\r
1001 Leash_kdestroy ();
\r
1010 not_an_API_LeashFreeTicketList(TicketList** ticketList)
\r
1012 TicketList* tempList = *ticketList, *killList;
\r
1014 //if (tempList == NULL)
\r
1019 killList = tempList;
\r
1021 tempList = (TicketList*)tempList->next;
\r
1022 free(killList->theTicket);
\r
1023 if (killList->tktEncType)
\r
1024 free(killList->tktEncType);
\r
1025 if (killList->keyEncType)
\r
1026 free(killList->keyEncType);
\r
1027 if (killList->addrCount) {
\r
1029 for ( n=0; n<killList->addrCount; n++) {
\r
1030 if (killList->addrList[n])
\r
1031 free(killList->addrList[n]);
\r
1034 if (killList->addrList)
\r
1035 free(killList->addrList);
\r
1036 if (killList->name)
\r
1037 free(killList->name);
\r
1038 if (killList->inst)
\r
1039 free(killList->inst);
\r
1040 if (killList->realm)
\r
1041 free(killList->realm);
\r
1045 *ticketList = NULL;
\r
1050 long FAR Leash_klist(HWND hlist, TICKETINFO FAR *ticketinfo)
\r
1052 // Don't think this function will be used anymore - ADL 5-15-99
\r
1053 // Old fucntion to put tickets in a listbox control
\r
1054 // Use function "not_an_API_LeashKRB4GetTickets()" instead!
\r
1055 char pname[ANAME_SZ];
\r
1056 char pinst[INST_SZ];
\r
1057 char prealm[REALM_SZ];
\r
1058 char buf[MAX_K_NAME_SZ+40];
\r
1063 int newtickets = 0;
\r
1067 * Since krb_get_tf_realm will return a ticket_file error,
\r
1068 * we will call tf_init and tf_close first to filter out
\r
1069 * things like no ticket file. Otherwise, the error that
\r
1070 * the user would see would be
\r
1071 * klist: can't find realm of ticket file: No ticket file (tf_util)
\r
1073 * klist: No ticket file (tf_util)
\r
1075 if (ptf_init == NULL)
\r
1080 SendMessage(hlist, WM_SETREDRAW, FALSE, 0L);
\r
1081 SendMessage(hlist, LB_RESETCONTENT, 0, 0L);
\r
1084 newtickets = NO_TICKETS;
\r
1086 err_context = (LPSTR)"tktf1";
\r
1088 /* Open ticket file */
\r
1089 if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
\r
1093 /* Close ticket file */
\r
1094 (void) (*ptf_close)();
\r
1096 * We must find the realm of the ticket file here before calling
\r
1097 * tf_init because since the realm of the ticket file is not
\r
1098 * really stored in the principal section of the file, the
\r
1099 * routine we use must itself call tf_init and tf_close.
\r
1101 err_context = "tf realm";
\r
1102 if ((k_errno = (*pkrb_get_tf_realm)((*ptkt_string)(), prealm)) != KSUCCESS)
\r
1106 /* Open ticket file */
\r
1107 err_context = "tf init";
\r
1108 if (k_errno = (*ptf_init)((*ptkt_string)(), R_TKT_FIL))
\r
1114 err_context = "tf pname";
\r
1115 /* Get principal name and instance */
\r
1116 if ((k_errno = (*ptf_get_pname)(pname)) || (k_errno = (*ptf_get_pinst)(pinst)))
\r
1122 * You may think that this is the obvious place to get the
\r
1123 * realm of the ticket file, but it can't be done here as the
\r
1124 * routine to do this must open the ticket file. This is why
\r
1125 * it was done before tf_init.
\r
1128 wsprintf((LPSTR)ticketinfo->principal,"%s%s%s%s%s", (LPSTR)pname,
\r
1129 (LPSTR)(pinst[0] ? "." : ""), (LPSTR)pinst,
\r
1130 (LPSTR)(prealm[0] ? "@" : ""), (LPSTR)prealm);
\r
1131 newtickets = GOOD_TICKETS;
\r
1133 err_context = "tf cred";
\r
1134 while ((k_errno = (*ptf_get_cred)(&c)) == KSUCCESS)
\r
1136 expdate = c.issue_date + c.lifetime * 5L * 60L;
\r
1138 if (!lstrcmp((LPSTR)c.service, (LPSTR)TICKET_GRANTING_TICKET) && !lstrcmp((LPSTR)c.instance, (LPSTR)prealm))
\r
1140 ticketinfo->issue_date = c.issue_date;
\r
1141 ticketinfo->lifetime = c.lifetime * 5L * 60L;
\r
1142 ticketinfo->renew_till = 0;
\r
1146 lstrcpy(cp, (LPSTR)short_date(&c.issue_date));
\r
1147 cp += lstrlen(cp);
\r
1148 wsprintf(cp,"\t%s\t%s%s%s%s%s",
\r
1149 (LPSTR)short_date(&expdate), (LPSTR)c.service,
\r
1150 (LPSTR)(c.instance[0] ? "." : ""),
\r
1151 (LPSTR)c.instance, (LPSTR)(c.realm[0] ? "@" : ""),
\r
1154 SendMessage(hlist, LB_ADDSTRING, 0, (LONG)(LPSTR)buf);
\r
1160 (*ptf_close)(); /* close ticket file */
\r
1164 SendMessage(hlist, WM_SETREDRAW, TRUE, 0L);
\r
1165 InvalidateRect(hlist, NULL, TRUE);
\r
1166 UpdateWindow(hlist);
\r
1168 if (k_errno == EOF)
\r
1171 /* XXX the if statement directly below was inserted to eliminate
\r
1172 an error 20 on Leash startup. The error occurs from an error
\r
1173 number thrown from krb_get_tf_realm. We believe this change
\r
1174 does not eliminate other errors, but it may. */
\r
1176 if (k_errno == RET_NOTKT)
\r
1179 ticketinfo->btickets = newtickets;
\r
1181 return KRBERR(k_errno);
\r
1187 static BOOL CALLBACK
\r
1188 EnumChildProc(HWND hwnd, LPARAM lParam)
\r
1190 HWND * h = (HWND *)lParam;
\r
1197 FindFirstChildWindow(HWND parent)
\r
1199 HWND hFirstChild = 0;
\r
1200 EnumChildWindows(parent, EnumChildProc, (LPARAM) &hFirstChild);
\r
1201 return hFirstChild;
\r
1205 not_an_API_Leash_AcquireInitialTicketsIfNeeded(krb5_context context, krb5_principal desiredKrb5Principal)
\r
1207 krb5_error_code err;
\r
1208 LSH_DLGINFO_EX dlginfo;
\r
1212 char *desiredName = 0;
\r
1213 char *desiredRealm = 0;
\r
1215 TicketList * list = NULL;
\r
1216 TICKETINFO ticketinfo;
\r
1220 DWORD dwMsLsaImport = Leash_get_default_mslsa_import();
\r
1222 char loginenv[16];
\r
1225 GetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", loginenv, sizeof(loginenv));
\r
1226 prompt = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
\r
1228 if ( !prompt || !pkrb5_init_context )
\r
1232 env = getenv("KRB5CCNAME");
\r
1233 if ( !env && context ) {
\r
1234 sprintf(newenv,"KRB5CCNAME=%s",pkrb5_cc_default_name(ctx));
\r
1235 env = (char *)putenv(newenv);
\r
1238 not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
\r
1239 not_an_API_LeashFreeTicketList(&list);
\r
1241 if ( ticketinfo.btickets != GOOD_TICKETS &&
\r
1242 Leash_get_default_mslsa_import() && Leash_importable() ) {
\r
1243 // We have the option of importing tickets from the MSLSA
\r
1244 // but should we? Do the tickets in the MSLSA cache belong
\r
1245 // to the default realm used by Leash? If so, import.
\r
1248 if ( dwMsLsaImport == 1 ) { /* always import */
\r
1250 } else if ( dwMsLsaImport == 2 ) { /* import when realms match */
\r
1251 krb5_error_code code;
\r
1252 krb5_ccache mslsa_ccache=0;
\r
1253 krb5_principal princ = 0;
\r
1254 char ms_realm[128] = "", *def_realm = 0, *r;
\r
1257 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
\r
1260 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
\r
1263 for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
\r
1264 *r = krb5_princ_realm(ctx, princ)->data[i];
\r
1268 if (code = pkrb5_get_default_realm(ctx, &def_realm))
\r
1271 import = !strcmp(def_realm, ms_realm);
\r
1275 pkrb5_free_default_realm(ctx, def_realm);
\r
1278 pkrb5_free_principal(ctx, princ);
\r
1281 pkrb5_cc_close(ctx, mslsa_ccache);
\r
1287 not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx);
\r
1288 not_an_API_LeashFreeTicketList(&list);
\r
1292 if ( ticketinfo.btickets != GOOD_TICKETS )
\r
1294 /* do we want a specific client principal? */
\r
1295 if (desiredKrb5Principal != NULL) {
\r
1296 err = pkrb5_unparse_name (ctx, desiredKrb5Principal, &desiredName);
\r
1298 dlginfo.username = desiredName;
\r
1299 for (p = desiredName; *p && *p != '@'; p++);
\r
1300 if ( *p == '@' ) {
\r
1302 desiredRealm = dlginfo.realm = ++p;
\r
1308 memset(&dlginfo, 0, sizeof(LSH_DLGINFO_EX));
\r
1309 dlginfo.size = sizeof(LSH_DLGINFO_EX);
\r
1310 dlginfo.dlgtype = DLGTYPE_PASSWD;
\r
1311 dlginfo.title = "Obtain Kerberos Ticket Getting Tickets";
\r
1312 dlginfo.use_defaults = 1;
\r
1314 err = Leash_kinit_dlg_ex(NULL, &dlginfo);
\r
1316 /* construct a marshalling of data
\r
1317 * <title><principal><realm>
\r
1318 * then send to Leash
\r
1321 hData = GlobalAlloc( GHND, 4096 );
\r
1322 hForeground = GetForegroundWindow();
\r
1323 hLeash = FindWindow("LEASH.0WNDCLASS", NULL);
\r
1324 SetForegroundWindow(hLeash);
\r
1325 hLeash = FindFirstChildWindow(hLeash);
\r
1326 if ( hData && hLeash ) {
\r
1327 char * strs = GlobalLock( hData );
\r
1329 strcpy(strs, "Obtain Kerberos Ticket Getting Tickets");
\r
1330 strs += strlen(strs) + 1;
\r
1331 if ( desiredName ) {
\r
1332 strcpy(strs, desiredName);
\r
1333 strs += strlen(strs) + 1;
\r
1334 if (desiredRealm) {
\r
1335 strcpy(strs, desiredRealm);
\r
1336 strs += strlen(strs) + 1;
\r
1345 GlobalUnlock( hData );
\r
1346 SendMessage(hLeash, 32809, 0, (LPARAM) hData);
\r
1349 GlobalFree( hData );
\r
1351 SetForegroundWindow(hForeground);
\r
1353 if (desiredName != NULL)
\r
1354 pkrb5_free_unparsed_name(ctx, desiredName);
\r
1357 if ( !env && context )
\r
1358 putenv("KRB5CCNAME=");
\r
1361 pkrb5_free_context(ctx);
\r