]> arthur.barton.de Git - netatalk.git/blob - etc/uams/uams_krb4/uams_krb4.c
remove gcc warnings and cleanup inline mess
[netatalk.git] / etc / uams / uams_krb4 / uams_krb4.c
1 /*
2  * $Id: uams_krb4.c,v 1.6.10.1.2.2 2008-11-25 15:16:33 didg Exp $
3  *
4  * Copyright (c) 1990,1993 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #if defined( KRB ) || defined( UAM_AFSKRB )
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif /* HAVE_UNISTD_H */
16 #ifdef HAVE_FCNTL_H
17 #include <fcntl.h>
18 #endif /* HAVE_FCNTL_H */
19 #include <sys/types.h>
20 #include <sys/time.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <limits.h>
24
25 /* STDC check */
26 #if STDC_HEADERS
27 #include <string.h>
28 #else /* STDC_HEADERS */
29 #ifndef HAVE_STRCHR
30 #define strchr index
31 #define strrchr index
32 #endif /* HAVE_STRCHR */
33 char *strchr (), *strrchr ();
34 #ifndef HAVE_MEMCPY
35 #define memcpy(d,s,n) bcopy ((s), (d), (n))
36 #define memmove(d,s,n) bcopy ((s), (d), (n))
37 #endif /* ! HAVE_MEMCPY */
38 #endif /* STDC_HEADERS */
39
40 #include <ctype.h>
41 #include <pwd.h>
42 #include <atalk/logger.h>
43 #include <netinet/in.h>
44 #include <des.h>
45 #include <krb.h>
46 #if 0
47 #include <prot.h>
48 #endif /* 0 */
49
50 #include <netatalk/endian.h>
51 #include <atalk/afp.h>
52 #include <atalk/compat.h>
53 #include <atalk/util.h>
54 #include <atalk/uam.h>
55
56 static C_Block                  seskey;
57 static Key_schedule             seskeysched;
58
59 static char             realm[ REALM_SZ ];
60
61 #ifdef UAM_AFSKRB
62 static int              validseskey = 0;
63 static int              logged = 0;
64 static char             *tktfile;
65 static char             instance[ INST_SZ ], name[ ANAME_SZ ];
66 #endif /* UAM_AFSKRB */
67
68 #ifdef AFS
69 #include <afs/stds.h>
70 #include <rx/rxkad.h>
71 #include <afs/afs.h>
72 #include <afs/venus.h>
73 #include <afs/afsint.h>
74
75 char *ka_LocalCell();
76
77 struct ClearToken {
78     int32_t AuthHandle;
79     char HandShakeKey[8];
80     int32_t ViceId;
81     int32_t BeginTimestamp;
82     int32_t EndTimestamp;
83 };
84 #endif /* AFS */
85
86
87 #ifdef KRB
88
89 static void lcase( p )
90     char        *p;
91 {
92     for (; *p; p++ ) {
93         if ( isupper( *p )) {
94             *p = tolower( *p );
95         }
96     }
97     return;
98 }
99
100 static void ucase( p )
101     char        *p;
102 {
103     for (; *p; p++ ) {
104         if ( islower( *p )) {
105             *p = toupper( *p );
106         }
107     }
108     return;
109 }
110
111 #define KRB4CMD_HELO    1
112 #define KRB4RPL_REALM   2
113 #define KRB4WRT_SESS    3
114 #define KRB4RPL_DONE    4
115 #define KRB4RPL_PRINC   5
116 #define KRB4WRT_TOKEN   6
117 #define KRB4WRT_SKIP    7
118 #define KRB4RPL_DONEMUT 8
119 #define KRB4CMD_SESS    9
120 #define KRB4CMD_TOKEN   10
121 #define KRB4CMD_SKIP    11
122
123 static int krb4_login(void *obj, struct passwd **uam_pwd,
124                       char *ibuf, int ibuflen,
125                       char *rbuf, int *rbuflen )
126 {
127     char                *p;
128     char                *username;
129     struct passwd       *pwd;
130     u_int16_t           len;
131     KTEXT_ST            tkt;
132     static AUTH_DAT     ad;
133     int                 rc, ulen, proto;
134     char                inst[ 40 ], princ[ 40 ];
135
136     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
137       return AFPERR_MISC;
138
139     if (uam_afpserver_option(obj, UAM_OPTION_PROTOCOL, &proto, NULL) < 0)
140       return AFPERR_MISC;
141
142     switch( *ibuf ) {
143         case KRB4CMD_SESS:
144             LOG(log_info, logtype_default, "krb4_login: KRB4CMD_SESS" );
145             ++ibuf;
146             p = ibuf;
147             memcpy( &len, p, sizeof( u_int16_t ));
148             tkt.length = ntohs( len );
149             p += sizeof( u_int16_t );
150
151             if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
152                 *rbuflen = 0;
153                 LOG(log_info, logtype_default, "krb4_login: tkt.length = %d", tkt.length );
154                 return( AFPERR_BADUAM );
155             }
156
157             memcpy( tkt.dat, p, tkt.length );
158             p += tkt.length;
159
160             strcpy( inst, "*" );
161
162             switch( proto ) {
163                 case AFPPROTO_ASP:
164                     strcpy( princ, "afpserver" );
165                     break;
166                 case AFPPROTO_DSI:
167                     strcpy( princ, "rcmd" );
168                     break;
169             }
170
171             if( (rc = krb_rd_req( &tkt, princ, inst, 0, &ad, "" )) 
172                 != RD_AP_OK ) {
173                 LOG(log_error, logtype_default, 
174                         "krb4_login: krb_rd_req(): %s", krb_err_txt[ rc ] );
175                 *rbuflen = 0;
176                 return( AFPERR_BADUAM );
177             }
178
179             LOG(log_info, logtype_default, "krb4_login: %s.%s@%s", ad.pname, ad.pinst, 
180                 ad.prealm );
181             strcpy( realm, ad.prealm );
182             memcpy( seskey, ad.session, sizeof( C_Block ) );
183             key_sched( (C_Block *)seskey, seskeysched );
184
185             strncpy( username, ad.pname, ulen );
186
187             p = rbuf;
188
189 #ifdef AFS
190             *p = KRB4RPL_DONE;  /* XXX */
191             *rbuflen = 1;
192
193             if (( pwd = uam_getname( obj, ad.pname, strlen(ad.pname) )) == NULL ) {
194                 return AFPERR_PARAM;
195             }
196 /*
197             if (uam_checkuser( pwd ) < 0) {
198                 return AFPERR_NOTAUTH;
199             }
200 */
201             *uam_pwd = pwd;
202             return( AFP_OK ); /* Should this be AFPERR_AUTHCONT? */
203 #else /* AFS */
204             /* get principals */
205             *p++ = KRB4RPL_PRINC;
206             len = strlen( realm );
207             *p++ = len + 1;
208             *p++ = '@';
209             strcpy( p, realm );
210             p += len + 1;
211             break;
212 #endif /* AFS */
213         case KRB4CMD_HELO:
214             p = rbuf;
215             if (krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
216                 LOG(log_error, logtype_default, "krb4_login: can't get local realm!" );
217                 return( AFPERR_NOTAUTH );
218             }
219             *p++ = KRB4RPL_REALM;
220             *p++ = 1;
221             len = strlen( realm );
222             *p++ = len;
223             strcpy( p, realm );
224             p += len + 1;
225             break;
226
227         default:
228             *rbuflen = 0;
229             LOG(log_info, logtype_default, "krb4_login: bad command %d", *ibuf );
230             return( AFPERR_NOTAUTH );
231     }
232
233 #ifdef AFS
234     if ( setpag() < 0 ) {
235         *rbuflen = 0;
236         LOG(log_error, logtype_default, "krb_login: setpag: %s", strerror(errno) );
237         return( AFPERR_BADUAM );
238     }
239 #endif /*AFS*/
240
241     *rbuflen = p - rbuf;
242     return( AFPERR_AUTHCONT );
243 }
244
245 static int krb4_action( void *v1, void *v2, const int i )
246 {
247         return i;
248 }
249
250 /*
251    I have a hunch that problems might arise on platforms 
252    with non-16bit short's and non-32bit int's
253 */
254 static int krb4_logincont(void *obj, struct passwd **uam_pwd,
255                           char *ibuf, int ibuflen,
256                           char *rbuf, int *rbuflen)
257 {
258     static struct passwd        *pwd;
259     KTEXT_ST            tkt;
260     static AUTH_DAT     ad;
261     int                 rc;
262     u_int16_t           len;
263     char                *p, *username, *servername;
264     CREDENTIALS         cr;
265 #ifdef AFS
266     struct ViceIoctl    vi;
267     struct ClearToken   ct;
268 #endif /* AFS */
269     char                buf[ 1024 ];
270     int                 aint, ulen, snlen;
271
272     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
273       return AFPERR_MISC;
274
275     if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen) < 0)
276       return AFPERR_MISC;
277
278     ibuf++;
279     switch ( rc = *ibuf++ ) {
280         case KRB4CMD_TOKEN :
281 #ifdef AFS
282             p = buf;
283             memcpy( &len, ibuf, sizeof( u_int16_t ) );
284             ibuf += sizeof( len );
285             len = ntohs( len );
286             aint = len;
287             memcpy( p, &aint, sizeof( int ) );
288             p += sizeof( int );
289             memcpy( p, ibuf, len );
290             pcbc_encrypt( (C_Block *)p, (C_Block *)p, len, seskeysched,
291                 seskey, DECRYPT );
292             p += len;
293             ibuf += len;
294
295             memcpy( &len, ibuf, sizeof( u_int16_t ) );
296             ibuf += sizeof( u_int16_t ) );
297             len = ntohs( len );
298
299             if ( len != sizeof( struct ClearToken ) ) {
300                 LOG(log_error, logtype_default, "krb4_logincont: token too short" );
301                 *rbuflen = 0;
302                 return( AFPERR_BADUAM );
303             }
304             memcpy( &ct, ibuf, len );
305
306             pcbc_encrypt( (C_Block *)&ct, (C_Block *)&ct, len, 
307                 seskeysched, seskey, DECRYPT );
308
309             aint = sizeof( struct ClearToken );
310             memcpy( p, &aint, sizeof( int ) );
311             p += sizeof( int );
312             memcpy( p, &ct, sizeof( struct ClearToken ) );
313             p += sizeof( struct ClearToken );
314
315             aint = 0;
316             memcpy( p, &aint, sizeof( int ) );
317             p += sizeof( int );
318
319             lcase( realm );
320             strcpy( p, realm );
321             p += strlen( realm ) + 1;
322
323             vi.in = buf;
324             vi.in_size = p - buf;
325             vi.out = buf;
326             vi.out_size = sizeof( buf );
327
328             if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
329                 LOG(log_error, logtype_default, "krb4_logincont: pioctl: %s", strerror(errno) );
330                 *rbuflen = 0;
331                 return( AFPERR_BADUAM );
332             }
333             /* FALL THROUGH */
334
335         case KRB4CMD_SKIP:
336             p = rbuf;
337             *p = KRB4RPL_DONE;  /* XXX */
338             *rbuflen = 1;
339
340             if (( pwd = uam_getname( obj, username, strlen(username) ) ) == NULL ) {
341                 return( AFPERR_NOTAUTH );
342             }
343 /*
344             if (uam_checkuser(pwd) < 0) {
345                 return AFPERR_NOTAUTH;
346             }
347 */
348             *uam_pwd = pwd;
349             return( AFP_OK );
350 #endif /* AFS */
351         default:
352             /* read in the rest */
353             if (uam_afp_read(obj, rbuf, rbuflen, krb4_action) < 0)
354                 return AFPERR_PARAM;
355
356             p = rbuf;
357             switch ( rc = *p++ ) {
358                 case KRB4WRT_SESS :
359                     memcpy( &len, p, sizeof( len ));
360                     tkt.length = ntohs( len );
361                     p += sizeof( short );
362
363                     if ( tkt.length <= 0 || tkt.length > MAX_KTXT_LEN ) {
364                         return( AFPERR_BADUAM );
365                     }
366                     memcpy( tkt.dat, p, tkt.length );
367                     p += tkt.length;
368
369                     if (( rc = krb_rd_req( &tkt, "afpserver", servername, 
370                         0, &ad, "" )) != RD_AP_OK ) {
371                         LOG(log_error, logtype_default, "krb4_logincont: krb_rd_req(): %s", krb_err_txt[ rc ] );
372                         return( AFPERR_BADUAM );
373                     }
374
375                     LOG(log_info, logtype_default, "krb4_login: %s.%s@%s", ad.pname, 
376                         ad.pinst, ad.prealm );
377                     memcpy(realm, ad.prealm, sizeof(realm));
378                     memcpy(seskey, ad.session, sizeof( C_Block ));
379                     key_sched((C_Block *) seskey, seskeysched );
380
381                     strncpy(username, ad.pname, ulen);
382
383                     p = rbuf;
384 #ifndef AFS
385                     *p = KRB4RPL_DONE;  /* XXX */
386                     *rbuflen = 1;
387
388                     if (( pwd = uam_getname( obj, ad.pname, strlen(ad.pname) )) 
389                         == NULL ) {
390                         return( AFPERR_PARAM );
391                     }
392                     *uam_pwd = pwd;
393                     return AFP_OK;
394 #else /* ! AFS */
395                     /* get principals */
396                     *p++ = KRB4RPL_PRINC;
397                     len = strlen( realm );
398                     *p++ = len + 1;
399                     *p++ = '@';
400                     strcpy( p, realm );
401                     p += len + 1;
402                     *rbuflen = p - rbuf;
403                     return( AFPERR_AUTHCONT );
404
405                 case KRB4WRT_TOKEN :
406                     memcpy( &len, p, sizeof( len ));
407                     len = ntohs( len );
408                     p += sizeof( len );
409                     memcpy( &cr, p, len );
410
411                     pcbc_encrypt((C_Block *)&cr, (C_Block *)&cr, len, 
412                         seskeysched, seskey, DES_DECRYPT );
413
414                     p = buf;
415                     cr.ticket_st.length = ntohl( cr.ticket_st.length );
416                     memcpy( p, &cr.ticket_st.length, sizeof( int ));
417                     p += sizeof( int );
418                     memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
419                     p += cr.ticket_st.length;
420
421                     ct.AuthHandle = ntohl( cr.kvno );
422                     memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
423                     ct.ViceId = 0;
424                     ct.BeginTimestamp = ntohl( cr.issue_date );
425                     ct.EndTimestamp = krb_life_to_time( ntohl( cr.issue_date ),
426                     ntohl( cr.lifetime ));
427
428                     aint = sizeof( struct ClearToken );
429                     memcpy( p, &aint, sizeof( int ));
430                     p += sizeof( int );
431                     memcpy( p, &ct, sizeof( struct ClearToken ));
432                     p += sizeof( struct ClearToken );
433
434                     aint = 0;
435                     memcpy( p, &aint, sizeof( int ));
436                     p += sizeof( int );
437
438                     lcase( realm );
439                     strcpy( p, realm );
440                     p += strlen( realm ) + 1;
441
442                     vi.in = buf;
443                     vi.in_size = p - buf;
444                     vi.out = buf;
445                     vi.out_size = sizeof( buf );
446                     if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
447                         LOG(log_error, logtype_default, "krb4_logincont: pioctl: %s", strerror(errno) );
448                         return( AFPERR_BADUAM );
449                     }
450                     /* FALL THROUGH */
451
452                 case KRB4WRT_SKIP :
453                     p = rbuf;
454                     *p = KRB4RPL_DONE;  /* XXX */
455                     *rbuflen = 1;
456
457                     if (( pwd = uam_getname( obj, ad.pname, strlen(ad.pname) )) 
458                         == NULL ) {
459                         return( AFPERR_PARAM );
460                     }
461                     *uam_pwd = pwd;
462                     return AFP_OK;
463 #endif /*AFS*/
464
465                 default:
466                     LOG(log_info, logtype_default, "krb4_logincont: bad command %d", rc );
467                     *rbuflen = 0;
468                     return( AFPERR_NOTAUTH );
469                     break;
470             }
471             break;
472     }
473 }
474
475 #endif /* KRB */
476
477
478 #ifdef AFS
479 #include <rx/rxkad.h>
480 #include <afs/afsint.h>
481
482 char *ka_LocalCell();
483
484 static void
485 addrealm(realm,cells)
486     char *realm;
487         char ***cells;
488 {
489     char **ptr;
490         int temp;
491
492         ptr= *cells;
493
494     for(;*ptr != 0 ;ptr++)
495         if(!strcmp(realm,*ptr))
496             return;
497
498         temp=ptr- *cells;
499         *cells=(char**)realloc(*cells,((2+temp)*sizeof(char*)));
500         ptr= *cells+temp;
501
502     *ptr=(char*)malloc(strlen(realm)+1);
503     strcpy(*ptr++,realm);
504         *ptr=0;
505     return;
506 }
507
508 static int kcheckuser(pwd,passwd)
509         struct passwd *pwd;
510         char *passwd;
511 {
512         int32_t code;
513         char *instance="";
514         char realm[MAXKTCREALMLEN];
515         char lorealm[MAXKTCREALMLEN];
516         char *cell;
517         Date lifetime=MAXKTCTICKETLIFETIME;
518         int rval;
519         char **cells=(char **)malloc(sizeof(char*));
520         char *temp;
521         int rc,cellNum;
522         struct ktc_principal serviceName;
523
524         *cells=0;
525
526         code = ka_Init(0);
527
528         {
529                 char *temp,*temp1;
530                 temp=(char*)malloc(strlen(pwd->pw_dir)+1);
531                 strcpy(temp,pwd->pw_dir);
532                 temp1=temp;
533                 temp=strtok(temp,"/");
534                 temp=strtok('\0',"/");
535                 ka_CellToRealm(temp,realm,0);
536                 addrealm(realm,&cells);
537                 free(temp1);
538         }
539
540         setpag();
541         authenticate(cells,pwd->pw_name,passwd);
542         cellNum=0;
543         rc=ktc_ListTokens(cellNum,&cellNum,&serviceName);
544         if(rc)
545                 rval=1;
546         else{
547                 rval=0;
548         }
549
550         return(rval);
551 }
552
553 static void authenticate(cells,name,passwd)
554         char **cells;
555         char *name;
556         char *passwd;
557 {
558         char **ptr=cells;
559         char *errorstring;
560
561         while(*ptr){
562             ka_UserAuthenticate(name,/*instance*/"",/*cell*/*ptr++,
563                     passwd,/*setpag*/0,&errorstring);
564         }
565 }
566 #endif /* AFS */
567
568 #if defined( UAM_AFSKRB ) && defined( AFS )
569 static int afskrb_login(void *obj, struct passwd *uam_pwd,
570                         char *ibuf, int ibuflen, 
571                         char *rbuf, int *rbuflen )
572 {
573     KTEXT_ST    authent, rpkt;
574     CREDENTIALS cr;
575     char        *p, *q, *username, servername;
576     int         len, rc, whoserealm, ulen, snlen;
577     short       slen;
578
579     *rbuflen = 0;
580     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, &ulen) < 0)
581       return AFPERR_MISC;
582
583     if (uam_afpserver_option(obj, UAM_OPTION_HOSTNAME, &servername, &snlen ) < 0)
584       return AFPERR_MISC;
585     
586     len = (unsigned char) *ibuf++;
587     ibuf[ len ] = '\0';
588     if (( p = strchr( ibuf, '@' )) != NULL ) {
589         *p++ = '\0';
590         strcpy( realm, p );
591         ucase( realm );
592         whoserealm = 0;
593     } else {
594         if ( krb_get_lrealm( realm, 1 ) != KSUCCESS ) {
595             return AFPERR_BADUAM;
596         }
597         whoserealm = 1;
598     }
599     if (( p = strchr( ibuf, '.' )) != NULL ) {
600         *p++ = '\0';
601         strcpy( instance, p );
602     } else {
603         *instance = '\0';
604     }
605     strcpy( name, ibuf );
606     /*
607      * We don't have the session key, yet. Get one.
608      */
609     p = rbuf;
610     if ( validseskey == 0 ) {
611         if ( setpag() < 0 ) {
612             LOG(log_error, logtype_default, "krb_login: setpag: %s", strerror(errno) );
613             return AFPERR_BADUAM;
614         }
615         krb_set_tkt_string(( tktfile = mktemp( _PATH_AFPTKT )));
616         if (( rc =  krb_get_svc_in_tkt( "afpserver", servername, realm,
617                 TICKET_GRANTING_TICKET, realm, 255, KEYFILE )) != INTK_OK ) {
618             LOG(log_error, logtype_default, "krb_login: can't get ticket-granting-ticket" );
619             return (( whoserealm ) ? AFPERR_BADUAM : AFPERR_PARAM );
620         }
621         if ( krb_mk_req( &authent, name, instance, realm, 0 ) != KSUCCESS ) {
622             return ( AFPERR_PARAM );
623         }
624         if ( krb_get_cred( name, instance, realm, &cr ) != KSUCCESS ) {
625             return ( AFPERR_BADUAM );
626         }
627
628         if ( unlink( tktfile ) < 0 ) {
629             LOG(log_error, logtype_default, "krb_login: unlink %s: %s", tktfile, strerror(errno) );
630             return ( AFPERR_BADUAM );
631         }
632
633         memcpy( seskey, cr.session, sizeof( C_Block ));
634         key_sched((C_Block *) seskey, seskeysched );
635         validseskey = 1;
636         strncpy(username, name, ulen);
637
638         memcpy( p, authent.dat, authent.length );
639         p += authent.length;
640     }
641
642     if ( kuam_get_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
643             realm, 255, &rpkt ) != INTK_OK ) {
644         return ( AFPERR_PARAM );
645     }
646
647
648     q = (char *)rpkt.dat;
649     *p++ = *q++;
650     *p++ = *q++;
651     while ( *q++ )
652         ;
653     while ( *q++ )
654         ;
655     while ( *q++ )
656         ;
657     q += 10;
658
659     len = strlen( realm );
660     strcpy( p, realm );
661     p += len + 1;
662     memcpy( &slen, q, sizeof( short ));
663     memcpy( p, &slen, sizeof( short ));
664     p += sizeof( short );
665     q += sizeof( short );
666     memcpy( p, q, slen );
667     p += slen;
668
669     *rbuflen = p - rbuf;
670     return( AFPERR_AUTHCONT );
671 }
672
673 static int afskrb_logincont(void *obj, struct passwd *uam_pwd,
674                             char *ibuf, int ibuflen, 
675                             char *rbuf, int *rbuflen )
676 {
677     CREDENTIALS         cr;
678     struct ViceIoctl    vi;
679     struct ClearToken   ct;
680     struct passwd       *pwd;
681     char                buf[ 1024 ], *p;
682     int                 aint;
683     short               clen;
684
685     *rbuflen = 0;
686     if (uam_afpserver_option(obj, UAM_OPTION_USERNAME, &username, NULL) < 0)
687       return AFPERR_MISC;
688     
689     ibuf += 2;
690     memcpy( &clen, ibuf, sizeof( short ));
691     clen = ntohs( clen );
692     ibuf += sizeof( short );
693
694     pcbc_encrypt((C_Block *)ibuf, (C_Block *)ibuf,
695             clen, seskeysched, seskey, DES_DECRYPT );
696     if ( kuam_set_in_tkt( name, instance, realm, TICKET_GRANTING_TICKET,
697             realm, ibuf ) != INTK_OK ) {
698         return ( AFPERR_PARAM );
699     }
700
701     if ( get_ad_tkt( "afs", "", realm, 255 ) != KSUCCESS ) {
702         return ( AFPERR_PARAM );
703     }
704     if ( krb_get_cred( "afs", "", realm, &cr ) != KSUCCESS ) {
705         return ( AFPERR_PARAM );
706     }
707
708     p = buf;
709     memcpy( p, &cr.ticket_st.length, sizeof( int ));
710     p += sizeof( int );
711     memcpy( p, cr.ticket_st.dat, cr.ticket_st.length );
712     p += cr.ticket_st.length;
713
714     ct.AuthHandle = cr.kvno;
715     memcpy( ct.HandShakeKey, cr.session, sizeof( cr.session ));
716     ct.ViceId = 0;
717     ct.BeginTimestamp = cr.issue_date;
718     /* ct.EndTimestamp = cr.issue_date + ( cr.lifetime * 5 * 60 ); */
719     ct.EndTimestamp = krb_life_to_time( cr.issue_date, cr.lifetime );
720
721     aint = sizeof( struct ClearToken );
722     memcpy( p, &aint, sizeof( int ));
723     p += sizeof( int );
724     memcpy( p, &ct, sizeof( struct ClearToken ));
725     p += sizeof( struct ClearToken );
726
727     aint = 0;
728     memcpy( p, &aint, sizeof( int ));
729     p += sizeof( int );
730
731     lcase( realm );
732     strcpy( p, realm );
733     p += strlen( realm ) + 1;
734
735     vi.in = buf;
736     vi.in_size = p - buf;
737     vi.out = buf;
738     vi.out_size = sizeof( buf );
739     if ( pioctl( 0, VIOCSETTOK, &vi, 0 ) < 0 ) {
740         LOG(log_error, logtype_default, "krb_logincont: pioctl: %s", strerror(errno) );
741         return ( AFPERR_BADUAM );
742     }
743
744     if ( unlink( tktfile ) < 0 ) {
745         LOG(log_error, logtype_default, "krb_logincont: %s: %s", tktfile, strerror(errno) );
746         return ( AFPERR_BADUAM );
747     }
748
749     if (( pwd = uam_getname( obj, username, strlen(username) )) == NULL ) {
750         return ( AFPERR_PARAM );
751     }
752
753     if ( logged == 0 ) {
754         logged = 1;
755         LOG(log_info, logtype_default, "authenticated %s.%s@%s", name, instance, realm );
756         *uam_pwd = pwd;
757         return AFP_OK;
758     }
759     LOG(log_info, logtype_default, "re-authenticated %s.%s@%s", name, instance, realm );
760     return( AFP_OK );
761 }
762 #endif /* UAM_AFSKRB AFS */
763
764 static int uam_setup(const char *path)
765 {
766 #ifdef KRB
767    uam_register(UAM_SERVER_LOGIN, path, "Kerberos IV", krb4_login, 
768                 krb4_logincont, NULL);
769    /* uam_afpserver_action(); */
770 #endif /* KRB */
771 #ifdef UAM_AFSKRB
772    uam_register(UAM_SERVER_LOGIN, path, "AFS Kerberos", afskrb_login, 
773                 afskrb_logincont, NULL);
774    /* uam_afpserver_action(); */
775 #endif /* UAM_AFSKRB */
776    return 0;
777 }
778
779 static void uam_cleanup(void)
780 {
781 #ifdef KRB
782    /* uam_afpserver_action(); */
783    uam_unregister(UAM_SERVER_LOGIN, "Kerberos IV");
784 #endif
785 #ifdef UAM_AFSKRB
786    /* uam_afpserver_action(); */
787    uam_unregister(UAM_SERVER_LOGIN, "AFS Kerberos");
788 #endif
789 }
790
791 UAM_MODULE_EXPORT struct uam_export uams_krb4 = {
792   UAM_MODULE_SERVER,
793   UAM_MODULE_VERSION,
794   uam_setup, uam_cleanup
795 };
796
797 #endif /* KRB or UAM_AFSKRB */
798