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