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