macos: avoid KLRenewInitialTickets crash in Lion
[openafs.git] / src / platform / DARWIN / AFSPreference / Krb5Util.m
1 //
2 //  Krb5Util.m
3 //  OpenAFS
4 //
5 //  Created by Claudio Bisegni on 20/03/10.
6 //  Copyright 2010 INFN. All rights reserved.
7 //
8
9 #import "Krb5Util.h"
10
11 @implementation Krb5Util
12 +(KLStatus) getNewTicketIfNotPresent {
13         KLPrincipal             princ = nil;
14         KLStatus                kstatus = noErr;
15         char                    *princName = 0L;
16         KLBoolean       outFoundValidTickets = false;
17         KLLoginOptions  inLoginOptions = nil;
18
19         @try{
20                 kstatus = KLCacheHasValidTickets(nil, kerberosVersion_All, &outFoundValidTickets, nil, nil);
21                 if(!outFoundValidTickets) {
22                     kstatus = KLCreateLoginOptions(&inLoginOptions);
23                     if (kstatus != noErr)
24                         @throw [NSException exceptionWithName:@"Krb5Util"
25                                             reason:@"getNewTicketIfNotPresent"
26                                             userInfo:nil];
27                     else {
28                         KLLifetime valuel;
29                         KLSize sizel = sizeof (valuel);
30                         KLBoolean value;
31                         KLSize size = sizeof (value);
32                         kstatus = KLGetDefaultLoginOption (loginOption_DefaultTicketLifetime, &valuel, &sizel);
33
34                         if (kstatus == noErr)
35                             kstatus = KLLoginOptionsSetTicketLifetime
36                                 (inLoginOptions, valuel);
37
38                         kstatus = KLGetDefaultLoginOption
39                             (loginOption_DefaultRenewableTicket, &value,
40                              &size);
41                         if (kstatus == noErr)
42                             if ((value != 0) &&
43                                 ((kstatus = KLGetDefaultLoginOption
44                                   (loginOption_DefaultRenewableLifetime,
45                                    &value, &size)) == noErr))
46                                 kstatus = KLLoginOptionsSetRenewableLifetime
47                                 (inLoginOptions, value);
48                             else {
49                                 kstatus = KLLoginOptionsSetRenewableLifetime(inLoginOptions, 0L);
50                         }
51                         kstatus = KLGetDefaultLoginOption
52                             (loginOption_DefaultForwardableTicket, &value,
53                              &size);
54
55                         if (kstatus == noErr)
56                             kstatus = KLLoginOptionsSetForwardable
57                                 (inLoginOptions, value);
58
59                         kstatus = KLGetDefaultLoginOption
60                             (loginOption_DefaultProxiableTicket, &value,
61                              &size);
62
63                         if (kstatus == noErr)
64                             kstatus = KLLoginOptionsSetProxiable
65                                 (inLoginOptions, value);
66
67                         kstatus = KLGetDefaultLoginOption
68                             (loginOption_DefaultAddresslessTicket, &value,
69                              &size);
70
71                         if (kstatus == noErr)
72                             kstatus = KLLoginOptionsSetAddressless
73                                 (inLoginOptions, value);
74                     }
75
76                     if (kstatus == noErr)
77                         kstatus = KLAcquireNewInitialTickets(nil,
78                                                              inLoginOptions,
79                                                              &princ,
80                                                              &princName);
81                     if(kstatus != noErr && kstatus != klUserCanceledErr)
82                         @throw [NSException exceptionWithName:@"Krb5Util"
83                                             reason:@"getNewTicketIfNotPresent"
84                                             userInfo:nil];
85                     if (inLoginOptions != NULL) {
86                         KLDisposeLoginOptions (inLoginOptions);
87                     }
88                 }
89         }
90         @catch (NSException * e) {
91                 @throw e;
92         }
93         @finally {
94                 KLDisposeString (princName);
95                 KLDisposePrincipal (princ);
96         }
97         return kstatus;
98 }
99
100 +(KLStatus) renewTicket:(NSTimeInterval)secToExpire
101                           renewTime:(NSTimeInterval)renewTime {
102         KLPrincipal             princ = nil;
103         KLStatus                kstatus = noErr;
104         char                    *princName = 0L;
105         KLTime          expireStartTime;
106         KLLoginOptions  inLoginOptions;
107         KLLifetime      inTicketLifetime = renewTime;
108         NSDate                  *expirationDate = nil;
109         @try {
110                 //prepare the login option
111                 kstatus = KLCreateLoginOptions(&inLoginOptions);
112                 //set the lifetime of ticket
113                 kstatus = KLLoginOptionsSetTicketLifetime (inLoginOptions,  inTicketLifetime);
114                 kstatus = KLLoginOptionsSetRenewableLifetime (inLoginOptions, 0L);
115                 kstatus = KLLoginOptionsSetTicketStartTime (inLoginOptions, 0);
116                 //set the preference renewable time
117                 //kstatus =  KLLoginOptionsSetRenewableLifetime (inLoginOptions, inTicketLifetime);
118                 //check the start time
119                 kstatus = KLTicketExpirationTime (nil, kerberosVersion_All, &expireStartTime);
120                 expirationDate = [NSDate dateWithTimeIntervalSince1970:expireStartTime];
121
122                 //NSLog(@"Ticket Expiration time: %@", [expirationDate description]);
123                 NSTimeInterval secondToExpireTime = [expirationDate timeIntervalSinceNow];
124                 if(secondToExpireTime <= secToExpire) {
125 #if defined(MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6)
126                         krb5_creds in;
127                         krb5_error_code ret;
128                         krb5_ccache id = NULL;
129                         static dispatch_once_t once = 0;
130                         static krb5_context kcontext;
131                         krb5_principal me=NULL;
132                         krb5_principal server=NULL;
133                         krb5_timestamp now;
134
135                         dispatch_once(&once, ^{
136                                         krb5_init_context(&kcontext);
137                                 });
138
139                         krb5_timeofday(kcontext, &now);
140                         memset((char *)&in, 0, sizeof(in));
141                         in.times.starttime = 0;
142                         in.times.endtime = now + inTicketLifetime;
143                         in.times.renew_till = now + inTicketLifetime;
144
145                         krb5_cc_default(kcontext, &id);
146                         if (ret == 0) {
147                                 ret = krb5_cc_get_principal(kcontext, id,
148                                                             &me);
149                                 in.client = me;
150                         }
151                         if (ret == 0) {
152                           ret = krb5_build_principal_ext(kcontext, &server,
153                                                        krb5_princ_realm(kcontext,
154                                                                         in.client)->length,
155                                                        krb5_princ_realm(kcontext,
156                                                                         in.client)->data,
157                                                        6, "krbtgt",
158                                                        krb5_princ_realm(kcontext,
159                                                                         in.client)->length,
160                                                        krb5_princ_realm(kcontext,
161                                                                         in.client)->data,
162                                                        0);
163                         }
164                         if (ret == 0) {
165                           in.server = server;
166                           ret = krb5_get_renewed_creds(kcontext, &in, me, id, server);
167                         }
168                         if (ret == 0) {
169                           ret = krb5_cc_initialize (kcontext, id, me);
170                           ret = krb5_cc_store_cred(kcontext, id, &in);
171                           krb5_cc_close(kcontext,id);
172                         }
173                         krb5_free_principal(kcontext, server);
174 #else
175                         KLPrincipal klprinc = nil;
176                         kstatus = KLRenewInitialTickets ( klprinc, inLoginOptions, nil, nil);
177 #endif
178
179 #if 0
180                         /* handoff to growl agent? */
181                         kstatus = KLTicketExpirationTime (nil, kerberosVersion_All, &expireStartTime);
182                         expirationDate = [NSDate dateWithTimeIntervalSince1970:expireStartTime];
183                         BuildNotificationInfo(@"Ticket Renewed Unitl %@", expirationDate,  callbackInfo->dcref, callbackInfo->regref, callbackInfo->icon);
184 #endif
185                 }
186         }
187         @catch (NSException * e) {
188                 @throw e;
189         }
190         @finally {
191                 KLDisposeString (princName);
192                 KLDisposePrincipal (princ);
193                 KLDisposeLoginOptions(inLoginOptions);
194         }
195         return kstatus;
196 }
197 @end