1 // Module name: krb5routines.c
7 /* _WIN32_WINNT must be 0x0501 or greater to pull in definition of
8 * all required LSA data types when the Vista SDK NtSecAPI.h is used.
11 #define _WIN32_WINNT 0x0501
13 #if _WIN32_WINNT < 0x0501
15 #define _WIN32_WINNT 0x0501
26 /* Private Include files */
29 #include "leash-int.h"
31 #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
33 char *GetTicketFlag(krb5_creds *cred)
41 if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
44 if (cred->ticket_flags & TKT_FLG_FORWARDED)
47 if (cred->ticket_flags & TKT_FLG_PROXIABLE)
50 if (cred->ticket_flags & TKT_FLG_PROXY)
53 if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
56 if (cred->ticket_flags & TKT_FLG_POSTDATED)
59 if (cred->ticket_flags & TKT_FLG_INVALID)
62 if (cred->ticket_flags & TKT_FLG_RENEWABLE)
65 if (cred->ticket_flags & TKT_FLG_INITIAL)
68 if (cred->ticket_flags & TKT_FLG_HW_AUTH)
71 if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
88 #if defined(NO_KRB5) || defined(NO_KRB4)
92 krb5_error_code code = 0;
94 krb5_principal me = 0;
95 krb5_principal server = 0;
96 krb5_creds *v5creds = 0;
99 CREDENTIALS * v4creds = NULL;
100 static int init_ets = 1;
102 if (!pkrb5_init_context ||
105 !pkrb524_convert_creds_kdc)
108 v4creds = (CREDENTIALS *) malloc(sizeof(CREDENTIALS));
109 memset((char *) v4creds, 0, sizeof(CREDENTIALS));
111 memset((char *) &increds, 0, sizeof(increds));
113 From this point on, we can goto cleanup because increds is
123 code = pkrb5_init_context(&ctx);
124 if (code) goto cleanup;
127 code = pkrb5_cc_default(ctx, &cc);
128 if (code) goto cleanup;
131 pkrb524_init_ets(ctx);
135 if (code = pkrb5_cc_get_principal(ctx, cc, &me))
138 if ((code = pkrb5_build_principal(ctx,
140 krb5_princ_realm(ctx, me)->length,
141 krb5_princ_realm(ctx, me)->data,
143 krb5_princ_realm(ctx, me)->data,
149 increds.server = server;
150 increds.times.endtime = 0;
151 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
152 if ((code = pkrb5_get_credentials(ctx, 0,
159 if ((icode = pkrb524_convert_creds_kdc(ctx,
165 /* initialize ticket cache */
166 if ((icode = pkrb_in_tkt(v4creds->pname, v4creds->pinst, v4creds->realm)
170 /* stash ticket, session key, etc. for future use */
171 if ((icode = pkrb_save_credentials(v4creds->service,
177 &(v4creds->ticket_st),
178 v4creds->issue_date))) {
183 memset(v4creds, 0, sizeof(v4creds));
187 pkrb5_free_creds(ctx, v5creds);
189 if (increds.client == me)
191 if (increds.server == server)
193 pkrb5_free_cred_contents(ctx, &increds);
195 pkrb5_free_principal(ctx, server);
198 pkrb5_free_principal(ctx, me);
200 pkrb5_cc_close(ctx, cc);
202 if (ctx && (ctx != alt_ctx)) {
203 pkrb5_free_context(ctx);
205 return !(code || icode);
211 LeashKRB5_renew(void)
216 krb5_error_code code = 0;
217 krb5_context ctx = 0;
219 krb5_principal me = 0;
220 krb5_principal server = 0;
222 krb5_data *realm = 0;
224 if ( !pkrb5_init_context )
227 memset(&my_creds, 0, sizeof(krb5_creds));
229 code = pkrb5_init_context(&ctx);
230 if (code) goto cleanup;
232 code = pkrb5_cc_default(ctx, &cc);
233 if (code) goto cleanup;
235 code = pkrb5_cc_get_principal(ctx, cc, &me);
236 if (code) goto cleanup;
238 realm = krb5_princ_realm(ctx, me);
240 code = pkrb5_build_principal_ext(ctx, &server,
241 realm->length,realm->data,
242 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
243 realm->length,realm->data,
245 if ( code ) goto cleanup;
247 my_creds.client = me;
248 my_creds.server = server;
250 #ifdef KRB5_TC_NOTICKET
251 pkrb5_cc_set_flags(ctx, cc, 0);
253 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
254 #ifdef KRB5_TC_NOTICKET
255 pkrb5_cc_set_flags(ctx, cc, KRB5_TC_NOTICKET);
258 if ( code != KRB5KDC_ERR_ETYPE_NOSUPP ||
259 code != KRB5_KDC_UNREACH)
260 Leash_krb5_error(code, "krb5_get_renewed_creds()", 0, &ctx, &cc);
264 code = pkrb5_cc_initialize(ctx, cc, me);
265 if (code) goto cleanup;
267 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
268 if (code) goto cleanup;
271 if (my_creds.client == me)
273 if (my_creds.server == server)
275 pkrb5_free_cred_contents(ctx, &my_creds);
277 pkrb5_free_principal(ctx, me);
279 pkrb5_free_principal(ctx, server);
281 pkrb5_cc_close(ctx, cc);
283 pkrb5_free_context(ctx);
289 static krb5_error_code KRB5_CALLCONV
290 leash_krb5_prompter( krb5_context context,
295 krb5_prompt prompts[]);
300 krb5_context alt_ctx,
302 char *principal_name,
304 krb5_deltat lifetime,
307 krb5_deltat renew_life,
315 krb5_error_code code = 0;
316 krb5_context ctx = 0;
317 krb5_ccache cc = 0, defcache = 0;
318 krb5_principal me = 0;
321 krb5_get_init_creds_opt * options = NULL;
322 krb5_address ** addrs = NULL;
323 int i = 0, addr_count = 0;
325 const char * deftype = NULL;
327 if (!pkrb5_init_context)
330 memset(&my_creds, 0, sizeof(my_creds));
338 code = pkrb5_init_context(&ctx);
339 if (code) goto cleanup;
342 code = pkrb5_get_init_creds_opt_alloc(ctx, &options);
343 if (code) goto cleanup;
345 code = pkrb5_cc_default(ctx, &defcache);
346 if (code) goto cleanup;
348 code = pkrb5_parse_name(ctx, principal_name, &me);
349 if (code) goto cleanup;
351 deftype = pkrb5_cc_get_type(ctx, defcache);
352 if (me != NULL && pkrb5_cc_support_switch(ctx, deftype)) {
353 /* Use an existing cache for the specified principal if we can. */
354 code = pkrb5_cc_cache_match(ctx, me, &cc);
355 if (code != 0 && code != KRB5_CC_NOTFOUND)
357 if (code == KRB5_CC_NOTFOUND) {
358 code = pkrb5_cc_new_unique(ctx, deftype, NULL, &cc);
363 pkrb5_cc_close(ctx, defcache);
368 code = pkrb5_unparse_name(ctx, me, &name);
369 if (code) goto cleanup;
372 lifetime = Leash_get_default_lifetime();
380 pkrb5_get_init_creds_opt_set_tkt_life(options, lifetime);
381 pkrb5_get_init_creds_opt_set_forwardable(options,
382 forwardable ? 1 : 0);
383 pkrb5_get_init_creds_opt_set_proxiable(options,
385 pkrb5_get_init_creds_opt_set_renew_life(options,
388 pkrb5_get_init_creds_opt_set_address_list(options,NULL);
392 // we are going to add the public IP address specified by the user
393 // to the list provided by the operating system
394 krb5_address ** local_addrs=NULL;
397 pkrb5_os_localaddr(ctx, &local_addrs);
398 while ( local_addrs[i++] );
401 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
403 pkrb5_free_addresses(ctx, local_addrs);
406 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
408 while ( local_addrs[i] ) {
409 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
410 if (addrs[i] == NULL) {
411 pkrb5_free_addresses(ctx, local_addrs);
415 addrs[i]->magic = local_addrs[i]->magic;
416 addrs[i]->addrtype = local_addrs[i]->addrtype;
417 addrs[i]->length = local_addrs[i]->length;
418 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
419 if (!addrs[i]->contents) {
420 pkrb5_free_addresses(ctx, local_addrs);
424 memcpy(addrs[i]->contents,local_addrs[i]->contents,
425 local_addrs[i]->length); /* safe */
428 pkrb5_free_addresses(ctx, local_addrs);
430 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
431 if (addrs[i] == NULL)
434 addrs[i]->magic = KV5M_ADDRESS;
435 addrs[i]->addrtype = AF_INET;
436 addrs[i]->length = 4;
437 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
438 if (!addrs[i]->contents)
441 netIPAddr = htonl(publicIP);
442 memcpy(addrs[i]->contents,&netIPAddr,4);
444 pkrb5_get_init_creds_opt_set_address_list(options,addrs);
449 code = pkrb5_get_init_creds_opt_set_out_ccache(ctx, options, cc);
453 code = pkrb5_get_init_creds_password(ctx,
456 password, // password
457 leash_krb5_prompter, // prompter
458 hParent, // prompter data
462 // @TODO: make this an option
463 if ((!code) && (cc != defcache)) {
464 code = pkrb5_cc_switch(ctx, cc);
466 const char *cctype = pkrb5_cc_get_type(ctx, cc);
467 if (cctype != NULL) {
469 sprintf_s(defname, sizeof(defname), "%s:", cctype);
470 pkrb5int_cc_user_set_default_name(ctx, defname);
475 if (code && cc_new) {
476 // don't leave newly-generated empty ccache lying around on failure
477 pkrb5_cc_destroy(ctx, cc);
481 for ( i=0;i<addr_count;i++ ) {
483 if ( addrs[i]->contents )
484 free(addrs[i]->contents);
489 if (my_creds.client == me)
491 pkrb5_free_cred_contents(ctx, &my_creds);
493 pkrb5_free_unparsed_name(ctx, name);
495 pkrb5_free_principal(ctx, me);
497 pkrb5_cc_close(ctx, cc);
499 pkrb5_get_init_creds_opt_free(ctx, options);
500 if (ctx && (ctx != alt_ctx))
501 pkrb5_free_context(ctx);
507 /**************************************/
508 /* LeashKRB5destroyTicket(): */
509 /**************************************/
524 rc = Leash_krb5_initialize(&ctx);
528 if (rc = pkrb5_cc_default(ctx, &cache))
531 rc = pkrb5_cc_destroy(ctx, cache);
534 pkrb5_free_context(ctx);
542 Leash_krb5_cc_default(krb5_context *ctx, krb5_ccache *cache)
547 char *functionName = NULL;
549 rc = pkrb5_cc_default(*ctx, cache);
551 functionName = "krb5_cc_default()";
555 #ifdef KRB5_TC_NOTICKET
556 flags = KRB5_TC_NOTICKET;
558 rc = pkrb5_cc_set_flags(*ctx, *cache, flags);
560 if (rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) {
561 if (*cache != NULL && *ctx != NULL)
562 pkrb5_cc_close(*ctx, *cache);
564 functionName = "krb5_cc_set_flags()";
569 if (rc && functionName) {
570 Leash_krb5_error(rc, functionName, 0, ctx, cache);
575 /**************************************/
576 /* Leash_krb5_initialize(): */
577 /**************************************/
578 int Leash_krb5_initialize(krb5_context *ctx)
584 LPCSTR functionName = NULL;
587 if (pkrb5_init_context == NULL)
591 if (rc = (*pkrb5_init_context)(ctx)) {
592 functionName = "krb5_init_context()";
593 return Leash_krb5_error(rc, functionName, 0, ctx, NULL);
601 /**************************************/
602 /* Leash_krb5_error(): */
603 /**************************************/
605 Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
606 int FreeContextFlag, krb5_context * ctx,
612 #ifdef USE_MESSAGE_BOX
616 errText = perror_message(rc);
617 _snprintf(message, sizeof(message),
618 "%s\n(Kerberos error %ld)\n\n%s failed",
622 message[sizeof(message)-1] = 0;
624 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
627 #endif /* USE_MESSAGE_BOX */
629 if (ctx != NULL && *ctx != NULL) {
630 if (cache != NULL && *cache != NULL) {
631 pkrb5_cc_close(*ctx, *cache);
635 if (FreeContextFlag) {
636 pkrb5_free_context(*ctx);
648 Leash_ms2mit(BOOL save_creds)
653 krb5_context kcontext = 0;
654 krb5_error_code code;
655 krb5_ccache ccache=0;
656 krb5_ccache mslsa_ccache=0;
658 krb5_cc_cursor cursor=0;
659 krb5_principal princ = 0;
662 if ( !pkrb5_init_context )
665 if (code = pkrb5_init_context(&kcontext))
668 if (code = pkrb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache))
672 if (code = pkrb5_cc_get_principal(kcontext, mslsa_ccache, &princ))
675 if (code = pkrb5_cc_default(kcontext, &ccache))
678 if (code = pkrb5_cc_initialize(kcontext, ccache, princ))
681 if (code = pkrb5_cc_copy_creds(kcontext, mslsa_ccache, ccache))
686 /* Enumerate tickets from cache looking for an initial ticket */
687 if ((code = pkrb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor)))
690 while (!(code = pkrb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds)))
692 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
694 pkrb5_free_cred_contents(kcontext, &creds);
697 pkrb5_free_cred_contents(kcontext, &creds);
699 pkrb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);
704 pkrb5_free_principal(kcontext, princ);
706 pkrb5_cc_close(kcontext, ccache);
708 pkrb5_cc_close(kcontext, mslsa_ccache);
710 pkrb5_free_context(kcontext);
717 /* User Query data structures and functions */
720 char * buf; /* Destination buffer address */
721 int len; /* Destination buffer length */
722 char * label; /* Label for this field */
723 char * def; /* Default response for this field */
724 int echo; /* 0 = no, 1 = yes, 2 = asterisks */
727 static int mid_cnt = 0;
728 static struct textField * mid_tb = NULL;
731 #define ID_MID_TEXT 300
734 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
740 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
742 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
745 for ( i=0; i < mid_cnt ; i++ ) {
746 if (mid_tb[i].echo == 0)
747 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
748 else if (mid_tb[i].echo == 2)
749 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
754 switch ( LOWORD(wParam) ) {
756 for ( i=0; i < mid_cnt ; i++ ) {
757 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
758 *mid_tb[i].buf = '\0';
762 EndDialog(hDialog, LOWORD(wParam));
770 lpwAlign( LPWORD lpIn )
782 * dialog widths are measured in 1/4 character widths
783 * dialog height are measured in 1/8 character heights
787 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
788 char * ptext[], int numlines, int width,
789 int tb_cnt, struct textField * tb)
793 LPDLGITEMTEMPLATE lpdit;
800 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
807 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
809 // Define a dialog box.
811 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
812 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
813 | DS_SETFOREGROUND | DS_3DLOOK
814 | DS_SHELLFONT | DS_NOFAILCREATE;
815 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
818 lpdt->cx = 20 + width * 4;
819 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
821 lpw = (LPWORD) (lpdt + 1);
822 *lpw++ = 0; // no menu
823 *lpw++ = 0; // predefined dialog box class (by default)
825 lpwsz = (LPWSTR) lpw;
826 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
828 *lpw++ = 8; // font size (points)
829 lpwsz = (LPWSTR) lpw;
830 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
834 //-----------------------
835 // Define an OK button.
836 //-----------------------
837 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
838 lpdit = (LPDLGITEMTEMPLATE) lpw;
839 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
840 lpdit->dwExtendedStyle = 0;
841 lpdit->x = (lpdt->cx - 14)/4 - 20;
842 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
845 lpdit->id = IDOK; // OK button identifier
847 lpw = (LPWORD) (lpdit + 1);
849 *lpw++ = 0x0080; // button class
851 lpwsz = (LPWSTR) lpw;
852 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
854 *lpw++ = 0; // no creation data
856 //-----------------------
857 // Define an Cancel button.
858 //-----------------------
859 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
860 lpdit = (LPDLGITEMTEMPLATE) lpw;
861 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
862 lpdit->dwExtendedStyle = 0;
863 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
864 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
867 lpdit->id = IDCANCEL; // CANCEL button identifier
869 lpw = (LPWORD) (lpdit + 1);
871 *lpw++ = 0x0080; // button class
873 lpwsz = (LPWSTR) lpw;
874 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
876 *lpw++ = 0; // no creation data
878 /* Add controls for preface data */
879 for ( i=0; i<numlines; i++) {
880 /*-----------------------
881 * Define a static text control.
882 *-----------------------*/
883 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
884 lpdit = (LPDLGITEMTEMPLATE) lpw;
885 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
886 lpdit->dwExtendedStyle = 0;
888 lpdit->y = 10 + i * 14;
889 lpdit->cx = strlen(ptext[i]) * 4 + 10;
891 lpdit->id = ID_TEXT + i; // text identifier
893 lpw = (LPWORD) (lpdit + 1);
895 *lpw++ = 0x0082; // static class
897 lpwsz = (LPWSTR) lpw;
898 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
901 *lpw++ = 0; // no creation data
904 for ( i=0, pwid = 0; i<tb_cnt; i++) {
905 if ( pwid < strlen(tb[i].label) )
906 pwid = strlen(tb[i].label);
909 for ( i=0; i<tb_cnt; i++) {
911 /*-----------------------
912 * Define a static text control.
913 *-----------------------*/
914 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
915 lpdit = (LPDLGITEMTEMPLATE) lpw;
916 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
917 lpdit->dwExtendedStyle = 0;
919 lpdit->y = 10 + (numlines + i + 1) * 14;
920 lpdit->cx = pwid * 4;
922 lpdit->id = ID_TEXT + numlines + i; // text identifier
924 lpw = (LPWORD) (lpdit + 1);
926 *lpw++ = 0x0082; // static class
928 lpwsz = (LPWSTR) lpw;
929 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
932 *lpw++ = 0; // no creation data
934 /*-----------------------
935 * Define an edit control.
936 *-----------------------*/
937 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
938 lpdit = (LPDLGITEMTEMPLATE) lpw;
939 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
940 lpdit->dwExtendedStyle = 0;
941 lpdit->x = 10 + (pwid + 1) * 4;
942 lpdit->y = 10 + (numlines + i + 1) * 14;
943 lpdit->cx = (width - (pwid + 1)) * 4;
945 lpdit->id = ID_MID_TEXT + i; // identifier
947 lpw = (LPWORD) (lpdit + 1);
949 *lpw++ = 0x0081; // edit class
951 lpwsz = (LPWSTR) lpw;
952 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
955 *lpw++ = 0; // no creation data
959 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
960 hwndOwner, (DLGPROC) MultiInputDialogProc);
964 case 0: /* Timeout */
972 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
973 MessageBox(hwndOwner,
976 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
983 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
985 extern HINSTANCE hLeashInst;
989 char * plines[16], *p = preface ? preface : "";
992 for ( i=0; i<16; i++ )
995 while (*p && numlines < 16) {
996 plines[numlines++] = p;
997 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
998 if ( *p == '\r' && *(p+1) == '\n' ) {
1001 } else if ( *p == '\n' ) {
1004 if ( strlen(plines[numlines-1]) > maxwidth )
1005 maxwidth = strlen(plines[numlines-1]);
1008 for ( i=0;i<n;i++ ) {
1009 len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
1010 if ( maxwidth < len )
1014 return(MultiInputDialog(hLeashInst, hParent, plines, numlines, maxwidth, n, tb));
1017 static krb5_error_code KRB5_CALLCONV
1018 leash_krb5_prompter( krb5_context context,
1023 krb5_prompt prompts[])
1025 krb5_error_code errcode = 0;
1027 struct textField * tb = NULL;
1028 int len = 0, blen=0, nlen=0;
1029 HWND hParent = (HWND)data;
1032 nlen = strlen(name)+2;
1035 blen = strlen(banner)+2;
1037 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
1040 memset(tb,0,sizeof(struct textField) * num_prompts);
1041 for ( i=0; i < num_prompts; i++ ) {
1042 tb[i].buf = prompts[i].reply->data;
1043 tb[i].len = prompts[i].reply->length;
1044 tb[i].label = prompts[i].prompt;
1046 tb[i].echo = (prompts[i].hidden ? 2 : 1);
1049 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
1051 for ( i=0; i < num_prompts; i++ )
1052 prompts[i].reply->length = strlen(prompts[i].reply->data);
1060 for (i = 0; i < num_prompts; i++) {
1061 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
1066 #endif /* NO_KRB5 */