xref: /freebsd/crypto/krb5/src/windows/leashdll/krb5routines.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert // Module name: krb5routines.c
2*7f2fe78bSCy Schubert 
3*7f2fe78bSCy Schubert #include <windows.h>
4*7f2fe78bSCy Schubert #define SECURITY_WIN32
5*7f2fe78bSCy Schubert #include <security.h>
6*7f2fe78bSCy Schubert 
7*7f2fe78bSCy Schubert /* _WIN32_WINNT must be 0x0501 or greater to pull in definition of
8*7f2fe78bSCy Schubert  * all required LSA data types when the Vista SDK NtSecAPI.h is used.
9*7f2fe78bSCy Schubert  */
10*7f2fe78bSCy Schubert #ifndef _WIN32_WINNT
11*7f2fe78bSCy Schubert #define _WIN32_WINNT 0x0501
12*7f2fe78bSCy Schubert #else
13*7f2fe78bSCy Schubert #if _WIN32_WINNT < 0x0501
14*7f2fe78bSCy Schubert #undef _WIN32_WINNT
15*7f2fe78bSCy Schubert #define _WIN32_WINNT 0x0501
16*7f2fe78bSCy Schubert #endif
17*7f2fe78bSCy Schubert #endif
18*7f2fe78bSCy Schubert #include <ntsecapi.h>
19*7f2fe78bSCy Schubert #include <stdio.h>
20*7f2fe78bSCy Schubert #include <string.h>
21*7f2fe78bSCy Schubert #include <time.h>
22*7f2fe78bSCy Schubert #include <assert.h>
23*7f2fe78bSCy Schubert 
24*7f2fe78bSCy Schubert #include <winsock2.h>
25*7f2fe78bSCy Schubert 
26*7f2fe78bSCy Schubert /* Private Include files */
27*7f2fe78bSCy Schubert #include "leashdll.h"
28*7f2fe78bSCy Schubert #include <leashwin.h>
29*7f2fe78bSCy Schubert #include "leash-int.h"
30*7f2fe78bSCy Schubert 
31*7f2fe78bSCy Schubert #define KRB5_DEFAULT_LIFE            60*60*10 /* 10 hours */
32*7f2fe78bSCy Schubert 
GetTicketFlag(krb5_creds * cred)33*7f2fe78bSCy Schubert char *GetTicketFlag(krb5_creds *cred)
34*7f2fe78bSCy Schubert {
35*7f2fe78bSCy Schubert    static char buf[32];
36*7f2fe78bSCy Schubert    int i = 0;
37*7f2fe78bSCy Schubert 
38*7f2fe78bSCy Schubert    buf[i++] = ' ';
39*7f2fe78bSCy Schubert    buf[i++] = '(';
40*7f2fe78bSCy Schubert 
41*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
42*7f2fe78bSCy Schubert      buf[i++] = 'F';
43*7f2fe78bSCy Schubert 
44*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_FORWARDED)
45*7f2fe78bSCy Schubert      buf[i++] = 'f';
46*7f2fe78bSCy Schubert 
47*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_PROXIABLE)
48*7f2fe78bSCy Schubert      buf[i++] = 'P';
49*7f2fe78bSCy Schubert 
50*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_PROXY)
51*7f2fe78bSCy Schubert      buf[i++] = 'p';
52*7f2fe78bSCy Schubert 
53*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
54*7f2fe78bSCy Schubert      buf[i++] = 'D';
55*7f2fe78bSCy Schubert 
56*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_POSTDATED)
57*7f2fe78bSCy Schubert      buf[i++] = 'd';
58*7f2fe78bSCy Schubert 
59*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_INVALID)
60*7f2fe78bSCy Schubert      buf[i++] = 'i';
61*7f2fe78bSCy Schubert 
62*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_RENEWABLE)
63*7f2fe78bSCy Schubert      buf[i++] = 'R';
64*7f2fe78bSCy Schubert 
65*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_INITIAL)
66*7f2fe78bSCy Schubert      buf[i++] = 'I';
67*7f2fe78bSCy Schubert 
68*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_HW_AUTH)
69*7f2fe78bSCy Schubert      buf[i++] = 'H';
70*7f2fe78bSCy Schubert 
71*7f2fe78bSCy Schubert    if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
72*7f2fe78bSCy Schubert      buf[i++] = 'A';
73*7f2fe78bSCy Schubert 
74*7f2fe78bSCy Schubert    buf[i++] = ')';
75*7f2fe78bSCy Schubert    buf[i] = '\0';
76*7f2fe78bSCy Schubert 
77*7f2fe78bSCy Schubert    if (i <= 3)
78*7f2fe78bSCy Schubert      buf[0] = '\0';
79*7f2fe78bSCy Schubert 
80*7f2fe78bSCy Schubert    return buf;
81*7f2fe78bSCy Schubert }
82*7f2fe78bSCy Schubert 
83*7f2fe78bSCy Schubert int
LeashKRB5_renew(void)84*7f2fe78bSCy Schubert LeashKRB5_renew(void)
85*7f2fe78bSCy Schubert {
86*7f2fe78bSCy Schubert     krb5_error_code		        code = 0;
87*7f2fe78bSCy Schubert     krb5_context		        ctx = 0;
88*7f2fe78bSCy Schubert     krb5_ccache			        cc = 0;
89*7f2fe78bSCy Schubert     krb5_principal		        me = 0;
90*7f2fe78bSCy Schubert     krb5_principal              server = 0;
91*7f2fe78bSCy Schubert     krb5_creds			        my_creds;
92*7f2fe78bSCy Schubert     krb5_data                   *realm = 0;
93*7f2fe78bSCy Schubert 
94*7f2fe78bSCy Schubert     if ( !pkrb5_init_context )
95*7f2fe78bSCy Schubert         goto cleanup;
96*7f2fe78bSCy Schubert 
97*7f2fe78bSCy Schubert 	memset(&my_creds, 0, sizeof(krb5_creds));
98*7f2fe78bSCy Schubert 
99*7f2fe78bSCy Schubert     code = pkrb5_init_context(&ctx);
100*7f2fe78bSCy Schubert     if (code) goto cleanup;
101*7f2fe78bSCy Schubert 
102*7f2fe78bSCy Schubert     code = pkrb5_cc_default(ctx, &cc);
103*7f2fe78bSCy Schubert     if (code) goto cleanup;
104*7f2fe78bSCy Schubert 
105*7f2fe78bSCy Schubert     code = pkrb5_cc_get_principal(ctx, cc, &me);
106*7f2fe78bSCy Schubert     if (code) goto cleanup;
107*7f2fe78bSCy Schubert 
108*7f2fe78bSCy Schubert     realm = krb5_princ_realm(ctx, me);
109*7f2fe78bSCy Schubert 
110*7f2fe78bSCy Schubert     code = pkrb5_build_principal_ext(ctx, &server,
111*7f2fe78bSCy Schubert                                     realm->length,realm->data,
112*7f2fe78bSCy Schubert                                     KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
113*7f2fe78bSCy Schubert                                     realm->length,realm->data,
114*7f2fe78bSCy Schubert                                     0);
115*7f2fe78bSCy Schubert     if ( code ) goto cleanup;
116*7f2fe78bSCy Schubert 
117*7f2fe78bSCy Schubert     my_creds.client = me;
118*7f2fe78bSCy Schubert     my_creds.server = server;
119*7f2fe78bSCy Schubert 
120*7f2fe78bSCy Schubert     pkrb5_cc_set_flags(ctx, cc, 0);
121*7f2fe78bSCy Schubert     code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
122*7f2fe78bSCy Schubert     pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
123*7f2fe78bSCy Schubert     if (code) {
124*7f2fe78bSCy Schubert         if (code != KRB5KDC_ERR_ETYPE_NOSUPP && code != KRB5_KDC_UNREACH &&
125*7f2fe78bSCy Schubert             code != KRB5_CC_NOTFOUND)
126*7f2fe78bSCy Schubert             Leash_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
127*7f2fe78bSCy Schubert         goto cleanup;
128*7f2fe78bSCy Schubert     }
129*7f2fe78bSCy Schubert 
130*7f2fe78bSCy Schubert     code = pkrb5_cc_initialize(ctx, cc, me);
131*7f2fe78bSCy Schubert     if (code) goto cleanup;
132*7f2fe78bSCy Schubert 
133*7f2fe78bSCy Schubert     code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
134*7f2fe78bSCy Schubert     if (code) goto cleanup;
135*7f2fe78bSCy Schubert 
136*7f2fe78bSCy Schubert   cleanup:
137*7f2fe78bSCy Schubert     if (my_creds.client == me)
138*7f2fe78bSCy Schubert         my_creds.client = 0;
139*7f2fe78bSCy Schubert     if (my_creds.server == server)
140*7f2fe78bSCy Schubert         my_creds.server = 0;
141*7f2fe78bSCy Schubert     pkrb5_free_cred_contents(ctx, &my_creds);
142*7f2fe78bSCy Schubert     if (me)
143*7f2fe78bSCy Schubert         pkrb5_free_principal(ctx, me);
144*7f2fe78bSCy Schubert     if (server)
145*7f2fe78bSCy Schubert         pkrb5_free_principal(ctx, server);
146*7f2fe78bSCy Schubert     if (cc)
147*7f2fe78bSCy Schubert         pkrb5_cc_close(ctx, cc);
148*7f2fe78bSCy Schubert     if (ctx)
149*7f2fe78bSCy Schubert         pkrb5_free_context(ctx);
150*7f2fe78bSCy Schubert     return(code);
151*7f2fe78bSCy Schubert }
152*7f2fe78bSCy Schubert 
153*7f2fe78bSCy Schubert static krb5_error_code KRB5_CALLCONV
154*7f2fe78bSCy Schubert leash_krb5_prompter( krb5_context context,
155*7f2fe78bSCy Schubert 					 void *data,
156*7f2fe78bSCy Schubert 					 const char *name,
157*7f2fe78bSCy Schubert 					 const char *banner,
158*7f2fe78bSCy Schubert 					 int num_prompts,
159*7f2fe78bSCy Schubert 					 krb5_prompt prompts[]);
160*7f2fe78bSCy Schubert 
161*7f2fe78bSCy Schubert int
Leash_krb5_kinit(krb5_context alt_ctx,HWND hParent,char * principal_name,char * password,krb5_deltat lifetime,DWORD forwardable,DWORD proxiable,krb5_deltat renew_life,DWORD addressless,DWORD publicIP)162*7f2fe78bSCy Schubert Leash_krb5_kinit(
163*7f2fe78bSCy Schubert krb5_context alt_ctx,
164*7f2fe78bSCy Schubert HWND hParent,
165*7f2fe78bSCy Schubert char *principal_name,
166*7f2fe78bSCy Schubert char *password,
167*7f2fe78bSCy Schubert krb5_deltat lifetime,
168*7f2fe78bSCy Schubert DWORD                       forwardable,
169*7f2fe78bSCy Schubert DWORD                       proxiable,
170*7f2fe78bSCy Schubert krb5_deltat                 renew_life,
171*7f2fe78bSCy Schubert DWORD                       addressless,
172*7f2fe78bSCy Schubert DWORD                       publicIP
173*7f2fe78bSCy Schubert )
174*7f2fe78bSCy Schubert {
175*7f2fe78bSCy Schubert     krb5_error_code		        code = 0;
176*7f2fe78bSCy Schubert     krb5_context		        ctx = 0;
177*7f2fe78bSCy Schubert     krb5_ccache			        cc = 0, defcache = 0;
178*7f2fe78bSCy Schubert     krb5_principal		        me = 0;
179*7f2fe78bSCy Schubert     char*                       name = 0;
180*7f2fe78bSCy Schubert     krb5_creds			        my_creds;
181*7f2fe78bSCy Schubert     krb5_get_init_creds_opt *   options = NULL;
182*7f2fe78bSCy Schubert     krb5_address **             addrs = NULL;
183*7f2fe78bSCy Schubert     int                         i = 0, addr_count = 0;
184*7f2fe78bSCy Schubert     int                         cc_new = 0;
185*7f2fe78bSCy Schubert     const char *                deftype = NULL;
186*7f2fe78bSCy Schubert 
187*7f2fe78bSCy Schubert     if (!pkrb5_init_context)
188*7f2fe78bSCy Schubert         return 0;
189*7f2fe78bSCy Schubert 
190*7f2fe78bSCy Schubert     memset(&my_creds, 0, sizeof(my_creds));
191*7f2fe78bSCy Schubert 
192*7f2fe78bSCy Schubert     if (alt_ctx)
193*7f2fe78bSCy Schubert     {
194*7f2fe78bSCy Schubert         ctx = alt_ctx;
195*7f2fe78bSCy Schubert     }
196*7f2fe78bSCy Schubert     else
197*7f2fe78bSCy Schubert     {
198*7f2fe78bSCy Schubert         code = pkrb5_init_context(&ctx);
199*7f2fe78bSCy Schubert         if (code) goto cleanup;
200*7f2fe78bSCy Schubert     }
201*7f2fe78bSCy Schubert 
202*7f2fe78bSCy Schubert     code = pkrb5_get_init_creds_opt_alloc(ctx, &options);
203*7f2fe78bSCy Schubert     if (code) goto cleanup;
204*7f2fe78bSCy Schubert 
205*7f2fe78bSCy Schubert     code = pkrb5_cc_default(ctx, &defcache);
206*7f2fe78bSCy Schubert     if (code) goto cleanup;
207*7f2fe78bSCy Schubert 
208*7f2fe78bSCy Schubert     code = pkrb5_parse_name(ctx, principal_name, &me);
209*7f2fe78bSCy Schubert     if (code) goto cleanup;
210*7f2fe78bSCy Schubert 
211*7f2fe78bSCy Schubert     deftype = pkrb5_cc_get_type(ctx, defcache);
212*7f2fe78bSCy Schubert     if (me != NULL && pkrb5_cc_support_switch(ctx, deftype)) {
213*7f2fe78bSCy Schubert         /* Use an existing cache for the specified principal if we can. */
214*7f2fe78bSCy Schubert         code = pkrb5_cc_cache_match(ctx, me, &cc);
215*7f2fe78bSCy Schubert         if (code != 0 && code != KRB5_CC_NOTFOUND)
216*7f2fe78bSCy Schubert             goto cleanup;
217*7f2fe78bSCy Schubert         if (code == KRB5_CC_NOTFOUND) {
218*7f2fe78bSCy Schubert             code = pkrb5_cc_new_unique(ctx, deftype, NULL, &cc);
219*7f2fe78bSCy Schubert             if (code)
220*7f2fe78bSCy Schubert                 goto cleanup;
221*7f2fe78bSCy Schubert             cc_new = 1;
222*7f2fe78bSCy Schubert         }
223*7f2fe78bSCy Schubert         pkrb5_cc_close(ctx, defcache);
224*7f2fe78bSCy Schubert     } else {
225*7f2fe78bSCy Schubert         cc = defcache;
226*7f2fe78bSCy Schubert     }
227*7f2fe78bSCy Schubert 
228*7f2fe78bSCy Schubert     code = pkrb5_unparse_name(ctx, me, &name);
229*7f2fe78bSCy Schubert     if (code) goto cleanup;
230*7f2fe78bSCy Schubert 
231*7f2fe78bSCy Schubert     if (lifetime == 0)
232*7f2fe78bSCy Schubert         lifetime = Leash_get_default_lifetime();
233*7f2fe78bSCy Schubert     else
234*7f2fe78bSCy Schubert         lifetime *= 5*60;
235*7f2fe78bSCy Schubert 
236*7f2fe78bSCy Schubert 	if (renew_life > 0)
237*7f2fe78bSCy Schubert 		renew_life *= 5*60;
238*7f2fe78bSCy Schubert 
239*7f2fe78bSCy Schubert     if (lifetime)
240*7f2fe78bSCy Schubert         pkrb5_get_init_creds_opt_set_tkt_life(options, lifetime);
241*7f2fe78bSCy Schubert 	pkrb5_get_init_creds_opt_set_forwardable(options,
242*7f2fe78bSCy Schubert                                              forwardable ? 1 : 0);
243*7f2fe78bSCy Schubert 	pkrb5_get_init_creds_opt_set_proxiable(options,
244*7f2fe78bSCy Schubert                                            proxiable ? 1 : 0);
245*7f2fe78bSCy Schubert 	pkrb5_get_init_creds_opt_set_renew_life(options,
246*7f2fe78bSCy Schubert                                             renew_life);
247*7f2fe78bSCy Schubert     if (addressless)
248*7f2fe78bSCy Schubert         pkrb5_get_init_creds_opt_set_address_list(options,NULL);
249*7f2fe78bSCy Schubert     else {
250*7f2fe78bSCy Schubert 		if (publicIP)
251*7f2fe78bSCy Schubert         {
252*7f2fe78bSCy Schubert             // we are going to add the public IP address specified by the user
253*7f2fe78bSCy Schubert             // to the list provided by the operating system
254*7f2fe78bSCy Schubert             krb5_address ** local_addrs=NULL;
255*7f2fe78bSCy Schubert             DWORD           netIPAddr;
256*7f2fe78bSCy Schubert 
257*7f2fe78bSCy Schubert             pkrb5_os_localaddr(ctx, &local_addrs);
258*7f2fe78bSCy Schubert             while ( local_addrs[i++] );
259*7f2fe78bSCy Schubert             addr_count = i + 1;
260*7f2fe78bSCy Schubert 
261*7f2fe78bSCy Schubert             addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
262*7f2fe78bSCy Schubert             if ( !addrs ) {
263*7f2fe78bSCy Schubert                 pkrb5_free_addresses(ctx, local_addrs);
264*7f2fe78bSCy Schubert                 assert(0);
265*7f2fe78bSCy Schubert             }
266*7f2fe78bSCy Schubert             memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
267*7f2fe78bSCy Schubert             i = 0;
268*7f2fe78bSCy Schubert             while ( local_addrs[i] ) {
269*7f2fe78bSCy Schubert                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
270*7f2fe78bSCy Schubert                 if (addrs[i] == NULL) {
271*7f2fe78bSCy Schubert                     pkrb5_free_addresses(ctx, local_addrs);
272*7f2fe78bSCy Schubert                     assert(0);
273*7f2fe78bSCy Schubert                 }
274*7f2fe78bSCy Schubert 
275*7f2fe78bSCy Schubert                 addrs[i]->magic = local_addrs[i]->magic;
276*7f2fe78bSCy Schubert                 addrs[i]->addrtype = local_addrs[i]->addrtype;
277*7f2fe78bSCy Schubert                 addrs[i]->length = local_addrs[i]->length;
278*7f2fe78bSCy Schubert                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
279*7f2fe78bSCy Schubert                 if (!addrs[i]->contents) {
280*7f2fe78bSCy Schubert                     pkrb5_free_addresses(ctx, local_addrs);
281*7f2fe78bSCy Schubert                     assert(0);
282*7f2fe78bSCy Schubert                 }
283*7f2fe78bSCy Schubert 
284*7f2fe78bSCy Schubert                 memcpy(addrs[i]->contents,local_addrs[i]->contents,
285*7f2fe78bSCy Schubert                         local_addrs[i]->length);        /* safe */
286*7f2fe78bSCy Schubert                 i++;
287*7f2fe78bSCy Schubert             }
288*7f2fe78bSCy Schubert             pkrb5_free_addresses(ctx, local_addrs);
289*7f2fe78bSCy Schubert 
290*7f2fe78bSCy Schubert             addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
291*7f2fe78bSCy Schubert             if (addrs[i] == NULL)
292*7f2fe78bSCy Schubert                 assert(0);
293*7f2fe78bSCy Schubert 
294*7f2fe78bSCy Schubert             addrs[i]->magic = KV5M_ADDRESS;
295*7f2fe78bSCy Schubert             addrs[i]->addrtype = AF_INET;
296*7f2fe78bSCy Schubert             addrs[i]->length = 4;
297*7f2fe78bSCy Schubert             addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
298*7f2fe78bSCy Schubert             if (!addrs[i]->contents)
299*7f2fe78bSCy Schubert                 assert(0);
300*7f2fe78bSCy Schubert 
301*7f2fe78bSCy Schubert             netIPAddr = htonl(publicIP);
302*7f2fe78bSCy Schubert             memcpy(addrs[i]->contents,&netIPAddr,4);
303*7f2fe78bSCy Schubert 
304*7f2fe78bSCy Schubert             pkrb5_get_init_creds_opt_set_address_list(options,addrs);
305*7f2fe78bSCy Schubert 
306*7f2fe78bSCy Schubert         }
307*7f2fe78bSCy Schubert     }
308*7f2fe78bSCy Schubert 
309*7f2fe78bSCy Schubert     code = pkrb5_get_init_creds_opt_set_out_ccache(ctx, options, cc);
310*7f2fe78bSCy Schubert     if (code)
311*7f2fe78bSCy Schubert         goto cleanup;
312*7f2fe78bSCy Schubert 
313*7f2fe78bSCy Schubert     code = pkrb5_get_init_creds_password(ctx,
314*7f2fe78bSCy Schubert                                        &my_creds,
315*7f2fe78bSCy Schubert                                        me,
316*7f2fe78bSCy Schubert                                        password, // password
317*7f2fe78bSCy Schubert                                        leash_krb5_prompter, // prompter
318*7f2fe78bSCy Schubert                                        hParent, // prompter data
319*7f2fe78bSCy Schubert                                        0, // start time
320*7f2fe78bSCy Schubert                                        0, // service name
321*7f2fe78bSCy Schubert                                        options);
322*7f2fe78bSCy Schubert     // @TODO: make this an option
323*7f2fe78bSCy Schubert     if ((!code) && (cc != defcache)) {
324*7f2fe78bSCy Schubert         code = pkrb5_cc_switch(ctx, cc);
325*7f2fe78bSCy Schubert         if (!code) {
326*7f2fe78bSCy Schubert             const char *cctype = pkrb5_cc_get_type(ctx, cc);
327*7f2fe78bSCy Schubert             if (cctype != NULL) {
328*7f2fe78bSCy Schubert                 char defname[20];
329*7f2fe78bSCy Schubert                 sprintf_s(defname, sizeof(defname), "%s:", cctype);
330*7f2fe78bSCy Schubert                 pkrb5int_cc_user_set_default_name(ctx, defname);
331*7f2fe78bSCy Schubert             }
332*7f2fe78bSCy Schubert         }
333*7f2fe78bSCy Schubert     }
334*7f2fe78bSCy Schubert  cleanup:
335*7f2fe78bSCy Schubert     if (code && cc_new) {
336*7f2fe78bSCy Schubert         // don't leave newly-generated empty ccache lying around on failure
337*7f2fe78bSCy Schubert         pkrb5_cc_destroy(ctx, cc);
338*7f2fe78bSCy Schubert         cc = NULL;
339*7f2fe78bSCy Schubert     }
340*7f2fe78bSCy Schubert     if ( addrs ) {
341*7f2fe78bSCy Schubert         for ( i=0;i<addr_count;i++ ) {
342*7f2fe78bSCy Schubert             if ( addrs[i] ) {
343*7f2fe78bSCy Schubert                 if ( addrs[i]->contents )
344*7f2fe78bSCy Schubert                     free(addrs[i]->contents);
345*7f2fe78bSCy Schubert                 free(addrs[i]);
346*7f2fe78bSCy Schubert             }
347*7f2fe78bSCy Schubert         }
348*7f2fe78bSCy Schubert     }
349*7f2fe78bSCy Schubert     if (my_creds.client == me)
350*7f2fe78bSCy Schubert 	my_creds.client = 0;
351*7f2fe78bSCy Schubert     pkrb5_free_cred_contents(ctx, &my_creds);
352*7f2fe78bSCy Schubert     if (name)
353*7f2fe78bSCy Schubert 	pkrb5_free_unparsed_name(ctx, name);
354*7f2fe78bSCy Schubert     if (me)
355*7f2fe78bSCy Schubert 	pkrb5_free_principal(ctx, me);
356*7f2fe78bSCy Schubert     if (cc)
357*7f2fe78bSCy Schubert 	pkrb5_cc_close(ctx, cc);
358*7f2fe78bSCy Schubert     if (options)
359*7f2fe78bSCy Schubert         pkrb5_get_init_creds_opt_free(ctx, options);
360*7f2fe78bSCy Schubert     if (ctx && (ctx != alt_ctx))
361*7f2fe78bSCy Schubert 	pkrb5_free_context(ctx);
362*7f2fe78bSCy Schubert     return(code);
363*7f2fe78bSCy Schubert }
364*7f2fe78bSCy Schubert 
365*7f2fe78bSCy Schubert 
366*7f2fe78bSCy Schubert /**************************************/
367*7f2fe78bSCy Schubert /* LeashKRB5destroyTicket():          */
368*7f2fe78bSCy Schubert /**************************************/
369*7f2fe78bSCy Schubert int
Leash_krb5_kdestroy(void)370*7f2fe78bSCy Schubert Leash_krb5_kdestroy(
371*7f2fe78bSCy Schubert     void
372*7f2fe78bSCy Schubert     )
373*7f2fe78bSCy Schubert {
374*7f2fe78bSCy Schubert     krb5_context		ctx;
375*7f2fe78bSCy Schubert     krb5_ccache			cache;
376*7f2fe78bSCy Schubert     krb5_error_code		rc;
377*7f2fe78bSCy Schubert 
378*7f2fe78bSCy Schubert     ctx = NULL;
379*7f2fe78bSCy Schubert     cache = NULL;
380*7f2fe78bSCy Schubert     rc = Leash_krb5_initialize(&ctx);
381*7f2fe78bSCy Schubert     if (rc)
382*7f2fe78bSCy Schubert         return(rc);
383*7f2fe78bSCy Schubert 
384*7f2fe78bSCy Schubert     if (rc = pkrb5_cc_default(ctx, &cache))
385*7f2fe78bSCy Schubert         return(rc);
386*7f2fe78bSCy Schubert 
387*7f2fe78bSCy Schubert     rc = pkrb5_cc_destroy(ctx, cache);
388*7f2fe78bSCy Schubert 
389*7f2fe78bSCy Schubert     if (ctx != NULL)
390*7f2fe78bSCy Schubert         pkrb5_free_context(ctx);
391*7f2fe78bSCy Schubert 
392*7f2fe78bSCy Schubert     return(rc);
393*7f2fe78bSCy Schubert 
394*7f2fe78bSCy Schubert }
395*7f2fe78bSCy Schubert 
396*7f2fe78bSCy Schubert krb5_error_code
Leash_krb5_cc_default(krb5_context * ctx,krb5_ccache * cache)397*7f2fe78bSCy Schubert Leash_krb5_cc_default(krb5_context *ctx, krb5_ccache *cache)
398*7f2fe78bSCy Schubert {
399*7f2fe78bSCy Schubert     krb5_error_code rc;
400*7f2fe78bSCy Schubert     krb5_flags flags;
401*7f2fe78bSCy Schubert 
402*7f2fe78bSCy Schubert     char *functionName = NULL;
403*7f2fe78bSCy Schubert     if (*cache == 0) {
404*7f2fe78bSCy Schubert         rc = pkrb5_cc_default(*ctx, cache);
405*7f2fe78bSCy Schubert         if (rc) {
406*7f2fe78bSCy Schubert             functionName = "krb5_cc_default()";
407*7f2fe78bSCy Schubert             goto on_error;
408*7f2fe78bSCy Schubert         }
409*7f2fe78bSCy Schubert     }
410*7f2fe78bSCy Schubert     flags = KRB5_TC_NOTICKET;
411*7f2fe78bSCy Schubert     rc = pkrb5_cc_set_flags(*ctx, *cache, flags);
412*7f2fe78bSCy Schubert     if (rc) {
413*7f2fe78bSCy Schubert         if (rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) {
414*7f2fe78bSCy Schubert             if (*cache != NULL && *ctx != NULL)
415*7f2fe78bSCy Schubert                 pkrb5_cc_close(*ctx, *cache);
416*7f2fe78bSCy Schubert         } else {
417*7f2fe78bSCy Schubert             functionName = "krb5_cc_set_flags()";
418*7f2fe78bSCy Schubert             goto on_error;
419*7f2fe78bSCy Schubert         }
420*7f2fe78bSCy Schubert     }
421*7f2fe78bSCy Schubert on_error:
422*7f2fe78bSCy Schubert     if (rc && functionName) {
423*7f2fe78bSCy Schubert         Leash_krb5_error(rc, functionName, 0, ctx, cache);
424*7f2fe78bSCy Schubert     }
425*7f2fe78bSCy Schubert     return rc;
426*7f2fe78bSCy Schubert }
427*7f2fe78bSCy Schubert 
428*7f2fe78bSCy Schubert /**************************************/
429*7f2fe78bSCy Schubert /* Leash_krb5_initialize():             */
430*7f2fe78bSCy Schubert /**************************************/
Leash_krb5_initialize(krb5_context * ctx)431*7f2fe78bSCy Schubert int Leash_krb5_initialize(krb5_context *ctx)
432*7f2fe78bSCy Schubert {
433*7f2fe78bSCy Schubert     LPCSTR          functionName = NULL;
434*7f2fe78bSCy Schubert     krb5_error_code	rc;
435*7f2fe78bSCy Schubert 
436*7f2fe78bSCy Schubert     if (pkrb5_init_context == NULL)
437*7f2fe78bSCy Schubert         return 1;
438*7f2fe78bSCy Schubert 
439*7f2fe78bSCy Schubert     if (*ctx == 0) {
440*7f2fe78bSCy Schubert         if (rc = (*pkrb5_init_context)(ctx)) {
441*7f2fe78bSCy Schubert             functionName = "krb5_init_context()";
442*7f2fe78bSCy Schubert             return Leash_krb5_error(rc, functionName, 0, ctx, NULL);
443*7f2fe78bSCy Schubert         }
444*7f2fe78bSCy Schubert     }
445*7f2fe78bSCy Schubert     return 0;
446*7f2fe78bSCy Schubert }
447*7f2fe78bSCy Schubert 
448*7f2fe78bSCy Schubert 
449*7f2fe78bSCy Schubert /**************************************/
450*7f2fe78bSCy Schubert /* Leash_krb5_error():           */
451*7f2fe78bSCy Schubert /**************************************/
452*7f2fe78bSCy Schubert int
Leash_krb5_error(krb5_error_code rc,LPCSTR FailedFunctionName,int FreeContextFlag,krb5_context * ctx,krb5_ccache * cache)453*7f2fe78bSCy Schubert Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
454*7f2fe78bSCy Schubert                  int FreeContextFlag, krb5_context * ctx,
455*7f2fe78bSCy Schubert                  krb5_ccache * cache)
456*7f2fe78bSCy Schubert {
457*7f2fe78bSCy Schubert #ifdef USE_MESSAGE_BOX
458*7f2fe78bSCy Schubert     char message[256];
459*7f2fe78bSCy Schubert     const char *errText;
460*7f2fe78bSCy Schubert 
461*7f2fe78bSCy Schubert     errText = perror_message(rc);
462*7f2fe78bSCy Schubert     _snprintf(message, sizeof(message),
463*7f2fe78bSCy Schubert               "%s\n(Kerberos error %ld)\n\n%s failed",
464*7f2fe78bSCy Schubert               errText,
465*7f2fe78bSCy Schubert               rc,
466*7f2fe78bSCy Schubert               FailedFunctionName);
467*7f2fe78bSCy Schubert     message[sizeof(message)-1] = 0;
468*7f2fe78bSCy Schubert 
469*7f2fe78bSCy Schubert     MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
470*7f2fe78bSCy Schubert                MB_TASKMODAL |
471*7f2fe78bSCy Schubert                MB_SETFOREGROUND);
472*7f2fe78bSCy Schubert #endif /* USE_MESSAGE_BOX */
473*7f2fe78bSCy Schubert 
474*7f2fe78bSCy Schubert     if (ctx != NULL && *ctx != NULL) {
475*7f2fe78bSCy Schubert         if (cache != NULL && *cache != NULL) {
476*7f2fe78bSCy Schubert             pkrb5_cc_close(*ctx, *cache);
477*7f2fe78bSCy Schubert             *cache = NULL;
478*7f2fe78bSCy Schubert         }
479*7f2fe78bSCy Schubert 
480*7f2fe78bSCy Schubert         if (FreeContextFlag) {
481*7f2fe78bSCy Schubert             pkrb5_free_context(*ctx);
482*7f2fe78bSCy Schubert             *ctx = NULL;
483*7f2fe78bSCy Schubert         }
484*7f2fe78bSCy Schubert     }
485*7f2fe78bSCy Schubert 
486*7f2fe78bSCy Schubert     return rc;
487*7f2fe78bSCy Schubert }
488*7f2fe78bSCy Schubert 
489*7f2fe78bSCy Schubert 
490*7f2fe78bSCy Schubert /* User Query data structures and functions */
491*7f2fe78bSCy Schubert 
492*7f2fe78bSCy Schubert struct textField {
493*7f2fe78bSCy Schubert     char * buf;                       /* Destination buffer address */
494*7f2fe78bSCy Schubert     int    len;                       /* Destination buffer length */
495*7f2fe78bSCy Schubert     char * label;                     /* Label for this field */
496*7f2fe78bSCy Schubert     char * def;                       /* Default response for this field */
497*7f2fe78bSCy Schubert     int    echo;                      /* 0 = no, 1 = yes, 2 = asterisks */
498*7f2fe78bSCy Schubert };
499*7f2fe78bSCy Schubert 
500*7f2fe78bSCy Schubert static int                mid_cnt = 0;
501*7f2fe78bSCy Schubert static struct textField * mid_tb = NULL;
502*7f2fe78bSCy Schubert 
503*7f2fe78bSCy Schubert #define ID_TEXT       150
504*7f2fe78bSCy Schubert #define ID_MID_TEXT 300
505*7f2fe78bSCy Schubert 
506*7f2fe78bSCy Schubert static BOOL CALLBACK
MultiInputDialogProc(HWND hDialog,UINT message,WPARAM wParam,LPARAM lParam)507*7f2fe78bSCy Schubert MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
508*7f2fe78bSCy Schubert {
509*7f2fe78bSCy Schubert     int i;
510*7f2fe78bSCy Schubert 
511*7f2fe78bSCy Schubert     switch ( message ) {
512*7f2fe78bSCy Schubert     case WM_INITDIALOG:
513*7f2fe78bSCy Schubert         if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
514*7f2fe78bSCy Schubert         {
515*7f2fe78bSCy Schubert             SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
516*7f2fe78bSCy Schubert             return FALSE;
517*7f2fe78bSCy Schubert         }
518*7f2fe78bSCy Schubert 		for ( i=0; i < mid_cnt ; i++ ) {
519*7f2fe78bSCy Schubert 			if (mid_tb[i].echo == 0)
520*7f2fe78bSCy Schubert 				SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
521*7f2fe78bSCy Schubert 		    else if (mid_tb[i].echo == 2)
522*7f2fe78bSCy Schubert 				SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
523*7f2fe78bSCy Schubert 		}
524*7f2fe78bSCy Schubert         return TRUE;
525*7f2fe78bSCy Schubert 
526*7f2fe78bSCy Schubert     case WM_COMMAND:
527*7f2fe78bSCy Schubert         switch ( LOWORD(wParam) ) {
528*7f2fe78bSCy Schubert         case IDOK:
529*7f2fe78bSCy Schubert             for ( i=0; i < mid_cnt ; i++ ) {
530*7f2fe78bSCy Schubert                 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
531*7f2fe78bSCy Schubert                     *mid_tb[i].buf = '\0';
532*7f2fe78bSCy Schubert             }
533*7f2fe78bSCy Schubert             /* fallthrough */
534*7f2fe78bSCy Schubert         case IDCANCEL:
535*7f2fe78bSCy Schubert             EndDialog(hDialog, LOWORD(wParam));
536*7f2fe78bSCy Schubert             return TRUE;
537*7f2fe78bSCy Schubert         }
538*7f2fe78bSCy Schubert     }
539*7f2fe78bSCy Schubert     return FALSE;
540*7f2fe78bSCy Schubert }
541*7f2fe78bSCy Schubert 
542*7f2fe78bSCy Schubert static LPWORD
lpwAlign(LPWORD lpIn)543*7f2fe78bSCy Schubert lpwAlign( LPWORD lpIn )
544*7f2fe78bSCy Schubert {
545*7f2fe78bSCy Schubert     ULONG ul;
546*7f2fe78bSCy Schubert 
547*7f2fe78bSCy Schubert     ul = (ULONG) lpIn;
548*7f2fe78bSCy Schubert     ul += 3;
549*7f2fe78bSCy Schubert     ul >>=2;
550*7f2fe78bSCy Schubert     ul <<=2;
551*7f2fe78bSCy Schubert     return (LPWORD) ul;;
552*7f2fe78bSCy Schubert }
553*7f2fe78bSCy Schubert 
554*7f2fe78bSCy Schubert /*
555*7f2fe78bSCy Schubert  * dialog widths are measured in 1/4 character widths
556*7f2fe78bSCy Schubert  * dialog height are measured in 1/8 character heights
557*7f2fe78bSCy Schubert  */
558*7f2fe78bSCy Schubert 
559*7f2fe78bSCy Schubert static LRESULT
MultiInputDialog(HINSTANCE hinst,HWND hwndOwner,char * ptext[],int numlines,int width,int tb_cnt,struct textField * tb)560*7f2fe78bSCy Schubert MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
561*7f2fe78bSCy Schubert                   char * ptext[], int numlines, int width,
562*7f2fe78bSCy Schubert                   int tb_cnt, struct textField * tb)
563*7f2fe78bSCy Schubert {
564*7f2fe78bSCy Schubert     HGLOBAL hgbl;
565*7f2fe78bSCy Schubert     LPDLGTEMPLATE lpdt;
566*7f2fe78bSCy Schubert     LPDLGITEMTEMPLATE lpdit;
567*7f2fe78bSCy Schubert     LPWORD lpw;
568*7f2fe78bSCy Schubert     LPWSTR lpwsz;
569*7f2fe78bSCy Schubert     LRESULT ret;
570*7f2fe78bSCy Schubert     int nchar, i;
571*7f2fe78bSCy Schubert     size_t pwid;
572*7f2fe78bSCy Schubert 
573*7f2fe78bSCy Schubert     hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
574*7f2fe78bSCy Schubert     if (!hgbl)
575*7f2fe78bSCy Schubert         return -1;
576*7f2fe78bSCy Schubert 
577*7f2fe78bSCy Schubert     mid_cnt = tb_cnt;
578*7f2fe78bSCy Schubert     mid_tb = tb;
579*7f2fe78bSCy Schubert 
580*7f2fe78bSCy Schubert     lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
581*7f2fe78bSCy Schubert 
582*7f2fe78bSCy Schubert     // Define a dialog box.
583*7f2fe78bSCy Schubert 
584*7f2fe78bSCy Schubert     lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
585*7f2fe78bSCy Schubert                    | DS_MODALFRAME | WS_CAPTION | DS_CENTER
586*7f2fe78bSCy Schubert                    | DS_SETFOREGROUND | DS_3DLOOK
587*7f2fe78bSCy Schubert                    | DS_SHELLFONT | DS_NOFAILCREATE;
588*7f2fe78bSCy Schubert     lpdt->cdit = numlines + (2 * tb_cnt) + 2;  // number of controls
589*7f2fe78bSCy Schubert     lpdt->x  = 10;
590*7f2fe78bSCy Schubert     lpdt->y  = 10;
591*7f2fe78bSCy Schubert     lpdt->cx = 20 + width * 4;
592*7f2fe78bSCy Schubert     lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
593*7f2fe78bSCy Schubert 
594*7f2fe78bSCy Schubert     lpw = (LPWORD) (lpdt + 1);
595*7f2fe78bSCy Schubert     *lpw++ = 0;   // no menu
596*7f2fe78bSCy Schubert     *lpw++ = 0;   // predefined dialog box class (by default)
597*7f2fe78bSCy Schubert 
598*7f2fe78bSCy Schubert     lpwsz = (LPWSTR) lpw;
599*7f2fe78bSCy Schubert     nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
600*7f2fe78bSCy Schubert     lpw   += nchar;
601*7f2fe78bSCy Schubert     *lpw++ = 8;                        // font size (points)
602*7f2fe78bSCy Schubert     lpwsz = (LPWSTR) lpw;
603*7f2fe78bSCy Schubert     nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
604*7f2fe78bSCy Schubert                                     -1, lpwsz, 128);
605*7f2fe78bSCy Schubert     lpw   += nchar;
606*7f2fe78bSCy Schubert 
607*7f2fe78bSCy Schubert     //-----------------------
608*7f2fe78bSCy Schubert     // Define an OK button.
609*7f2fe78bSCy Schubert     //-----------------------
610*7f2fe78bSCy Schubert     lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
611*7f2fe78bSCy Schubert     lpdit = (LPDLGITEMTEMPLATE) lpw;
612*7f2fe78bSCy Schubert     lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
613*7f2fe78bSCy Schubert     lpdit->dwExtendedStyle = 0;
614*7f2fe78bSCy Schubert     lpdit->x  = (lpdt->cx - 14)/4 - 20;
615*7f2fe78bSCy Schubert     lpdit->y  = 10 + (numlines + tb_cnt + 2) * 14;
616*7f2fe78bSCy Schubert     lpdit->cx = 40;
617*7f2fe78bSCy Schubert     lpdit->cy = 14;
618*7f2fe78bSCy Schubert     lpdit->id = IDOK;  // OK button identifier
619*7f2fe78bSCy Schubert 
620*7f2fe78bSCy Schubert     lpw = (LPWORD) (lpdit + 1);
621*7f2fe78bSCy Schubert     *lpw++ = 0xFFFF;
622*7f2fe78bSCy Schubert     *lpw++ = 0x0080;    // button class
623*7f2fe78bSCy Schubert 
624*7f2fe78bSCy Schubert     lpwsz = (LPWSTR) lpw;
625*7f2fe78bSCy Schubert     nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
626*7f2fe78bSCy Schubert     lpw   += nchar;
627*7f2fe78bSCy Schubert     *lpw++ = 0;           // no creation data
628*7f2fe78bSCy Schubert 
629*7f2fe78bSCy Schubert     //-----------------------
630*7f2fe78bSCy Schubert     // Define an Cancel button.
631*7f2fe78bSCy Schubert     //-----------------------
632*7f2fe78bSCy Schubert     lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
633*7f2fe78bSCy Schubert     lpdit = (LPDLGITEMTEMPLATE) lpw;
634*7f2fe78bSCy Schubert     lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
635*7f2fe78bSCy Schubert     lpdit->dwExtendedStyle = 0;
636*7f2fe78bSCy Schubert     lpdit->x  = (lpdt->cx - 14)*3/4 - 20;
637*7f2fe78bSCy Schubert     lpdit->y  = 10 + (numlines + tb_cnt + 2) * 14;
638*7f2fe78bSCy Schubert     lpdit->cx = 40;
639*7f2fe78bSCy Schubert     lpdit->cy = 14;
640*7f2fe78bSCy Schubert     lpdit->id = IDCANCEL;  // CANCEL button identifier
641*7f2fe78bSCy Schubert 
642*7f2fe78bSCy Schubert     lpw = (LPWORD) (lpdit + 1);
643*7f2fe78bSCy Schubert     *lpw++ = 0xFFFF;
644*7f2fe78bSCy Schubert     *lpw++ = 0x0080;    // button class
645*7f2fe78bSCy Schubert 
646*7f2fe78bSCy Schubert     lpwsz = (LPWSTR) lpw;
647*7f2fe78bSCy Schubert     nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
648*7f2fe78bSCy Schubert     lpw   += nchar;
649*7f2fe78bSCy Schubert     *lpw++ = 0;           // no creation data
650*7f2fe78bSCy Schubert 
651*7f2fe78bSCy Schubert     /* Add controls for preface data */
652*7f2fe78bSCy Schubert     for ( i=0; i<numlines; i++) {
653*7f2fe78bSCy Schubert         /*-----------------------
654*7f2fe78bSCy Schubert          * Define a static text control.
655*7f2fe78bSCy Schubert          *-----------------------*/
656*7f2fe78bSCy Schubert         lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
657*7f2fe78bSCy Schubert         lpdit = (LPDLGITEMTEMPLATE) lpw;
658*7f2fe78bSCy Schubert         lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
659*7f2fe78bSCy Schubert         lpdit->dwExtendedStyle = 0;
660*7f2fe78bSCy Schubert         lpdit->x  = 10;
661*7f2fe78bSCy Schubert         lpdit->y  = 10 + i * 14;
662*7f2fe78bSCy Schubert         lpdit->cx = strlen(ptext[i]) * 4 + 10;
663*7f2fe78bSCy Schubert         lpdit->cy = 14;
664*7f2fe78bSCy Schubert         lpdit->id = ID_TEXT + i;  // text identifier
665*7f2fe78bSCy Schubert 
666*7f2fe78bSCy Schubert         lpw = (LPWORD) (lpdit + 1);
667*7f2fe78bSCy Schubert         *lpw++ = 0xFFFF;
668*7f2fe78bSCy Schubert         *lpw++ = 0x0082;                         // static class
669*7f2fe78bSCy Schubert 
670*7f2fe78bSCy Schubert         lpwsz = (LPWSTR) lpw;
671*7f2fe78bSCy Schubert         nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
672*7f2fe78bSCy Schubert                                          -1, lpwsz, 2*width);
673*7f2fe78bSCy Schubert         lpw   += nchar;
674*7f2fe78bSCy Schubert         *lpw++ = 0;           // no creation data
675*7f2fe78bSCy Schubert     }
676*7f2fe78bSCy Schubert 
677*7f2fe78bSCy Schubert     for ( i=0, pwid = 0; i<tb_cnt; i++) {
678*7f2fe78bSCy Schubert         if ( pwid < strlen(tb[i].label) )
679*7f2fe78bSCy Schubert             pwid = strlen(tb[i].label);
680*7f2fe78bSCy Schubert     }
681*7f2fe78bSCy Schubert 
682*7f2fe78bSCy Schubert     for ( i=0; i<tb_cnt; i++) {
683*7f2fe78bSCy Schubert         /* Prompt */
684*7f2fe78bSCy Schubert         /*-----------------------
685*7f2fe78bSCy Schubert          * Define a static text control.
686*7f2fe78bSCy Schubert          *-----------------------*/
687*7f2fe78bSCy Schubert         lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
688*7f2fe78bSCy Schubert         lpdit = (LPDLGITEMTEMPLATE) lpw;
689*7f2fe78bSCy Schubert         lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
690*7f2fe78bSCy Schubert         lpdit->dwExtendedStyle = 0;
691*7f2fe78bSCy Schubert         lpdit->x  = 10;
692*7f2fe78bSCy Schubert         lpdit->y  = 10 + (numlines + i + 1) * 14;
693*7f2fe78bSCy Schubert         lpdit->cx = pwid * 4;
694*7f2fe78bSCy Schubert         lpdit->cy = 14;
695*7f2fe78bSCy Schubert         lpdit->id = ID_TEXT + numlines + i;  // text identifier
696*7f2fe78bSCy Schubert 
697*7f2fe78bSCy Schubert         lpw = (LPWORD) (lpdit + 1);
698*7f2fe78bSCy Schubert         *lpw++ = 0xFFFF;
699*7f2fe78bSCy Schubert         *lpw++ = 0x0082;                         // static class
700*7f2fe78bSCy Schubert 
701*7f2fe78bSCy Schubert         lpwsz = (LPWSTR) lpw;
702*7f2fe78bSCy Schubert         nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
703*7f2fe78bSCy Schubert                                      -1, lpwsz, 128);
704*7f2fe78bSCy Schubert         lpw   += nchar;
705*7f2fe78bSCy Schubert         *lpw++ = 0;           // no creation data
706*7f2fe78bSCy Schubert 
707*7f2fe78bSCy Schubert         /*-----------------------
708*7f2fe78bSCy Schubert          * Define an edit control.
709*7f2fe78bSCy Schubert          *-----------------------*/
710*7f2fe78bSCy Schubert         lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
711*7f2fe78bSCy Schubert         lpdit = (LPDLGITEMTEMPLATE) lpw;
712*7f2fe78bSCy Schubert         lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
713*7f2fe78bSCy Schubert         lpdit->dwExtendedStyle = 0;
714*7f2fe78bSCy Schubert         lpdit->x  = 10 + (pwid + 1) * 4;
715*7f2fe78bSCy Schubert         lpdit->y  = 10 + (numlines + i + 1) * 14;
716*7f2fe78bSCy Schubert         lpdit->cx = (width - (pwid + 1)) * 4;
717*7f2fe78bSCy Schubert         lpdit->cy = 14;
718*7f2fe78bSCy Schubert         lpdit->id = ID_MID_TEXT + i;             // identifier
719*7f2fe78bSCy Schubert 
720*7f2fe78bSCy Schubert         lpw = (LPWORD) (lpdit + 1);
721*7f2fe78bSCy Schubert         *lpw++ = 0xFFFF;
722*7f2fe78bSCy Schubert         *lpw++ = 0x0081;                         // edit class
723*7f2fe78bSCy Schubert 
724*7f2fe78bSCy Schubert         lpwsz = (LPWSTR) lpw;
725*7f2fe78bSCy Schubert         nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
726*7f2fe78bSCy Schubert                                      -1, lpwsz, 128);
727*7f2fe78bSCy Schubert         lpw   += nchar;
728*7f2fe78bSCy Schubert         *lpw++ = 0;           // no creation data
729*7f2fe78bSCy Schubert     }
730*7f2fe78bSCy Schubert 
731*7f2fe78bSCy Schubert     GlobalUnlock(hgbl);
732*7f2fe78bSCy Schubert     ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
733*7f2fe78bSCy Schubert 							hwndOwner, (DLGPROC) MultiInputDialogProc);
734*7f2fe78bSCy Schubert     GlobalFree(hgbl);
735*7f2fe78bSCy Schubert 
736*7f2fe78bSCy Schubert     switch ( ret ) {
737*7f2fe78bSCy Schubert     case 0:     /* Timeout */
738*7f2fe78bSCy Schubert         return -1;
739*7f2fe78bSCy Schubert     case IDOK:
740*7f2fe78bSCy Schubert         return 1;
741*7f2fe78bSCy Schubert     case IDCANCEL:
742*7f2fe78bSCy Schubert         return 0;
743*7f2fe78bSCy Schubert     default: {
744*7f2fe78bSCy Schubert         char buf[256];
745*7f2fe78bSCy Schubert         sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
746*7f2fe78bSCy Schubert         MessageBox(hwndOwner,
747*7f2fe78bSCy Schubert                     buf,
748*7f2fe78bSCy Schubert                     "GetLastError()",
749*7f2fe78bSCy Schubert                     MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
750*7f2fe78bSCy Schubert         return -1;
751*7f2fe78bSCy Schubert     }
752*7f2fe78bSCy Schubert     }
753*7f2fe78bSCy Schubert }
754*7f2fe78bSCy Schubert 
755*7f2fe78bSCy Schubert static int
multi_field_dialog(HWND hParent,char * preface,int n,struct textField tb[])756*7f2fe78bSCy Schubert multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
757*7f2fe78bSCy Schubert {
758*7f2fe78bSCy Schubert 	extern HINSTANCE hLeashInst;
759*7f2fe78bSCy Schubert     size_t maxwidth = 0;
760*7f2fe78bSCy Schubert     int numlines = 0;
761*7f2fe78bSCy Schubert     size_t len;
762*7f2fe78bSCy Schubert     char * plines[16], *p = preface ? preface : "";
763*7f2fe78bSCy Schubert     int i;
764*7f2fe78bSCy Schubert 
765*7f2fe78bSCy Schubert     for ( i=0; i<16; i++ )
766*7f2fe78bSCy Schubert         plines[i] = NULL;
767*7f2fe78bSCy Schubert 
768*7f2fe78bSCy Schubert     while (*p && numlines < 16) {
769*7f2fe78bSCy Schubert         plines[numlines++] = p;
770*7f2fe78bSCy Schubert         for ( ;*p && *p != '\r' && *p != '\n'; p++ );
771*7f2fe78bSCy Schubert         if ( *p == '\r' && *(p+1) == '\n' ) {
772*7f2fe78bSCy Schubert             *p++ = '\0';
773*7f2fe78bSCy Schubert             p++;
774*7f2fe78bSCy Schubert         } else if ( *p == '\n' ) {
775*7f2fe78bSCy Schubert             *p++ = '\0';
776*7f2fe78bSCy Schubert         }
777*7f2fe78bSCy Schubert         if ( strlen(plines[numlines-1]) > maxwidth )
778*7f2fe78bSCy Schubert             maxwidth = strlen(plines[numlines-1]);
779*7f2fe78bSCy Schubert     }
780*7f2fe78bSCy Schubert 
781*7f2fe78bSCy Schubert     for ( i=0;i<n;i++ ) {
782*7f2fe78bSCy Schubert         len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
783*7f2fe78bSCy Schubert         if ( maxwidth < len )
784*7f2fe78bSCy Schubert             maxwidth = len;
785*7f2fe78bSCy Schubert     }
786*7f2fe78bSCy Schubert 
787*7f2fe78bSCy Schubert     return(MultiInputDialog(hLeashInst, hParent, plines, numlines, maxwidth, n, tb));
788*7f2fe78bSCy Schubert }
789*7f2fe78bSCy Schubert 
790*7f2fe78bSCy Schubert static krb5_error_code KRB5_CALLCONV
leash_krb5_prompter(krb5_context context,void * data,const char * name,const char * banner,int num_prompts,krb5_prompt prompts[])791*7f2fe78bSCy Schubert leash_krb5_prompter( krb5_context context,
792*7f2fe78bSCy Schubert 					 void *data,
793*7f2fe78bSCy Schubert 					 const char *name,
794*7f2fe78bSCy Schubert 					 const char *banner,
795*7f2fe78bSCy Schubert 					 int num_prompts,
796*7f2fe78bSCy Schubert 					 krb5_prompt prompts[])
797*7f2fe78bSCy Schubert {
798*7f2fe78bSCy Schubert     krb5_error_code     errcode = 0;
799*7f2fe78bSCy Schubert     int                 i;
800*7f2fe78bSCy Schubert     struct textField * tb = NULL;
801*7f2fe78bSCy Schubert     int    len = 0, blen=0, nlen=0;
802*7f2fe78bSCy Schubert 	HWND hParent = (HWND)data;
803*7f2fe78bSCy Schubert 
804*7f2fe78bSCy Schubert     if (name)
805*7f2fe78bSCy Schubert         nlen = strlen(name)+2;
806*7f2fe78bSCy Schubert 
807*7f2fe78bSCy Schubert     if (banner)
808*7f2fe78bSCy Schubert         blen = strlen(banner)+2;
809*7f2fe78bSCy Schubert 
810*7f2fe78bSCy Schubert     tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
811*7f2fe78bSCy Schubert     if ( tb != NULL ) {
812*7f2fe78bSCy Schubert         int ok;
813*7f2fe78bSCy Schubert         memset(tb,0,sizeof(struct textField) * num_prompts);
814*7f2fe78bSCy Schubert         for ( i=0; i < num_prompts; i++ ) {
815*7f2fe78bSCy Schubert             tb[i].buf = prompts[i].reply->data;
816*7f2fe78bSCy Schubert             tb[i].len = prompts[i].reply->length;
817*7f2fe78bSCy Schubert             tb[i].label = prompts[i].prompt;
818*7f2fe78bSCy Schubert             tb[i].def = NULL;
819*7f2fe78bSCy Schubert             tb[i].echo = (prompts[i].hidden ? 2 : 1);
820*7f2fe78bSCy Schubert         }
821*7f2fe78bSCy Schubert 
822*7f2fe78bSCy Schubert         ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
823*7f2fe78bSCy Schubert         if ( ok ) {
824*7f2fe78bSCy Schubert             for ( i=0; i < num_prompts; i++ )
825*7f2fe78bSCy Schubert                 prompts[i].reply->length = strlen(prompts[i].reply->data);
826*7f2fe78bSCy Schubert         } else
827*7f2fe78bSCy Schubert             errcode = -2;
828*7f2fe78bSCy Schubert     }
829*7f2fe78bSCy Schubert 
830*7f2fe78bSCy Schubert     if ( tb )
831*7f2fe78bSCy Schubert         free(tb);
832*7f2fe78bSCy Schubert     if (errcode) {
833*7f2fe78bSCy Schubert         for (i = 0; i < num_prompts; i++) {
834*7f2fe78bSCy Schubert             memset(prompts[i].reply->data, 0, prompts[i].reply->length);
835*7f2fe78bSCy Schubert         }
836*7f2fe78bSCy Schubert     }
837*7f2fe78bSCy Schubert     return errcode;
838*7f2fe78bSCy Schubert }
839