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